13、Pythonic
2018-12-25 本文已影响0人
IT_Freak
Pythonic:极具Python特色的Python代码(明显区别于其它语言的写法的代码)
用字典映射代替switch case语句
if/else可以代替switch但是非常不合适。
用字典代替switch:
day = 5
switcher = {
0:'Sunday',
1:'Monday',
2:'Tuesday'
}
day_name = switcher.get(day,'Unknow') #第一个参数为key,第二个参数为key不存在返回的值
用字典模拟带函数的switch:
day = 6
def get_sunday():
return 'Sunday'
def get_monday():
return 'Monday'
def get_tuesday():
return 'Tuesday'
def get_default():
return 'Unknow'
switcher = {
0:get_sunday,
1:get_monday,
2:get_tuesday
}
day_name = switcher.get(day,get_default)()
print(day_name)
列表推导式
根据已经存在的列表创建新的列表:
a = [1,2,3,4,5,6,7,8]
b = [i * i for i in a]
print(b)
结果:[1, 4, 9, 16, 25, 36, 49, 64]
条件筛选:
a = [1,2,3,4,5,6,7,8]
b = [i**2 for i in a if i >= 5]
print(b)
结果:[25, 36, 49, 64]
a是集合、字典、元组也可以被推导。
字典编写列表推导式
students = {
'tai':18,
'park':32,
'a':12
}
b = [key for key,value in students.items()]
print(b)
结果:['tai', 'park', 'a']
b = {value:key for key,value in students.items()}
print(b)
结果:{18: 'tai', 32: 'park', 12: 'a'}
迭代器(iterator)
可迭代对象(iterable):可被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 in 遍历,还可以调用next方法:
books = BookCollection()
print(next(books))
print(next(books))
print(next(books))
迭代器具有一次性,只能遍历一次。若想再次遍历需要实例化一个新的对象。或者:
import copy
books = BookCollection()
books_copy = copy.copy(books) #浅拷贝
若想实现深拷贝的话:
books_copy = copy.deepcopy(books) #生成器
生成器(generator)
打印从0-10000的数字:
n = [i for i in range(0,10001)]
for i in n :
print(i)
可以实现但是太消耗内存。n是一个列表,列表存储需要消耗内存的。
生成器:迭代器是针对一个对象的,生成器是针对一个函数的。
函数实现法:
def gen(max):
n = 0
while n <= max:
print(n)
n += 1
gen(100000)
每次打印的都是实时计算出来的结果,不是都存储起来再打印。
不应该在函数内部实现如print这样的操作。
生成器:
def gen(max):
n = 0
while n <= max:
n += 1
yield n
g = gen(10)
for i in g:
print(i)
yield会接着返回的地方继续执行。
n = (i for i in range(0,10001))
此时n也为生成器。
None
- None 空,不等于空字符串、空列表、0、False
- None不仅在类型上不同,而且在值的比较上也不相同。
- None永远对应False
a = None
print(not a)
print(a is None)
结果:True
True
a = []
print(not a)
print(a is None)
结果:True
False
推荐if a/if not a来判空。
对象存在并不一定是True
自定义的对象:
class Test():
def __len__(self):
return 0
test = Test()
if test:
print('s')
else:
print('f')
结果:f #进的是False分支
test存在也有可能是False,需要考虑__len__与__bool__方法。
len与bool内置方法
如果对象没有定义__len__与__bool__方法则默认为True。
__len__代表长度,只能用int和bool返回。
使用len()时,则会调用对象的__len__,如果没有自定义__len__,求长度的时候会报错。
一旦加入了__bool__则由__bool__来控制对象的取值。
装饰器的副作用
import time
def decorator(func):
def wrapper():
print(time.time())
func()
return wrapper
def f1():
print(f1.__name__)
f1()
结果:f1 #不加装饰器的函数名字
@decorator
def f1():
print(f1.__name__)
f1()
结果:1532492964.0116718
wrapper #闭包函数的名字
python->help(len)->打印出内置说明
加了装饰器之后就无法找到函数的help()了
保证名字不改变:
import time
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper():
print(time.time())
func()
return wrapper
@decorator
def f1():
print(f1.__name__)
f1()
结果:1532493245.2623913
f1
wraps传入了原有函数,所以得知了原函数的信息,然后复制到闭包函数上,则信息得以保存。