Python入门学习(十)第十四章其他
一、用字典映射代替switch语句
''' 用字典来代替其他语言中的switch实现 day = 2 switch(day) { case 0: daytime="Sunday"; break; case 1: daytime="Monday"; break; case 2... default: dayname = "Unknown"; break; } ''' day = 5 daytime_switchers = { 0 : "Sunday", 1 : "Monday", 2 : "Tuesday" } #day_name = daytime_switchers[day] #但switch语句中一般还有default分支默认值的情况 #可以通过字典的get方法 #get方法第一个参数对应键,如键不存在时则返回第二个参数内容 day_name = daytime_switchers.get(day, "Unknown") print(day_name)
如果switch分支对应的是代码块,则在字典键内容中设置函数去实现
''' 用字典来代替其他语言中的switch实现 如果switch分支中对应的是代码块 则可以通过字典值中设置不同的函数去实现 ''' day = 2 def get_sunday(): return "Sunday" def get_monday(): return "Monday" def get_tuesday(): return "Tuesday" def get_default(): return "Unkonw" daytime_switchers = { 0 : get_sunday(), 1 : get_monday(), 2 : get_tuesday() } day_time =daytime_switchers.get(day, get_default()) print(day_time)
二、列表推导式
#列表推导式 a = [1, 2, 3, 4, 5, 6, 7, 8] #从上述已知列表a获取新列表,元素为对应的平方 #第一种方法是通过map映射 b = map(lambda x : x*x, a) print(list(b)) #第二种通过原始的实现 b = [] for i in a: b.append(i * i) print(b) #第三种就是列表推导式 b = [i * i for i in a] print(b)
a = [1, 2, 3, 4, 5, 6, 7, 8] #如果要对列表a中大于等于5的元素作立方运算,并用列表输出 #map则不是太合适,需要先对原列表分解出对应条件的集合再去映射 #或者配合filter实现 c = filter(lambda x:1 if x >= 5 else 0, a) b = map(lambda i : i**3, list(c)) print(list(b)) #用for自然也可以实现 #但用列表推导式是最简便快速的 b = [i**3 for i in a if i >= 5] print(b)
从上面代码可看出:列表推导式分为三部分:1、运算规则;2、遍历;3、遍历元素筛选条件
列表推导式对序列也是通用的,如果想得到集合则推导式需要使用{},如想到元组则使用():
#列表推导式对序列也是通用的 a = [1, 3, 5, 5, 7, 9] t1 = (i**2 for i in a) s1 = {i**2 for i in a} print(tuple(t1)) print(set(s1))
#字典的推导式 students = { "王斌" : 28, "李晓明" : 36, "Mike" : 26 } #尝试把key提取出来作为一个元组 b = [key for key,value in students.items()] print(b) #如果要把键-值做一个颠倒 b = {value : key for key,value in students.items()} print(b) #如果把键值对做成元组 b = ({key:value} for key,value in students.items()) print(tuple(b)) #或者: b_key = (key for key,value in students.items()) print(tuple(b_key)) b_value = (value for key,value in students.items()) print(tuple(b_value)) #如果把键值对做成列表 b = [{key:value} for key,value in students.items()] print(b)
三、关于组、序列的概念:iterator和generator
1、可迭代对象:是指可以被遍历的对象,如列表、元组、集合、字典,也包括一些具备迭代器(iterator)功能的对象
#创建一个可遍历的类 #类必须被设计为具备迭代器功能的才可以被for/in迭代 #必须具有__iter__()和__next__()两个方法 class BookCollection: def __init__(self): self.data = ["边城", "三体", "平凡的世界", "金锁记"] self.cur = 0 def __iter__(self): return self def __next__(self): if self.cur >= len(self.data): raise StopIteration r = self.data[self.cur] self.cur += 1 return r books = BookCollection() for book in books: print(book) for book in books: print(book)
2、生成器
#生成器 #如果要生成1~10000的数字 #可以用列表推导式 #n = [i for i in range(1, 10001)] #print(n) #上述代码虽然可以实现功能,但非常消耗计算机内存 #有没有什么方法可以不过多消耗计算机内存,又能实现这一功能 #如下可以: ''' def gen(max): n = 0 while n <= max: print(n) n += 1 gen(10005) ''' #但上述gen()函数不只是提供了数字,还兼顾实现了打印功能 #这种方式把数据获取和业务功能捆绑在一起,并不合理 #有没有单纯的可以获取数据呢 def gen(max): n = 0 while n <= max: n += 1 yield n #通过yield则gen()就变成了一个生成器 #yield与return不同,return会直接退出函数,yield则会继续循环 g = gen(20) print(next(g)) print(next(g)) print(next(g)) print((".........................")) #可以如上逐次通过next()调用获取 #也可以通过for in遍历生成器 for i in g: print(i)
四、关于None
None即表示“空”,而非(不等于)0、空字符串、空列表、false等
a = "" b = False c = 0 d = [] print (a == None) print (b == None) print (c == None) print (d == None) #以上均打印“False”
python中的“None”本身也是一个对象
print(type(None)) #打印“<class 'NoneType'>”
可以看出None属于Nonetype类型,而False是布尔类型。
a = [] if not a: print("S") else: print("F") #以上输出"S" if a is None: print("S") else: print("F") #以上输出"F" #说明空列表的反义(not a)为真,但空列表a却不等同于None print(type(a)) #可以看出a仍为列表类型,但前面我们得知None是“NoneType”类型
对象存在并一定是True
class Test(): def __len__(self): return 10 #类中的__len__方法返回为0,则该类创建的对象对应布尔值为False,非0则为True def __bool__(self): return False #类中__bool__方法也可以设置实例对象对应布尔值为真或伪 #同时,__bool__方法设置的优先级是大于__len__方法的 test = Test() print(bool(None)) #False print(bool([])) #False print(bool(test)) #False if test: print("S") else: print("F")
五、关于装饰器的“副作用”
import time def showtime_deco(func): def wrapper(): t1 = time.time() func() t2 = time.time() print("The Function runed for", str(t2-t1), "seconds.") return wrapper @showtime_deco def f1(): ''' This is f1 function. :return: None ''' print("This is the f1 function.") print(f1.__name__) print(help(f1)) f1() #可以发现打印函数名称输出的是wrapper,而非原函数名f1
可以通过给f1()保留和去掉装饰器之后运行的差异发现:1、函数名发生变化,加上装饰器之后函数名打印为wrapper;2、原函数f1的注释文档在help(f1)中未显示,只显示wrapper()
这些就是装饰器对原函数的副作用
要保持原函数名不变并且help可以显示原函数的注释文档,可以导入wraps,并且将其作为既有装饰器内部函数的装饰器:
import time from functools import wraps def showtime_deco(func): @wraps(func) def wrapper(): t1 = time.time() func() t2 = time.time() print("The Function runed for", str(t2-t1), "seconds.") return wrapper @showtime_deco def f1(): ''' This is f1 function. :return: None ''' print("This is the f1 function.") print(f1.__name__) print(help(f1)) f1() #可以发现打印函数名称输出的是wrapper,而非原函数名f1
六、python3.8新增的海象运算符
#walrus operator 海象运算符 := a = "python3.8" b = len(a) if b > 5: print("长度大于5;"+ "实际长度为"+str(b)) print("-------------以上为传统的写法-------------") print("-------------下面为海象运算符写法--------------") if (c:=len(a)) < 10: #需要注意海象运算符优先级较低,需要括号 print("长度小于10," + "实际长度为" + str(c))
七、字符串拼接
a = 3 b = 5 print(str(a),"和",str(b),"之和为",str(a+b)) print(str(a)+"和"+str(b)+"之和为"+str(a+b)) #用f+{}形式拼接更为方便 print(f"{a}和{b}之和为{a+b}。")
八、python3.7新增数据类dataclass装饰器
原来的写法:
class Student(): def __init__(self, name, age, school_name): self.name = name self.age = age self.school = school_name def test(self): print(self.name) student = Student("Michale", 18, "Tsinghua") student.test()
使用dataclass装饰器的写法:
from dataclasses import dataclass @dataclass class Student(): name : str age : int school_name : str #上述代码等同于__init__构造函数 def test(self): print(self.name) student = Student("Michale", 18, "Tsinghua") print(student.__repr__()) student.test()
浙公网安备 33010602011771号