赞
踩
- print() 可以输出数字、字符串、表达式;
- 换行/不换行输出;
- 将数据输出到文件中;
- 转义字符。
# 输出字符串 print('hello world') # 输出数字 print(520) print(98.5) # 输出表达式 print(3+1) # 将数据输出到文件中 fp = open('D:/text.txt','a+') # a+:如果文件不存在就创建,存在就在文件内容后面继续追加 print("hello world",file = fp) fp.close() #不换行输出 print('hello','world','Python') # 转义字符 print('hello\nworld') print('hello\tworld') print('helloooo\tworld') # \b:退格 print('hello\bworld') # world将hello覆盖了 print('hello\rworld') print('http:\\\\www.baidu.com') print('老师说:\'大家好\'') # r/R 是原字符,不希望字符串中的转义字符起作用,就用原字符。最后一个字符不能是反斜杠 print(r'hello\nworld')
- 对于单个字符的编码,Python提供了以下两个函数:
1) chr(i):用来返回整数i所对应的Unicode字符。
2) ord():用来返回对应字符的ascii码。
# ASCII
print(chr(20056))
print(ord('乘'))
- 如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。
1) bytes类型的数据用带b前缀的单引号或双引号表示,如 x=b’ABC’。
2) 以Unicode表示的str通过encode()方法可以编码为指定的bytes。
(1) 纯英文的str可以用ASCII编码为bytes,内容是一样的。
(2) 含有中文的str可以用utf-8编码为bytes。
(3) 含有中文的str无法用ASCII编码,因为中文编码的范围超过了ASCII编码的范围。
print('ABC'.encode('ascii'))
print('中国'.encode('utf-8'))
# print('中国'.encode('ascii')) # 报错UnicodeEncodeError
- 如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法。如果bytes中只有一小部分无效字节,可以传入errors='ignore’忽略错误的字节。
print(b'ABC'.decode('ascii'))
print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8',errors='ignore'))
- 保留字
python import keyword print(keyword.kwlist)
- 标识符
① 变量。函数、类、模块和其他对象起的名字就叫标识符
② 区分大小写
- 变量由标识、类型、值三部分组成。
标识:表示对象所存储的内存地址,使用id(obj)来获取
类型:表示的是对象的数据类型,使用type(obj)来获取
值:表示对象存储的具体数据,使用print(obj)直接打印输出
- 整数
- 浮点数
① 使用浮点数进行计算时,可能会出现小数位数不确定的情况。
② 导入decimal模块。
from decimal import Decimal
print(Decimal('1.1')+Decimal('2.2'))
- 布尔类型
① True为真,False为假
② 布尔值可以转化为整数
# 布尔类型
f1 = True
f2 = False
print(f1,type(f1))
print(f2,type(f2))
# 布尔值可以转成整数计算
print(f1+1)
print(f2+2)
- 字符串类型
① 不可变的字符序列
② 可以使用单引号’'、双引号"“、三引号”“”“”"来定义
③ 单引号和双引号定义的字符串必须在一行,三引号定义的字符串可以分布在连续的多行
④ 要计算str包含多少个字符,可以用len()函数。如果换成bytes,len()函数计算的是字节数。
⑤ 字符串是数组,可以使用str[i]来获取字符。
⑥ Python中的内置方法:
1. strip()方法删除开头和结尾的空白字符。
2. lower()返回小写的字符串。
3. upper()方法返回大写的字符串。
4. replace()用另一段字符串来替换字符串。
5. split()方法在找到分隔符的实例时将字符串拆分为子字符串。
6. 字符串串联使用+连接。
7. 可以使用format()方法对结果进行格式化。使用{}充当占位符。
1)可以在花括号内添加参数以指定如何转换值;
2)如需使用更多值,只需向 format() 方法添加更多值;
3)可以使用索引号(花括号 {0} 内的数字)来确保将值放在正确的占位符中;
4)还可以通过在花括号 {carname} 中输入名称来使用命名索引,但是在传递参数值 txt.format(carname = “Ford”) 时,必须使用名称。
8. join()方法使用哈希字符作为分隔符,将元组中的所有项目连接到字符串中。
9. find()和index()方法在字符串中搜索指定的值并返回它被找到的位置。如果找不到指定值,find()返回-1,index()报错。
10. 所有的字符串方法都返回新值,不会改变原始字符串。
# 字符串类型 str1 = '人生苦短,我用Python' str2 = "人生苦短,我用Python" str3 = """人生苦短, 我用Python """ print(str1) print(str2) print(str3) print(len(str1)) # 计算字符串长度 print(str1[1]) print(str1[2:5]) # 字符串方法 print('----------strip()删除开头和结尾的空白字符----------------') a = ' Hello,world! ' print(a.strip()) print('----------lower()----------------') print(a.lower()) print('----------upper()----------------') print(a.upper()) print('----------replace()----------------') print(a.replace('world','Python')) print('----------split()----------------') print(a.split(',')) print('----------检查字符串 in , not in----------------') print('Hello' in a) print('----------字符串串联使用+连接----------------') b1 = 'Good ' b2 = 'Morning' b = b1 + b2 print(b) print('----------format()----------------') age = 20 gender = 'boy' txt = 'My name is Bill, I am {} years old,and I am a {}.' print(txt.format(age,gender)) quantity = 3 itemno = 567 price = 52 myorder = "I want {0} pieces of item number {1} for {2:.2f} dollars." print(myorder.format(quantity, itemno, price)) myorder = "I have a {carname}, it is a {model}." print(myorder.format(carname = "Porsche", model = "911")) print('----------join()----------------') new_str = '*'.join(str1) print(new_str) print('----------find()------------') print(txt.find('name')) print('----------index()------------') print(txt.index('name'))
- 格式化
1) 通过使用 % 运算符来格式化字符串。
2) 在字符串内部,%s 表示用字符串替换, %d 表示用整数替换, %f 表示用浮点数替换,有几个 %? 占位符,后面就跟几个变量或者值,括号可以省略。格式化整数和浮点数还可以指定是否补0和整数与小数的位数。
3) 使用format()方法格式化字符串,他会用传入的参数依次替换字符串内的占位符{0}、{1}等。
4) f-string:是一种用以f开头的字符串格式化字符串的方法,字符串中如果包含{xxx},就会以对应的变量替换。
# 格式化
print('Hello,%s' % 'world')
print('Hi,%s,you have $%d.' % ('Michael',1000000))
print('%2d-%03d' % (3,1))
print('%.2f' % 3.1415926)
print('Hello,{0},数学考了{1:.1f}'.format('小明',98))
r = 2.5
s = 3.14 * r ** 2
print(f'The area of a circle with radius {r} is {s:.2f}')
- str()将其他类型转换成str类型
- int()将其他类型转换成int类型
注意:① 文字类和小数字符串不可转;② 浮点数转化成整数,抹零取整- float()将其他类型转换成float类型
注意:① 文字类无法转换;② 整数转成浮点数,末尾为.0
print('-------------------str()将其他类型转换成str类型') a = 10 b=198.7 c=False print(str(a),str(b),str(c),type(str(a)),type(str(b)),type(str(c))) print('--------------------int()将其他类型转换成int类型') s1='128' s2=98.7 s3='hello' s4=True print(int(s1),type(int(s1))) # 将str转换成int类型,字符串只能是整数串 print(int(s2),type(int(s2))) # print(int(s3),type(int(s3))) print(int(s4),type(int(s4))) print('--------------------float()将其他类型转换成float类型') s1='128.98' s2=98 print(float(s1),type(float(s1))) print(float(s2),type(float(s2))) print(float(s4),type(float(s4))) # print(float(s3),type(float(s3)))
- 单行注释:以#开头
- 多行注释:将一对三引号之间的代码称为多行注释
- 中文编码声明注释:
在文件开头写# -- coding:utf-8 --,标识的是该文件的编码方式为utf8。
- 基本使用:input()函数的结果是str类型
#输入函数input()
present=input('输入提示')
print(present,type(present))
a = int(input('请输入一个数:'))
b = int(input('请输入另一个数:'))
print(a+b)
- 算术运算符
# 算术运算符
print(1+1)
print(3-1)
print(2*4)
print(11/2)
print(11//2) # 整除运算
print(-9//-2)
print(9//-2) # 一正一负向下取整
print(-9//2)
print(11%2) # 取余运算:余数=被除数-除数*商
print(9%-2) # 9-(-2)*(-5)=-1
print(-9%2) #-9-2*(-5)=1
print(2**3) # 幂运算
- 赋值运算符
① 执行顺序:右→左
② 链式赋值:a=b=c=20
③ 支持参数赋值:+=、-=、*=、/=、//=、%=
④ 支持系列解包赋值:左右变量的个数与值的个数对应
print('------------赋值运算符--------') a=b=c=20 # 链式赋值 print(a,id(a)) print(b,id(b)) print(c,id(c)) print('--------支持参数赋值----------') a=20 a+=30 print(a) a-=10 print(a) a*=2 print(a) a/=3 print(a,type(a)) a//=2 print(a,type(a)) a%=2 print(a,type(a)) print('--------支持系列解包赋值-----------') a,b,c=20,30,40 print(a,b,c) print('-----交换两个变量的值-----') a,b=10,20 print('交换前:',a,b) a,b=b,a print('交换后:',a,b)
- 比较运算符:结果为True或False
# 比较运算符
a,b=10,10
print('a>b吗?',a>b)
print('a<b吗?',a<b)
print('a>=b吗?',a>=b)
print('a<=b吗?',a<=b)
print('a==b吗?',a==b) # ==比较的是值 is 比较的是地址(标识)
print('a is b?',a is b)
print('a is not b?',a is not b)
print('a!=b吗?',a!=b)
lst1=[11,22,33,44]
lst2=[11,22,33,44]
print('lst1 == lst2?',lst1 == lst2)
print('lst1 is lst2?',lst1 is lst2)
- 布尔运算符:and、or、not、in、not in
# 布尔运算符
a,b = 1,2
print(a==1 and b==2) # and 且
print(a==2 or b==2) # or 或
print(not a==1) # not 非
print('---------in 与 not in----------')
s = 'hello world'
print('w' in s)
print('k' in s)
print('w' not in s)
- 位运算符:
① 按位与 &:同为1结果为1,其余为0
② 按位或 |:同为0时结果为0,其余为1
③ 左移位:向左移动一位相当于乘以2(高位溢出低位补0)
④ 右移位:向右移动相当于除以2(高位补0低位溢出)
# 位运算符
print(4&8) # 按位与:同为1时结果为1,其余为0
print(4|8) # 按位或:同为0时结果为0,其余为1
print(4<<1) # 左移位:向左移动一位
print(4<<2) # 向左移动两位
print(4>>1) # 右移位:向右移动一位
print(4>>2) # 向右移动两位
- 运算符的优先级
算术运算(**、*,/,//,%、+,-)>位运算(<<,>>、&、|)>比较运算>布尔运算(and、or)>赋值运算(=)
- 从上到下顺序执行代码,中间没有任何判断和跳转,直到程序结束。
- 对象的布尔值:Python一切皆对象,所有对象都有一个布尔值。
使用内置函数bool()获取对象的布尔值- 以下对象的布尔值全为False:False、数值0、None、空字符串、空列表、空元组、空字典、空集合。
# 对象的布尔值
print(bool(False))
print(bool(0))
print(bool(0.0))
print(bool(None))
print(bool(''))
print(bool([])) # 空列表
print(bool(list())) # 空列表
print(bool(())) # 空元组
print(bool(tuple())) # 空元组
print(bool({})) # 空字典
print(bool(dict())) # 空字典
print(bool(set())) # 空集合
- 单分支结构
- 双分支结构
- 多分支结构
- 嵌套if
# 单分支结构 money=1000 s=int(input('请输入取款金额:')) # 判断余额是否充足 if money>=s: money-=s print('取款成功,余额为:',money) # 双分支结构 '''从键盘录入一个整数,判断是奇数还是偶数''' num=int(input('请输入一个整数:')) if num%2==0: print(num,"是偶数") else: print(num,"是奇数") # 多分支结构 '''从键盘录入一个整数成绩,判断成绩的范围''' score=int(input('请输入一个整数成绩:')) if score>=90 and score <=100:#也可写成 90<=score<=100 print('A') elif score>=80 and score<90: print('B') elif score>=70 and score<80: print('C') elif score>=60 and score<70: print('D') elif score>=0 and score<60: print('E') else: print('成绩无效') # 嵌套if '''会员:购物金额≥200打8折,≥100打9折,否则不打折 非会员:购物金额≥200打9.5折,否则不打折 ''' answer=input('您是会员吗?y/n') money=int(input('请输入您的购物金额:')) if answer=='y': if money>=200: print('打8折,付款金额为:',money * 0.8) elif money>=100 and money<200: print('打9折,付款金额为:',money * 0.9) else: print('不打折,付款金额为:',money) else: if money>=200: print('打9.5折,付款金额为:', money * 0.95) else: print('不打折,付款金额为:', money)
- 条件表达式:是if-else的简写
# 条件表达式
num_a=int(input('请输入第一个整数:'))
num_b=int(input('请输入第二个整数:'))
print((num_a,'大于等于',num_b) if num_a >= num_b else (num_a,'小于',num_b))
- pass语句:语句什么都不做,只是一个占位符,用在语法上需要语句的地方。
# pass语句
answer=input('您是会员吗?y/n')
if answer=='y':
pass
else:
pass
- 内置函数range():用于生成一个整数序列
- range()的三种创建方式
(1) range(stop):创建一个[0,stop)之间的整数序列,步长为1
(2) range(start,stop):创建一个[start,stop]之间的整数序列,步长为1
(3) range(start,stop,step):创建一个[start,stop]之间的整数序列,步长为step- 返回值是一个迭代器对象
- 不管range对象表示的整数序列有多长,所有range对象占用的内存空间都是相同的,只需存储start,stop和step。
- in 与 not in 判断整数序列中是否存在(不存在)指定整数
#range()的三种常见方式
'''1. range(stop)'''
r=range(10)
print(r)
print(list(r)) # 用于查看range对象中的整数序列 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
'''2. range(start,stop)'''
r=range(1,10)
print(list(r)) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
'''3. range(start,stop,step)'''
r=range(1,10,2)
print(list(r)) # [1, 3, 5, 7, 9]
'''判断指定整数是否在序列中 in 或 not in'''
print(10 not in r)
print(9 in r)
- while循环:判断n+1次,条件为True执行n次。
# while循环
'''1到100之间的偶数和'''
a=1
sum=0
while(a<=100):
if a%2==0:# not bool(a%2)
sum+=a
a+=1
print('1-100之间的偶数和为',sum)
- for-in循环
- in 表示从(字符串、序列等)中依次取值,又称为遍历
- 遍历的对象必须是可迭代对象(字符串、序列等)。
- 如果在循环体中不需要使用自定义变量,可将自定义变量写为’_‘。
'''输出100-999之间的水仙花数
水仙花数:153=3^3+5^3+1^3
'''
for item in range(100,1000):
ge=item%10 # 个位
shi=item//10%10 # 十位
bai=item//100 # 百位
# print(bai,shi,ge)
if (ge**3 + shi**3 + bai**3) == item:
print(item)
- 流程控制语句
1) break
(1) 用于结束循环结构。
(2) 直接跳出当前循环。
2) continue:结束当前循环,进入下一次循环。
3) else:可以与if、while、for配合使用。
# break语句
for _ in range(1,4):
pwd = input('请输入密码:')
if pwd=='8888':
print('密码正确')
break
else:
print('密码错误')
# continue 语句
for item in range(0,51):
if item%5!=0:
continue
print(item)
# else语句 # for _ in range(3): # pwd = input('请输入密码:') # if pwd=='8888': # print('密码正确') # break # else: # print('密码错误') # else: # print('三次密码输入错误') a=0 while a<3: pwd = input('请输入密码:') if pwd=='8888': print('密码正确') break else: print('密码错误') a+=1 else: print('三次密码输入错误')
- 嵌套循环:外层循环执行一次,内层循环执行完整的一轮。
# 嵌套循环
'''产生一个三行四列的矩形'''
for _ in range(1,4):
for _ in range(1,5):
print('*',end='\t') # 不换行输出
print()
'''打印出99乘法表'''
print()
for i in range(1,10):
for j in range(1,i+1):
print(i,'*',j,'=',i*j,end='\t')
print()
- break和continue在二重循环用于控制本层循环
# break和continue在二重循环的使用
print('---------break在二重循环的使用--------')
for i in range(1,5):
for j in range(1,10):
if j%2==0:
break
print(j)
print('---------continue在二重循环的使用--------')
for i in range(1,5):
for j in range(1,10):
if j%2==0:
continue
print(j)
- 通过[]进行创建
- 使用内置函数list()创建
- len()函数可以获取列表中元素的个数
# 列表
lst1 = ['hello','world',98] # 使用方括号创建
lst2 = list(['hello','world',98]) # 使用内置函数list()创建
print('lst1:',lst1)
print('lst2:',lst2)
print(len(lst1))
- 列表元素按顺序有序排序
- 索引映射唯一一个数据
- 列表可以存储重复数据
- 任意数据类型混存
- 根据需要动态分配和回收内存
- 获取指定元素的索引:index(‘item’)
1) 如果列表中存在N个相同元素,只返回相同元素中第一个元素的索引
2) 如果查询的元素在列表中不存在,则会抛出ValueError
3) 还可以在指定的start和stop之间进行查找[start,stop)
# 列表的查询操作
lst1 = ['hello','world',98,'hello']
print(lst1.index('hello'))
# print(lst1.index('python'))
print(lst1.index('hello',1,4))
- 获取列表中的单个元素
1) 正向索引从0到N-1,如:lst[0]
2) 逆向索引从-N到-1,如:lst[-N]
3) 指定索引不存在,抛出IndexError
# 获取列表中的单个元素
lst1 = ['hello','world',98,'hello',234]
print(lst1[2]) # 正向索引
print(lst1[-3]) # 逆向索引
# print(lst1[5]) # IndexError: list index out of range
- 获取列表中的多个元素
1) 语法格式:列表名[start:stop:step]
2) 切片操作
(1) 切片的结果:原列表片段的拷贝
(2) 切片的范围:[start,stop)
(3) step默认为1:简写为[start,stop)
(4) step为正数:从start开始往后计算切片
① [:stop:step] : 切片的第一个元素默认是列表的第一个元素
② [start::step]:切片的最后一个元素默认是列表的最后一个元素
(5) step为负数:从start开始往前计算切片
① [:stop:step]:切片的第一个元素默认是列表的最后一个元素
② [start::step]:切片的最后一个元素默认是列表的第一个元素
# 获取列表中的多个元素
lst=[10,20,30,40,50,60,70,80]
lst2=lst[1:4:1]
print(lst2)
print('原列表地址:',id(lst))
print('切片地址:',id(lst2))
print(lst[1:6]) # step默认为1
print(lst[1:6:]) # step默认为1
print(lst[:6:2]) # start默认为0
print(lst[1::2]) # stop采用默认
print('------------step步长为负数的情况-------------')
print(lst[::-1]) # 列表逆序
print(lst[7::-1]) # stop省略
print(lst[6:0:-2])
- 列表元素的查询操作
1) 判断指定元素在列表中是否存在
(1) 元素 in 列表名
(2) 元素 not in 列表名
2) 列表元素的遍历
for 迭代变量 in 列表名:
操作
# 列表元素的判断及遍历
lst=['hello','world',98,'python']
print(98 in lst) # True
print(98 not in lst) # False
print('good' in lst) # False
print('good' not in lst) # True
print('----------列表元素的遍历-----------')
for item in lst:
print(item)
- 列表元素的增删改操作
1) 增加元素
(1) append():在列表的末尾添加一个元素(如果添加的是列表,则把这个列表看作一个元素)。
(2) extend():在列表的末尾一次性添加多个元素(如果添加的是列表,则将该列表中的元素依次添加)。
(3) insert():在列表的任意位置添加一个元素。
(4) 切片:在列表的任意位置添加至少一个元素。
'''增加元素''' lst=[10,20,30] print('添加元素之前',lst,id(lst)) lst.append(40) # 在列表的末尾添加一个元素 print('添加元素之后',lst,id(lst)) lst2=['hello','world'] # lst.append(lst2) # 如果添加的是列表,则把这个列表看作一个元素 # print(lst) lst.extend(lst2) # 在列表的末尾一次性添加多个元素 print(lst) # 在任意位置上添加一个元素 lst.insert(1,90) print(lst) # 使用切片在任意位置上添加n多个元素 lst3=[True,False,'hello'] lst[1:]=lst3 print(lst)
2) 删除元素
(1) remove():从列表中移除一个元素,如果有重复元素,则只删第一个元素,元素不存在抛出ValueError。
(2) pop():根据索引移除元素,如果不指定索引,将删除列表中的最后一个元素,指定索引不存在抛出IndexError。
(3) 切片:切片操作删除至少一个元素,将产生一个新的列表对象。
(4) clear():清空列表
(5) del:删除列表对象
'''删除元素''' lst=[10,20,30,40,50,60,30] lst.remove(30) # 从列表中移除一个元素,如果有重复元素,则只删第一个元素 print(lst) lst.pop(1) # 根据索引移除元素 print(lst) lst.pop() # 如果不指定索引,将删除列表中的最后一个元素 print(lst) print('-------切片操作删除至少一个元素,将产生一个新的列表对象------') new_lst=lst[1:3] print('原列表',lst) print('切片后的列表',new_lst) '''不产生新的列表对象,删除原列表中的内容''' lst[1:3]=[] print(lst) '''clear()清除列表中的所有元素''' lst.clear() print(lst) '''del语句将列表对象删除''' del lst # print(lst) # 报错,列表对象已被删除
3) 修改元素
(1) 为指定索引的元素赋予一个新值。
(2) 为指定的切片赋予一个新值。
'''修改元素'''
lst=[10,20,30,40]
# 一次修改一个值
lst[2]=100
print(lst)
# 一次修改多个值
lst[1:3]=[300,400,500,600]
print(lst)
- 调用sort()方法:升序排序,在括号中指定reverse=True,进行降序排序,在原列表的基础上排序。
- 调用内置函数sorted():升序排序,在括号中指定reverse=True,进行降序排序,原列表不发生变化。
# 列表元素的排序操作
lst=[20,40,10,98,54]
print('----调用sort()方法排序-------')
print('排序前的列表',lst,id(lst))
lst.sort() # 升序排序 省略了reverse=False
print('升序排序后的列表',lst,id(lst))
lst.sort(reverse=True) # 降序排序
print('降序排序后的列表',lst,id(lst))
print('----调用内置函数sorted()排序,将产生一个新的列表对象-------')
lst=[20,40,10,98,54]
print('排序前的列表',lst)
new_lst=sorted(lst) # 升序排序
print('升序排序后的列表',new_lst)
desc_lst=sorted(lst,reverse=True) # 降序排序
print('降序排序后的列表',desc_lst)
- 语法格式:[i*i for i in range(1,10)]
- 注意:表示列表元素的表达式(如i*i)中通常包含自定义变量。
- for循环后面还可以加上if判断。如果把if写在for前面,必须加上else。
- 还可以使用两层循环。
# 列表生成式
lst=[i*i for i in range(1,10)]
print(lst)
lst2 = [i * i for i in range(1,10) if i % 2 == 0]
print(lst2)
lst3 = [i if i % 2 == 0 else -i for i in range(1,10)]
print(lst3)
'''使用两层循环生成全排列'''
lst4 = [m + n for m in 'ABC' for n in 'XYZ']
print(lst4)
- 在Python中,一边循环一边计算的机制,称为生成器:generator。
- 创建生成器:把列表生成式的[]改为()
- 可以通过next()函数获得generator的下一个返回值,直到最后抛出StopIteration错误表示无法继续返回下一个值。
- 可以使用for循环遍历生成器中的元素。
g = (i*i for i in range(1,10))
# print(next(g))
for x in g:
print(x)
- 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator函数,调用一次generator函数将返回一个generator对象。
generator函数在每次调用next()时执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
# 斐波那契数列
def fib(max):
n,a,b = 0,0,1
while n < max:
yield b
a,b = b, a + b
n = n + 1
return 'done'
'''使用for循环调用generator时,拿不到generator的return语句的返回值。'''
for n in fib(6):
print(n)
1、元组是有序且不可变的序列。
2、语法格式:thistuple = (‘张三’,‘李四’,‘王五’)
3、更改元组值:将元组转换为列表,再将列表转换为元组。
4、只有一个元素的tuple定义时,必须加一个逗号,来消除歧义。
5、如果元组中有可变序列,那么元组看起来也是“可变”的。
6、确定元组长度,用len()方法。
7、count()方法返回元组中指定值出现的次数
8、index() 方法在元组中搜索指定的值并返回它被找到的位置,如果有多个相同值,则返回第一个值的位置。
# 元组 '''创建元组''' thisTuple = ('张三','李四','王五','apple','banana','lemon') '''通过构造函数tuple()创建元组''' thisTuple2 = tuple(('apple','banana','lemon')) '''创建空元组''' t = () print(thisTuple) print(thisTuple2) print(t) print(thisTuple[1]) # 元组中第二个元素 print(thisTuple[-1]) # 元组中最后一个元素 print(thisTuple[2:5]) # 切片返回多个元素 '''只有一个元素的元组''' t1 = (1,) print(t1) '''无法删除元组中的元素,只能删除整个元组''' tuple1 = ['a','b','c','d'] del tuple1 # print(tuple1) # NameError: name 'tuple1' is not defined # 更改元组值 fruit = ('apple','banana','cherry','lemon') y = list(fruit) y[1] = 'watermelon' fruit = tuple(y) print(fruit) # "可变"元组 t2 = ('a','b',['A','B']) t2[2][0] = 'X' t2[2][1] = 'Y' print(t2) # 确定元组长度 print(len(t2)) # 合并元组 tuple1 = ('a','b','c','a') tuple2 = (1,2,3) tuple3 = tuple1 + tuple2 print(tuple3) # count()方法 print('a的个数:',tuple1.count('a')) #index()方法 print('a的位置:',tuple1.index('a'))
- 字典与列表一样,是一个可变序列。
- 以键值对的方式存储数据,字典是一个无序序列。
- 语法格式:thisDict = {‘name’:‘张三’,‘age’:18}
- 通过字典名[‘键名’]或字典名.get(‘键名’)来访问字典的元素。
- 可以通过引用其键名来更改特定项的值,也可以使用update()方法向字典中添加。
- 使用values()函数返回字典的值。
- 通过使用items()函数遍历键和值。
- 确定字典有多少键值对,使用len()方法。
- 嵌套字典:字典中包含字典。
- fromkeys() 方法返回具有指定键和值的字典,语法:dict.fromkeys(keys, value)。
- setdefault() 方法使用指定的键返回项目的值。如果键不存在,则插入这个具有指定值的键。
# 字典 '''创建字典''' thisDict = { 'name':'张三', 'age':18, 'gender':'男' } print(thisDict) '''使用dict()构造函数创建字典''' thisDict2 = dict(brand='Porsche',model='911',year=1963) print(thisDict2) '''通过方括号内引用其键名来访问字典的元素''' name = thisDict['name'] print(name) '''通过get()访问字典的元素''' age = thisDict.get('age') print(age) '''更改元组内元素的值''' thisDict['gender'] = '女' print(thisDict) # 遍历字典的键 for item in thisDict: print(item) # 使用values()函数返回字典的值 print(thisDict.values()) # 通过使用items()函数遍历键和值 for key,value in thisDict.items(): print(key,value) # 确定字典中是否存在指定的键,使用 in 关键字 if 'name' in thisDict: print(True) # 确定字典有多少键值对,使用len()方法 print(len(thisDict)) # 向字典中添加键值对 thisDict['school'] = 'QUT' print(thisDict) thisDict.update({'class':'Software'}) print(thisDict) # 删除键值对 '''pop()方法删除具有指定键名的项''' thisDict.pop('age') print(thisDict) '''popitem()删除最后一个键值对''' thisDict.popitem() print(thisDict) '''del 关键字删除具有指定键名的键值对''' del thisDict['name'] print(thisDict) '''clear()清空字典''' thisDict.clear() print(thisDict) '''del 删除字典对象''' del thisDict # print(thisDict) # 复制字典 '''使用copy()方法来复制字典''' dict1 = { 'name':'Mike', 'age':20, 'gender':'男' } mydict = dict1.copy() print('mydict:',mydict) '''使用dict()方法创建字典的副本''' dict2 = dict(dict1) print('dict2:',dict1) # 嵌套字典 myfamily1 = { 'child1':{ 'name':'Phoebe Adele', 'year':2002 }, 'child2':{ 'name':'Mike', 'year':2001 }, 'child3':{ 'name':'Rory John', 'year':1999 } } print('myfamily1:',myfamily1) '''创建三个字典,然后创建一个包含其他三个字典的字典''' child1 = { 'name':'Phoebe Adele', 'year':2002 } child2 = { 'name':'Mike', 'year':2001 } child3 = { 'name':'Rory John', 'year':1999 } myfamily2 = { 'child1':child1, 'child2':child2, 'child3':child3 } print('myfamily2:',myfamily2) # fromkeys() x = ('name','age','gender') y = 0 dict3 = dict.fromkeys(x,0) print('dict3:',dict3) # setdefault()方法 car = { "brand": "Porsche", "model": "911", "year": 1963 } year = car.setdefault("year") print('year:',year) color = car.setdefault("color", "white") print('color:',color)
- 集合是无序和无索引的集合。
- 语法表示:thisSet={‘apple’,‘banana’,‘lemon’}
- 可以使用for循环遍历set,或者使用in关键字查询集合中是否存在指定值。
- 集合一旦创建,就无法更改其中的元素。
- 可以使用add()和update()方法添加元素。
- 使用len()方法获取 set的长度。
- 使用remove() 或 discard()方法删除元素。如果删除的元素不存在,remove()会报错,而discard()不会。
- pop()方法删除的是集合中的最后一个元素,因为集合是无序的,所以不知道删除的是哪个元素。
- clear()方法清空集合,del 删除集合对象。
- 合并两个集合:union()方法返回包含两个集合中所有项目的新集合,update()将一个集合插入另一个集合。两个方法都排除重复项。
- difference()返回差集。
- intersection()返回交集。
# 集合 '''创建集合''' thisSet = {'apple','banana','lemon'} print('thisSet:',thisSet) '''通过使用set()构造函数来创建集合''' thisSet2 = set(('apple','banana','lemon')) print('thisSet2:',thisSet2) '''遍历set''' for item in thisSet: print(item) '''检查set中是否存在指定值''' print('apple' in thisSet) '''添加元素''' thisSet.add('orange') print('thisSet:',thisSet) thisSet.update(['mango','grapes']) print('thisSet:',thisSet) # 获取 set 的长度 print(len(thisSet)) # 删除元素 print('--------remove()--------') thisSet.remove('banana') print('--------discard()--------') thisSet.discard('mango') print('thisSet:',thisSet) # thisSet.remove('watermelon') thisSet.discard('watermelon') print('thisSet:',thisSet) print('--------pop()--------') thisSet.pop() print('thisSet:',thisSet) print('--------clear()--------') thisSet.clear() print('thisSet:',thisSet) print('--------del--------') del thisSet # 合并两个集合 print('--------union()--------') set1 = {'a','b','c'} set2 = {'a',1,2,3} set3 = set1.union(set2) print('set3:',set3) print('--------difference()--------') set4 = set1.difference(set2) # 返回差集 print('set4:',set4) print('--------intersection()--------') set5 = set1.intersection(set2) print('set5:',set5) print('--------update()--------') set1.update(set2) print('set1:',set1)
- 函数是一种仅在调用时运行的代码块。
- 函数中可以传参。
- 函数可以把数据作为结果返回。
- 函数名就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个别名。
- 使用 def 关键字定义函数。
- 使用函数名()来调用函数。
# 函数
'''创建函数'''
def my_function():
print('Hello, Function')
'''调用函数'''
my_function()
- 在函数名后的括号内指定,用逗号分隔多个参数。
- 默认参数值:def my_function(country=‘China’): …,注意:必选参数在前,默认参数在后。默认参数必须指向不变对象。
- 关键字参数:可以使用key = value 语法发送参数,参数的顺序无关紧要。这些关键字参数在函数内部自动组装成一个dict。
- 命名关键字参数:必须传入参数名。命名关键字参数需要一个特殊分隔符 * , * 后面的参数被视为命名关键字参数。如果函数定义中已有一个可变参数,后面跟着的命名关键字参数就不需要特殊分隔符 * 了。
- 可变参数:如果不知道传几个参数,在定义的参数名称前添加 *,这样函数将接收一个参数元组,并可以相应的访问各项。
# 参数 def function_1(fname): print(fname+' Gates') function_1('Bill') function_1('Steve') function_1('Elon') '''默认参数值''' def function_2(country = 'China'): print('I am from ' + country) function_2('India') function_2() '''以List传参''' def function_3(food): for x in food: print(x) fruits = ['apple','banana','cherry'] function_3(fruits) '''关键字参数''' def function_4(child3,child2,child1): print('The youngest child is ' + child3) function_4(child1 = 'Bill', child2 = 'Mike', child3 = 'Steve') def function4(name,age,**kw): print('name:',name,'age:',age,'other:',kw) function4('张三',18,city='北京') extra = {'gender':'男','city':'北京'} function4('张三',18,**extra) # **extra表示把rxtra中的所有键值对用关键字参数传到函数的**kw中。 '''命名关键字参数''' def person(name,age,*,city,job): print(name,age,city,job) person('Mike',20,city='Beijing',job='Doctor') def person(name,age,*args,city,job): print(name,age,args,city,job) person('Mike',20,'Boy',city='Beijing',job='Doctor') '''可变参数''' def function_5(*kids): print('The youngest child is ' + kids[2]) function_5('Bill','Mike','Steve')
- 如果需要使函数返回值,使用return语句。
- 函数也可以返回多个值,实际上是返回一个元组。
# 返回值
def function_6(x):
return x * x, x * 2
print(function_6(3))
- 尾递归可以解决递归调用栈溢出。
- 尾递归是指在函数返回的时候,调用自身本身,并且 return 语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈桢,不会出现栈溢出的情况。
- Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。
# 递归 '''实现阶乘''' def fact(k): if k==1: return 1 return k * fact(k-1) print(fact(5)) # 汉诺塔问题 def move(a,c): print(a,'-->',c) def hanoi(n,a,b,c): if n == 1: move(a,c) else: hanoi(n-1,a,c,b) move(a,c) hanoi(n-1,b,a,c) hanoi(3,'A','B','C')
- 将函数作为参数传入的函数称为高阶函数。
- map()函数接收两个参数,一个是函数,另一个是Iterable,map 将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
'''map()'''
def f(x):
return x * x
r = map(f,[1,2,3,4,5,6,7,8,9])
print(list(r))
print(list(map(str,[1,2,3,4,5,6])))
- reduce()函数把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算。
'''reduce()'''
from functools import reduce
def fn(x,y):
return x * 10 + y
def char2num(s):
digits = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
return digits[s]
print(reduce(fn,map(char2num,'13579')))
- filter()函数用于过滤序列。filter()函数接收一个函数和一个序列,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
'''filter()'''
'''在一个list中,删除偶数,只保留奇数'''
def not_odd(x):
return x % 2 == 1
print(list(filter(not_odd,[1,2,3,4,5,6,7,8,9])))
- sorted()函数可以对list进行排序,还可以接受一个key函数来实现自定义排序,要进行反向排序,传入第三个参数reverse = True即可。
'''sorted()'''
print(sorted([5,7,1,4,-3]))
print(sorted(['bob','about','Zoo','Credit'],key=str.lower))
print(sorted(['bob','about','Zoo','Credit'],key=str.lower,reverse=True))
- 高阶函数还可以把函数作为结果值返回。
- 闭包函数是能够读取其他函数内部变量的函数。
- 返回一个函数时,该函数并未执行,返回函数中不要引用任何可能会变化的变量。
def count():
def f(j):
def g():
return j * j
return g
fs = []
for i in range(1,4):
fs.append(f(i))
return fs
f1,f2,f3 = count()
print(f1())
print(f2())
print(f3())
- Lambda函数是一种小的匿名函数,冒号前面的变量表示函数参数。
- Lambda函数可接受任意数量的参数,但只能有一个表达式。
- 语法表示:lambda arguments : expression
- 如果在短时间内需要匿名函数,使用lambda函数。
# Lambda
x = lambda a,b : a * b
print(x(5,6))
y = lambda a,b,c : a + b+ c
print(y(1,2,3))
'''把lambda作为返回值返回'''
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
- 在代码运行期间动态增加功能的方式,称为装饰器。
- 函数对象有一个__name__属性,可以拿到函数的名字。
import functools
def log(func):
@ functools.wraps(func)
def wrapper(*args,**kw):
print('call %s():' % func.__name__)
return func(*args,**kw)
return wrapper
# 把decorator置于函数的定义处,相当于执行了 now = log(now)
@log
def now():
print('2022-10-15')
now()
print(now.__name__)
- 通过functools.partial来创建偏函数。
- functools.partial的作用就是把一个函数的某些参数固定住(即设置默认值),返回一个新的函数,调用这个新函数会更简单。
- 创建偏函数时,实际上可以接收函数对象、*args、**kw三个参数。
# 偏函数
import functools
'''相当于
kw = {'base': 2}
int('100000',**kw)
'''
int2 = functools.partial(int,base=2)
print(int2('100000'))
'''相当于
args = (10,5,7,12)
max(*args)
'''
max2 = functools.partial(max,10)
print(max2(5,7,12))
- 模块是包含一组函数的文件,希望在应用程序中引用。
- 在Python中,一个.py文件就是一个模块。
- 使用模块的好处: 1) 大大提高了代码的可维护性。 2) 可以避免函数名和变量名冲突。
- 为了避免模块名冲突,可以通过包来组织模块。
- 如需创建模块,只需将所需代码保存在文件扩展名为.py的文件中。
- 通过import 语句来导入模块。
- 如果使用模块中的函数,语法为:module_name.function_name。
- 模块可以包含已经描述的函数,但也可以包含各种类型的变量(数组、字典、对象等)。
- 重命名模块:使用as关键字创建别名。如: import mymodule as mx。
- Python中有几个内建模块,可以随时导入,如:platform。
- 使用dir()函数可以列出模块中的所有函数名(或变量名)。
- 可以使用from关键字选择仅从模块中导入部件。此时引用模块中的元素时不需要使用模块名称了。
# -*- coding: utf-8 -*- ' a test module ' # 表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释 __author__ = 'CuiYuqing' # 作者姓名 import sys def test(): '''sys.argv即 "argument value" 是一个列表对象, 其中存储的是在命令行调用python脚本时提供的“命令行参数”. sys.argv[0]是被调用的脚本文件名或全路径。 sys.argv[1:]之后的元素就是从程序外部输入的,而非代码本身的, 想要看到它的效果,就要将程序保存,从外部(即命令行)运行程序并给参数。 ''' args = sys.argv if len(args) == 1: print('Hello, World!') elif len(args) == 2: print('Hello, %s!' % args[1]) else: print('Too Many Arguments!') if __name__ == '__main__': # 相当于python模拟的程序入口 ''' 如果if __name__ == '__main__' 所在模块是被直接运行的,则该语句下代码块被运行,如果所在模块是被导入到其他的python脚本中运行的,则该语句下代码块不被运行。''' test()
import platform
import mymodule as mx # 重命名模块
from mymodule import person2 # 使用 from 关键字选择仅从模块导入部件
x = dir(platform) # dir()可以列出模块中的所有函数名(或变量名)。
print(x)
age = mx.person1["age"] # 访问模块中的变量
print('age:',age)
print('person2["name"]:',person2['name'])
- 正常的函数和变量名是公开的(public),可以直接被引用。
- 类似“ xxx ”这样的变量是特殊变量,可以被直接引用,但是有特殊用途。如:author
- 类似 “_xxx”和“__xxx”这样的函数或变量就是非公开的(private),不应该被直接引用。
'''在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来, 这样,调用greeting函数不用关心内部private函数的细节''' '''这是一种非常有用的代码封装和抽象的方法:即: 外部不需要引用的函数全部定义为private,只有外部需要引用的函数才定义为public ''' def _private_1(name): return 'Hello, %s' % name def __private_2(name): return 'Hi, %s' % name def greeting(name): if len(name)==3: return _private_1(name) else: return __private_2(name) print(greeting('李明'))
- 安装语法:pip install 模块名
- Anaconda是一个基于Python的数据处理和科学计算平台。
- 下载后直接安装,Anaconda会把系统Path中的python指向自带的Python,并且,Anaconda安装的第三方模块会安装在Anaconda自己路径下,不影响系统已安装的Python目录。
- OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
- 面向过程的程序设计就是把计算机程序视为一系列的命令集合,即一组函数的顺序执行。面向过程把函数切分成子函数,来降低系统的复杂度。
- 面向对象的程序设计把计算机程序视为一组对象的集合,每个对象都可以接收其他对象发过来的消息,并处理这些消息。
- 在Python中,所有数据类型都可以视为对象,自定义的对象数据类型就是面向对象中的类的概念。
- 类是抽象的模板。
- 实例是根据类创建出来的一个个具体的“对象”。每个对象都拥有相同的方法,但各自的数据可能不同。
- 类是通过class关键字定义的,class后面紧接着是类名,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的。
- object类是所有类的父类。
- 创建实例是通过类名()实现的。
- init()函数。 1) 所有类都有一个名为 init() 的函数,他始终在启动类时执行。 2) 使用__init__()函数将值赋值给对象属性,或者在创建对象时需要执行的其他操作。 3)
每次使用类创建新对象时,都会自动调用__init__()函数。 4)
init()函数的第一个参数永远是self,表示创建的实例本身,是对类的当前实例的引用,用于访问属于该类的变量。因此,在__init__()方法内部,就可以把各种属性绑定到self。
5) 有了__init__()方法,在创建实例时,必须传入与__init__方法匹配的参数,但是self不需要传。- 数据封装 1) 可以直接在类的内部定义访问类中数据的函数,这就把数据封装起来了。 2) 这些封装数据的函数称为类的方法。 3) 定义方法时,方法的第一个参数也必须是self,其他和普通函数一样。 4) 调用方法时,使用对象.方法名()直接调用。
- 修改对象属性 使用 对象.属性名 = 要修改的属性值 来修改对象属性。
- 删除对象属性 使用del关键字删除对象属性。del 对象.属性名
- 删除对象 使用 del 对象 来删除对象。
class Student(object): # 初始化方法,self表示创建的实例本身 def __init__(self,name,score): self.name = name self.score = score def print_score(self): print('The score of %s is: %s' % (self.name,self.score)) # 创建实例(对象) stu1 = Student('Mike',90) stu1.print_score() stu2 = Student('Bill',100) stu2.print_score() # 修改对象的属性 stu2.score = 88 stu2.print_score() # 删除对象属性 del stu2.score # stu2.print_score() # AttributeError: 'Student' object has no attribute 'score' # 删除对象 del stu2
- 如果想让内部属性不被外部访问,可以将属性变成私有属性(private),这样就确保了外部代码不能随意修改对象内部的状态。
- 如果外部代码要获取内部属性,可以给类增加get_属性名()方法。
- 如果外部代码要修改内部属性,可以给类增加set_属性名()方法。在set方法中,可以对参数做检查,避免传入无效的参数。
class Student(object): # 初始化方法,self表示创建的实例本身 def __init__(self,name,score): self.__name = name self.__score = score def print_score(self): print('The score of %s is: %s' % (self.__name,self.__score)) def get_name(self): return self.__name def get_score(self): return self.__score def set_name(self,name): self.__name = name def set_score(self,score): if 0<=score<=100: self.__score = score else: raise ValueError('error score') # 创建实例(对象) stu2 = Student('Bill',100) stu2.print_score() # 修改对象的属性 # print(stu2.__score) # AttributeError: 'Student' object has no attribute '__score' print(stu2.get_name()) stu2.set_score(99) stu2.print_score()
- 继承允许我们定义继承另一个类的所有方法和属性的类。
- 父类是被继承的类,也称为基类、超类。
- 子类也称为派生类。
- 继承的好处 1) 子类获得了父类的全部功能。 2) 子类可以新增自己特有的方法,也可以重写父类的方法。
- 当子类和父类存在相同的方法时,子类会覆盖父类的方法。
- 判断一个变量是否是某个类型,可以用 isinstance()判断。
- 多态:不同的子类对象调用相同的父类方法产生不同的执行结果。
- 对于静态语言来说,如果需要传入一个Animal类型,则传入的对象必须是Animal类型或者其子类,否则,无法调用run()方法。
- 对于Python这样的动态语言,则不一定需要传入Animal类型,只需保证传入的对象有一个run()方法就可以了。这就是动态语言的“鸭子类型”。
- super()函数,会使子类自动从其父继承所有方法和属性。
- 添加属性 使用self.属性名 = 属性值来添加。
# 继承和多态 class Animal(object): def run(self): print("Animal is running...") class Dog(Animal): pass dog = Dog() dog.run() class Cat(Animal): def run(self): # 多态:子类重写了父类的方法 print("Cat is running...") def eat(self): print('Eat fish...') cat = Cat() cat.run() cat.eat() # 判断一个变量是否是某个类型 print(isinstance(cat,Animal)) def run_twice(animal): animal.run() run_twice(Animal()) run_twice(Cat()) class Tortoise(object): def run(self): print("Tortoise is running...") run_twice(Tortoise()) class Person(object): def __init__(self,name,age): self.name = name self.age = age class Student(Person): def __init__(self,name,age,year): super().__init__(name,age) self.graduationyear = year def show(self): print('%s 今年 %s 岁,在 %s 年毕业' % (self.name,self.age,self.graduationyear)) x = Student('Mike',20,2023) x.show()
- 使用type()判断对象类型。
- 使用isinstance()判断对象类型。能用type()判断的基本类型也可以用isinstance()判断。
- 还可以使用isinstance()判断一个变量是否是某些类型中的一种。
- 使用dir()可以获得一个对象的所有属性和方法。
- getattr(obj, attr[, default]) 用来获取属性,如果属性不存在,就返回传入的默认值。
- setattr(obj, attr, 属性值) 用来为obj对象设置属性值。
- hasattr(obj, attr) 判断obj对象是否有属性attr。
- 只有在不知道对象信息时,才会去获取对象信息。
- 如果可以直接写 sum = obj.x + obj.y,就不要写 sum = getattr(obj,‘x’) + getattr(obj,‘y’) 。
# 获取对象信息 # type() print(type(123)) print(type(123) == type(456)) # 判断一个对象是否是函数 import types def fn(): pass print(type(fn) == types.FunctionType) # isinstance() print(isinstance(123,int)) # 判断一个变量是否是某些类型中的一种 print(isinstance([1,2,3],(list,tuple))) print('--------------------') class MyObject(object): def __init__(self): self.x = 9 def power(self): return self.x * self.x obj = MyObject() print(dir(obj)) # 获得该对象的所有属性和方法 print(hasattr(obj,'x')) print(getattr(obj,'x')) print(getattr(obj,'y',100)) setattr(obj,'z',2) print(getattr(obj,'z'))
- 实例属性属于各个实例所有,互不干扰;
- 类属性属于类所有,所有实例共享一个属性‘
- 不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误。
# 实例属性和类属性
class Student(object):
name = 'Student' # 类属性
# def __init__(self,name):
# self.name = name # 实例属性
s = Student()
print(s.name) # 实例没有name属性,所以会继续查找cass的name属性
print(Student.name)
s.name = 'Mike'
print(s.name) # 实例属性的优先级比类属性高,所以实例属性会覆盖类属性
- 在类中定义一个__slots__变量来限制该类的实例能添加的属性。
- __slots__定义的属性只对当前类实例起作用,对继承的子类不起作用。
- 如果在子类中也定义__slots__,子类实例就允许定义的属性就是自身的__slot__加上父类的__slots__。
class Student(object): __slots__ = ('name','age') s = Student() s.name = 'Mike' s.age = 20 # s.score = 90 # AttributeError: 'Student' object has no attribute 'score' # __slots__定义的属性只对当前类实例起作用,对继承的子类不起作用 class S(Student): pass a = S() a.score = 99 # 如果在子类中也定义__slots__,子类实例就允许定义的属性就是自身的__slot__加上父类的__slots__ class Stu(Student): __slots__ = ('name', 'age') b = Stu() # b.score = 80
- @property装饰器就是负责把一个方法变成属性调用。
- 属性名和方法名一定要区分开,不然会进入死循环。
- 实例化的对象使用属性时,不是调用属性,而是用的方法名。
- @property实现的是getter功能,@xxx.setter实现的是setter功能;@xxx.deleter实现的是删除功能。
- 定义方法时@property必须在@xxx.setter之前,且二者修饰的方法名相同。
- 如果只实现了@property,那么该属性为只读属性。
# @property用法 class Student(object): def __init__(self,name,age): self._name = name self._age = age @property # 实现一个age相关的getter方法 def age(self): return self._age @age.setter # 实现一个age相关的setter方法 def age(self,value): if isinstance(value,int): self._age = value else: raise ValueError("'int' type need") stu = Student('Xiaohong',18) stu.age = 19 print(stu.age)
- 通过多重继承,一个子类就可以同时获得多个父类的所有功能。
- 在设计类的继承关系时,通常主线都是单一继承下来的。如果需要“混入”额外的功能,通过多重继承可以实现,这种设计称为MixIn。
- MixIn的目的就是给一个类增加多个功能。
# 多重继承 class Animal(object): pass # 大类: class Mammal(Animal): pass class Bird(Animal): pass # 会飞 class FlyableMixIn(object): def fly(self): print("Flying...") # 会跑 class RunnableMixIn(object): def run(self): print("Runnable...") # 各种动物:多重继承 class Dog(Mammal,RunnableMixIn): pass class Parrot(Bird,RunnableMixIn): pass
- Python在使用枚举类时需要导入enum模块,枚举定义用class关键字,继承Enum类。
- 定义枚举时,成员名称不允许重复,成员名称相同时就会报错。
- 默认情况下,不同的成员值允许相同。但是两个相同值的成员,第二个成员的名称被视作第一个成员的别名。
- 可以使用装饰器@unique【要导入unique模块】,可以帮助我们检查保证没有重复值。
- 既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。
- 如果枚举有值重复的成员,循环遍历枚举时只获取值重复成员的第一个成员。如果想把值重复的成员也遍历出来,要用枚举的一个特殊属性__members__。
- 枚举成员可进行同一性比较,使用is和not等,枚举成员可进等值比较,使用==,枚举成员不能进行大小比较。
# 枚举类 from enum import Enum,unique Month = Enum('Month',('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')) for name,member in Month.__members__.items(): print(name,'=>',member,',',member.value) @unique # 保证没有重复值 class Weekday(Enum): Sun = 0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6 print(Weekday.Mon) print(Weekday['Tue']) print(Weekday.Wed.value) print(Weekday(1))
- 使用__str__()方法可以返回一个自定义的字符串。
- repr()方法:当直接打印类的实例化对象时,系统将会自动调用该方法,输出对象的自我描述信息,用来告诉外界对象具有的状态信息。repr()方法返回程序开发者看到的字符串。
- 如果一个类像被用于for…in循环,就实现一个__iter__()方法,该方法返回一个迭代对象。
- getitem(self,key):这个方法返回与指定键相关联的值。 对序列来说(通常是列表),键应该是0~n-1的整数,其中n为序列的长度。对映射来说(通常是字典),键可以是任何类型。
- getattr()方法可以动态返回一个属性。只有当调用不存在的属性时,Python解释器会试图调用__getattr__(self,‘score’)来尝试获得属性。
- 在类中定义一个__call__()方法,可以直接对实例进行调用。call()还可以定义参数。
# 定制类 class Student(object): def __init__(self,name): self.name = name # 使用__str__()方法可以返回一个自定义的字符串 def __str__(self): return 'Student object (name: %s)' % self.name # __repr__()方法返回程序开发者看到的字符串。 __repr__ = __str__ # __getattr__()方法可以动态返回一个属性.只有当调用不存在的属性时,Python解释器会试图调用__getattr__(self,'score')来尝试获得属性。 def __getattr__(self,attr): if attr == 'score': return 99 # __call__()可以直接对实例进行调用。 def __call__(self): print('My name is %s.' % self.name) s = Student('Mike') print(s) print('score:',s.score) s() # iter()方法 class Fib(object): def __init__(self): self.a, self.b = 0,1 def __iter__(self): return self # 实例本身就是迭代对象 def __next__(self): self.a, self.b = self.b, self.a + self.b # 计算下一个值 if self.a > 100000: raise StopIteration() return self.a # 返回下一个值 # __getitem__(self,key):这个方法返回与指定键相关联的值。 def __getitem__(self,n): a,b = 1,1 for x in range(n): a,b = b,a+b return a for n in Fib(): print(n) f = Fib() print(f[0])
- 当我们认为某些代码可能会出错时,就可以使用try来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块,
执行完except后,如果有finally语句块,则执行finally语句块,至此,执行完毕。- 如果没有错误发生,就不会执行except语句块,但是如果有finally,则一定会被自行。
- 如果发生了不同类型的错误,应该有不同的except语句块来捕获不同类型的错误。
- 使用try…except捕获错误可以跨越多层调用。不需要在每个可能出错的地方捕获错误,只要在合适的层次去捕获就可以。
- Python内置的logging 模块可以容易的记录错误信息,然后让程序继续执行下去。
- 可以使用raise语句抛出错误。raise语句如果不带参数,就会把当前错误原样抛出。
try:
print('try...')
r = 10 / int('2')
print('result:',r)
except ValueError as e:
print('ValueError:',e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
else:
print('no error!')
finally:
print('finally...')
print('END')
import logging
def foo(s):
return 10 / int(s)
def main():
try:
foo('0')
except Exception as e:
logging.exception(e)
main()
print('End')
# 捕获错误后,打印ValueError后,又把错误抛出去
def foo(s):
n = int(s)
if n==0:
raise ValueError('invalid value: %s' % s)
return 10 / n
def bar():
try:
foo('0')
except ValueError as e:
print('ValueError!')
raise
bar()
- 单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。
- 如果我们对某个函数代码做了修改,只需要再跑一遍单元测试,如果通过,说明我们的修改不会对函数原有的行为造成影响, 否则,说明我们的修改与原有行为不一致,要么修改代码,要么修改测试。
- 为了编写单元测试,需要引入Python自带的unittest模块。
- 编写单元测试时,我们需要编写一个测试类,从unittest.TestCase继承。以test开头的方法就是测试方法,否则就不是测试方法,测试时不会被执行。
- 最常用的断言是assertEqual(),判断函数返回值是否与指定值相等。
- 另一个重要的断言是assertRaises(Error),期待抛出指定类型的Error。
- 在单元测试中编写setUp()和tearDown()方法,会分别在每调用一个测试方法的前后分别被执行。
import unittest from mydict import Dict class TestDict(unittest.TestCase): def test_init(self): d = Dict(a=1,b='test') self.assertEqual(d.a,1) self.assertEqual(d.b,'test') self.assertTrue(isinstance(d,dict)) def test_key(self): d = Dict() d['key'] = 'value' self.assertEqual(d.key,'value') def setUp(self): print('setUp...') def tearDown(self): print('tearDown...') if __name__ == '__main__': unittest.main()
- Python内置的“文档测试”(doctest)模块可以直接提取注释中的代码并执行测试。
- doctest严格按照Python交互式命令行的输入和输出来判断测试结果是否正确。
- 当模块正常导入时,doctest不会被执行,只有在命令行直接运行时,才执行doctest。
- 如果什么输出也没有,说明编写的doctest运行都是正确的。
class Dict(dict): ''' Simple dict but also support access as x.y style. >>> d1 = Dict() >>> d1['x'] = 100 >>> d1.x 100 >>> d1.y = 200 >>> d1.y 200 >>> d2 = Dict(a=1,b=2,c='3') >>> d2.c '3' >>> d2['empty'] Traceback (most recent call last): ... KeyError: 'empty' >>> d2.empty Traceback (most recent call last): ... AttributeError: 'Dict' object has no attribute 'empty' ''' def __init__(self,**kw): super().__init__(**kw) def __getattr__(self,key): try: return self[key] except KeyError: raise AttributeError(r"'Dict' object has no attribute '%s'" % key) def __setattr__(self,key,value): self[key] = value if __name__=='__main__': import doctest doctest.testmod()
- Python中的日期不是其自身的数据类型,但是我们可以导入名为datetime的模块,把日期视作日期对象进行处理。
- 可以使用datetime模块的datetime()类来创建日期。datetime() 类需要三个参数来创建日期:年、月、日,其他参数可选。
- datetime 对象拥有把日期对象格式化为可读字符串的方法。该方法称为 strftime(),并使用一个 format 参数来指定返回字符串的格式。
- %A:Weekday; %B:月; %d:日; %m:数字的月; %Y:年; %H:小时; %M:分; %S:秒
import datetime
x = datetime.datetime.now()
print(x) # 返回当前日期
print(x.year) # 返回年份
# strftime()方法可以把日期对象格式化为可读字符串,使用一个format参数来指定返回字符串的格式。
print(x.strftime("%A")) # 返回weekday的名称
print(x.strftime("%B")) # 返回month的名称
# 创建日期对象
y = datetime.datetime(2020,5,20,13,14) # 年月日必须有,其他参数可选
print(y)
- JSON是用于存储和交换数据的语法。
- JSON是用JavaScript对象表示法编写的文本。
- Python中有一个名为json的内置包,可用于处理JSON数据。
- JSON转化为Python:若有JSON字符串,则可以使用json.loads()方法对其进行解析,结果将是Python字典。
- Python转化为JSON:若有Python对象,可以使用json.dumps()方法转换为JSON字符串。
- json.dumps()中的参数 1) 可以使用indent参数定义缩进数。 2) 使用 separators 参数来更改默认分隔符,默认值为(", ", ": "),这意味着使用逗号和空格分隔每个对象,使用冒号和空格将键与值分开。 3) 使用
sort_keys 参数来指定是否应对结果进行排序.
import json # JSON字符串 x = '{"name":"Bill","age":63,"city":"USA"}' # 解析 JSON:JSON转化为Python y = json.loads(x) # 结果是Python字典 print(y,type(y)) # Python转化为JSON '''Python 对象(字典)''' dict = { "name":"Mike", "age":30, "city":"USA" } y = json.dumps(dict) # 把Python对象转换为JSON字符串 print(y,type(y)) print(json.dumps(["apple","banana"])) # 把Python的list转换为JSON的Array print(json.dumps(("apple","banana"))) # 把Python的tuple转换为JSON的Array print(json.dumps(42)) # 把Python的int转换为JSON的Number print(json.dumps(None)) # 把Python的None转换为JSON的null print(json.dumps(dict,indent=4,separators=(".","="),sort_keys=True))
- RegEx 或正则表达式是形成搜索模式的字符序列。
- RegEx可用于检查字符串是否包含指定的搜索模式。
- Python 提供名为 re 的内置包,可用于处理正则表达式。
- re 模块提供了一组函数,允许我们检索字符串以进行匹配。 1) findall():返回包含所有匹配项的列表。 2) search():如果字符串中的任意位置存在匹配,则返回Match对象。如果有多个匹配,就返回首个匹配项。 3)
split():返回在每次匹配时拆分字符串的列表。 4) sub():用字符串替换一个或多个匹配项。- 元字符 []:表示一组字符; \:表示特殊序列(如:转义字符); .:除换行符以外的任何字符; ^:起始字符; $:结束字符; *:0次或多次出现; +:一次或多次出现; {}:确切指定出现次数; |:两者任一;
():捕获和分组- Match 对象是包含有关搜索和结果信息的对象。 1) 如果没有匹配,则返回值 None,而不是 Match 对象。 2) span() 返回的元组包含了匹配的开始和结束位置。 3) .string 返回传入函数的字符串。 4) group()
返回匹配的字符串部分。
import re
txt = "China is a great country"
x = re.search("^China.*country$",txt)
x2 = re.findall("a",txt)
x3 = re.split("\s",txt) # \s 返回字符串包含空白字符的匹配项
x4 = re.split("\s",txt,1) # 仅在首次出现时拆分字符串
x5 = re.sub("\s","\t",txt)
print(x.group())
print(x.span())
print(x.string)
print(x2)
print(x3)
print(x4)
print(x5)
- 在Python中使用文件的关键函数是open()函数。
- open()函数有两个参数:文件名和模式。
- 打开文件的方法: 1) “r”:读取,默认值,打开文件进行读取,文件不存在则报错。 2) “a”:追加,打开供追加的文件,文件不存在则创建文件。会追加到文件末尾。 3)
“w”:写入,打开文件进行写入,文件不存在则创建文件。会覆盖已有的全部内容。 4) “x”:创建,创建指定文件,文件存在则报错。- 指定文件处理方式: 1) “t”:默认值,文本模式。 2) “b”:二进制模式。
- 关闭文件:f.close()
- open()函数返回文件对象,使用该对象的read()方法用于读取文件内容。
- 默认情况下,read() 方法返回整个文本,也可以指定要返回的字符数。
- 使用 readline() 方法返回一行。通过循环遍历文件中的行,可以逐行读取整个文件。
- 使用 readlines() 方法读取文件的所有行,自动将文件内容分析成一个行的列表,返回的每一行内容包含换行符。
# 文件打开、读取、关闭
f = open("D:\\text.txt") # 等同于 f = open("D:\test.txt","rt")
# print(f.read()) # 读取整个文本
# print(f.read(5)) # 读取文本中的指定字符数
# print(f.readline()) # 读取文件中的一行
# print(f.readlines()) # 读取文件的所有行,自动将文件内容分析成一个行的列表
# 通过循环遍历文件中的行,您可以逐行读取整个文件
for x in f:
print(x)
f.close()
- 如需写入已有文件,必须向open()函数中添加"a"、"w"参数。
- 使用write()函数追加内容。
- 如需在 Python 中创建新文件,请使用 open() 方法,并使用"a"、“w”、"x"中的一个参数。
f = open("D:\\text.txt","a") # 向文件中追加内容
f.write("Happy New Year!")
f = open("D:\\text.txt","w") # 覆盖文件中的内容
f.write("Happy New Year!")
f = open("D:\\demo.txt","x") # 创建新文件
f.write("Happy New Year!")
- 删除文件时,需要导入os模块,并使用os.remove()函数。
- 为了避免出现错误,在删除文件之前检查文件是否存在。
- 如果需要删除空文件夹,使用os.rmdir()方法。
# 删除文件
import os
if os.path.exists("D:\\demo.txt"): # 检查文件是否存在
os.remove("D:\\demo.txt")
else:
print("The file does not exist")
os.rmdir("D:\\test") # 只能删除空的文件夹
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。