Python基础+刷廖雪峰教程笔记(一)——字符串、列表元组集合、函数

由于在深度学习的路上,发现自己两年前学习的python有些遗忘,在面向对象这一块尤其不熟悉,故刷一遍廖雪峰老师的官方教程,梳理一下遗漏的知识点。

参考网址:https://www.liaoxuefeng.com/wiki/1016959663602400

1.默认字符不转义

如果字符串里面有很多字符都需要转义,就需要加很多\,为了简化,Python还允许用r’‘表示’'内部的字符串默认不转义。

demo1:

print('\\\t\\')
print(r'\\\t\\')#Python允许用r''表示''内部的字符串默认不转义

out1:

\	\
\\\t\\

2.除了\n的换行

demo2:

print('''line1
line2
line3''')

out2:

line1
line2
line3

3.字符编码问题

在这里插入代码片

ord()函数获取字符的整数表示;
chr()函数把编码转换为对应的字符。

demo3:

print(ord('A'))
print(ord('邓'))
print(chr(66))#不用加引号
print(chr(20216))
print('\u4e2d\u6587')

out3:

65
37011
B
仸
中文

由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。

Python对bytes类型的数据用带b前缀的单引号或双引号表示。

demo4:

>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

纯英文的str可以用ASCII编码为bytes,内容是一样的,含有中文的str可以用UTF-8编码为bytes。含有中文的str无法用ASCII编码,因为中文编码的范围超过了ASCII编码的范围,Python会报错。

反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法。

demo5:

>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'
#如果bytes中只有一小部分无效的字节,可以传入errors='ignore'忽略错误的字节
>>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
'中'

4.len()函数

len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字节数。

demo6:

a = len(b'ABC')
print(a)

b = len(b'\xe4\xb8\xad\xe6\x96\x87')
print(b)

c = len('中文'.encode('utf-8'))#转为byte
print(c)

out6:

3
6
6

1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节。

5.字符串的格式化

在这里插入图片描述
demo7:

print('Hi, I am your %s' % 'father')# %s永远起作用,可以把任何数据类型转换为字符串
print('Hi, I am %d years old' % 22)#整数不用加引号
print('I have %d %s' % (5, 'apple'))#多个变量
print('%.2f' % 3.1415926) #格式化输出
print( 'growth rate: %d %%' % 7)#%是一个普通字符则需要转义,用%%来表示一个%

out7:

Hi, I am your father
Hi, I am 22 years old
I have 5 apple
3.14
growth rate: 7 %

f-string的方法:

使用以f开头的字符串,称之为f-string,它和普通字符串不同之处在于,字符串如果包含{xxx},就会以对应的变量替换.

demo8:

#python 3.6以上才支持这种方法
r = 2.5
s = 3.14 * r ** 2
print(f'The area of a circle with radius {r} is {s:.2f}')

out8:

The area of a circle with radius 2.5 is 19.62

6.删除列表中的元素

demo9:

li = ['a', 'b', 'c', 'd']
li.pop(2)#删除索引位置为2的元素,即c;不指定则删除最后一个元素
print(li)

out9:

['a', 'b', 'd']

7.定义只有一个元素的tuple

demo10:

t1 = (1)
print(t1)

t2 = (1,)#必须加逗号,不然默认小括号运算
print(t2)

out10:

1
(1,)

注意:tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的。

8.set

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。

经常用来元素去重。

要创建一个set,需要提供一个list作为输入集合

demo11:

#创建一个set
s1 = set([1, 2, 3])
print(s1)
#set中无重复元素,重复元素自动过滤
s2 = set([1, 1, 2, 2, 3, 3])
print(s2)
#通过add(key)添加元素
s1.add(4)
print(s1)
#通过remove(key)删除元素
s1.remove(1)
print(s1)

out11:

{1, 2, 3}
{1, 2, 3}
{1, 2, 3, 4}
{2, 3, 4}

9.函数取别名

函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”。

demo12:

a = abs # 变量a指向abs函数
res = a(-1) # 所以也可以通过a调用abs函数
print(res)

out12:

1

10.整数转十六进制

demo13:

n1 = 255
n2 = 1000

print(hex(n1))
print(hex(n2))

out13:

0xff 
0x3e8 

11.空函数

如果想定义一个什么事也不做的空函数,可以用pass语句。pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

或者用在if条件判断语句中

demo14:

def nop():
    pass

12.函数的默认参数

默认参数可以简化函数的调用。使得输入一个参数也可行,而不会报错。

注意:

1、必选参数在前,默认参数在后,否则Python的解释器会报错;

2、当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。

demo15:

def power(x, n=2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s

print(power(5))
print(power(5, 3))

out15:

25
125

另外:默认参数必须指向不变对象!

demo16:

def add_end(L=[]):
    L.append('END')
    return L

#正常调用
res1 = add_end([1, 2, 3])
print(res1)

#使用默认参数
print(add_end())
print(add_end())
print(add_end())

#Python函数在定义的时候,默认参数L的值就被计算出来了,即[],
#因为默认参数L也是一个变量,它指向对象[],
#每次调用该函数,如果改变了L的内容,
#则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了

#修改如下:
def new_add_end(L=None):#使用None这个不变对象
    if L is None:
        L = []
    L.append('END')
    return L

print('-' * 50)
print(new_add_end())
print(new_add_end())
print(new_add_end())

out16:

[1, 2, 3, 'END']
['END']
['END', 'END']
['END', 'END', 'END']
--------------------------------------------------
['END']
['END']
['END']

13.函数的可变参数

在参数前面加一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数。

demo17:

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

print(calc(1, 2))
print(calc())

#传入的本身就是个list或者tuple
nums = [1, 2, 3]
print(calc(*nums))#*nums表示把nums这个list的所有元素作为可变参数传进去

out17:

5
0
14

14.函数的关键词参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。

demo18:

def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

#只传入必选参数
res1 = person('Michael', 30)
print(res1)

#传入任意个数的关键字参数
res2 = person('Bob', 35, city='Beijing')
print(res2)
res3 = person('Adam', 45, gender='M', job='Engineer')
print(res3)

#传入的本身就是一个字典
extra = {'city': 'Beijing', 'job': 'Engineer'}
res4 = person('Jack', 24, **extra)
print(res4)

'''
**extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,
kw将获得一个dict,
注意kw获得的dict是extra的一份拷贝,
对kw的改动不会影响到函数外的extra.
'''

其实不用先赋值给res,再打印。

因为函数本身就有打印输出,而由于函数无return返回值,打印出来只会是None

out18:

name: Michael age: 30 other: {}
None
name: Bob age: 35 other: {'city': 'Beijing'}
None
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
None
name: Jack age: 24 other: {'job': 'Engineer', 'city': 'Beijing'}
None

命名关键词:限制关键字参数的名字。

demo19:

def person(name, age, *, city, job): # 只接收city和job作为关键字参数,*后面的参数被视为命名关键字参数
    print(name, age, city, job)

#调用
person('Jack', 24, city='Beijing', job='Engineer')

#如果函数定义中已经有了一个可变参数
#后面跟着的命名关键字参数就不再需要一个特殊分隔符*
def person_v2(name, age, *args, city, job):
    print(name, age, args, city, job)

#命名关键字参数必须传入参数名,不然报错
person_v2('Jack', 24, city = 'Beijing', job = 'Engineer')

#命名关键字参数可以有缺省值,从而简化调用
def person_v3(name, age, *, city='Shenzhen', job):
    print(name, age, city, job)

person_v3('Jack', 24, job='Engineer')


out19:

Jack 24 Beijing Engineer
Jack 24 () Beijing Engineer
Jack 24 Shenzhen Engineer

用命名关键字参数时,要特别注意,如果没有可变参数,就必须加一个作为特殊分隔符。如果缺少,Python解释器将无法识别位置参数和命名关键字参数。

15.参数组合问题

参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

demo20:

def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

#只用到了必选参数
f1(1, 2)
#必选参数和默认参数
f1(1, 2, c=3)
#必选、默认、可变参数(本例中为a和b两个)
f1(1, 2, 3, 'a', 'b')
#必选、默认、可变、关键词参数(x=99)
f1(1, 2, 3, 'a', 'b', x=99)
#必选,默认没给参数为默认的0,命名关键词
f2(1, 2, d=99, ext=None)

#通过一个tuple和dict,可以调用上述函数
args1 = (1, 2, 3, 4)
kw1 = {'d': 99, 'x': '#'}
f1(*args1, **kw1)

args2 = (1, 2, 3)
kw2 = {'d': 88, 'x': '#'}
f2(*args2, **kw2)

out20:

a = 1 b = 2 c = 0 args = () kw = {}
a = 1 b = 2 c = 3 args = () kw = {}
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
a = 1 b = 2 c = 3 args = (4,) kw = {'x': '#', 'd': 99}
a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}

虽然可以组合多达5种参数,但不要同时使用太多的组合,否则函数接口的可理解性很差。

16.递归函数

使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

demo21:

def fact(n):
    return fact_iter(n, 1)

def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)

out21:

#fact(5)对应的fact_iter(5, 1)的调用如下:
===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值