Pythonic,简单的翻译就是Python风格,Pythonic code,就是说你写的代码要带有浓厚的Python规范和Python风格。
字典映射代替switch case语句
Python中没有 switch case 语句, switch case 语句就是条件分支语句,例如C#中的switch case语句:
switch (day) { case 0 : dayName = "Sunday"; break; case 1 : dayName = "Monday"; break; case 0 : dayName = "Sunday"; break; case 2 : dayName = "Tuesday"; break; ... default : dayName = "Unknown"; break; }
在Python中,可以使用字典映射来代替 switch case 语句,例如:
day = 0switcher = { 0 : 'Sunday', 1 : 'Monday', 2 : 'Tuesday', ...}day_name = switcher.get(day, 'Unkown')print(day_name)
字典的value还可以是函数,在函数中return相应的值。
列表推导式
Python里面有个很棒的语法糖,它就是 list comprehension,有人把它翻译成“列表推导式”或“列表解析式”。虽然名字叫做 list comprehension,但是这个语法同样适用于dict、set等这一系列可迭代(iterable)数据结构。
out_list = [out_express for out_express in input_list if out_express_condition]
其中的 if 条件判断根据需要可有可无。
示例:l = [i ** 2 for i in range(1, 11) if i >= 5]print(l)[25, 36, 49, 64, 81, 100] #结果
from random import randint d = {'student%d' % i: randint(50, 100) for i in range(1, 6)}print(d){'student1': 64, 'student2': 96, 'student3': 98, 'student4': 81, 'student5': 50} #结果
迭代器与生成器
对于 Iterable 类:>>> from collections.abc import Iterable>>> issubclass(int, Iterable)False>>> issubclass(str, Iterable)True>>> issubclass(list, Iterable)True>>> issubclass(dict, Iterable)True
Iterable 类是提供了 __iter__() 方法的抽象基类。 iterable表示可迭代对象 ,即能够逐一返回其成员项的对象。可迭代对象被可用于for循环以及许多其他需要一个序列的地方( zip() 、 map() 、…)。当一个可迭代对象作为参数传给内置函数 iter() 时,它会返回该对象的迭代器。
使用 isinstance(obj, Iterable) 可以检测一个对象是否已经注册到 Iterable 或者实现 __iter__() 函数;但检测一个对象是否是可迭代对象的唯一可信赖的方法是调用 iter(obj) 。
对于 Iterator 类:>>> from collections.abc import Iterator>>> issubclass(int, Iterator)False>>> issubclass(str, Iterator)False>>> issubclass(list, Iterator)False>>> issubclass(dict, Iterator)False
Iterator 类是提供了 __iter__() 和 __next__() 方法的抽象基类,它继承 Iterable 类。 iterator表示迭代器对象 ,即用来表示一连串数据流的对象。重复调用迭代器的 __next__() 方法(或将其传给内置函数 next() )将逐个返回流中的项,迭代器具有一次性。
迭代器必须具有 __iter__() 方法用来返回该迭代器对象自身,因此 迭代器对象必定也是可迭代对象,但可迭代对象不一定是迭代器对象 。
Iterable 与 Iterator 区别:判断是否是 Iterable 与 Iterator :
isinstance(obj, Iterable)isinstance(obj, Iterator)
凡是可以for循环的,都是Iterable;凡是可以 next() 的,都是Iterator。Iterable是一次性消费的,不同的Iterable之间没有关联 。Python中的for循环就是通过 next() 实现的。
集合数据类型如list、truple、dict、str,都是Itrable不是Iterator,但可以通过 iter() 函数获得一个Iterator对象。
对于 generator 函数:在 Python 中,使用了 yield 关键字的函数被称为生成器generator 。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值,并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
生成器分类:
1、生成器函数:常规函数定义,但是使用yield语句而不是return语句返回结果,yield语句一次返回一个结果,可以使用多次,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
2、生成器表达式:类似列表推导式,生成器返回按需产生结果的一个对象,而不是一次构建一个完整的结果列表。
生成器优点:
在需要的时候才产生结果,不是立即产生结果。
None
Python中的None表示空值(空对象),是一个特殊的常量,None有自己的数据类型 NoneType 。
None不是False None不是0 None不是空字符串、空列表 None和任何其他的数据类型比较永远返回False 你可以将None赋值给任何变量,但是你不能创建其它的NoneType对象
对于Python中几乎所有的对象,在if逻辑判断时,与bool类型都有对应关系:
print(bool(None))print(bool(''))print(bool([]))print(bool(()))print(bool({}))print(bool(set()))False #结果FalseFalseFalseFalseFalse
None默认与bool值对应关系为False。但当判空操作时,可以使用 if var 或 if not var 对变量var进行判空,不建议使用 if var is None 或 if var is not None 。
内置方法 __len__() 与 __bool__()
对象的bool值由Python内置的 __bool__() 和 __len__() 方法决定, __bool__() 方法优先于 __len__() 方法。Python3的 __bool__() 方法替代了Python2的 __nonzero__() 方法。
object.__bool__(self)
调用此方法以实现真值检测以及内置函数 bool() 。 __bool__() 方法必须返回bool类型(True或False)。如果未定义此方法,则会查找并调用 __len__() 方法并在其返回非零值时视对象的逻辑值为真。如果一个类既未定义 __len__() 也未定义 __bool__() 则视其所有实例的逻辑值为真。
object.__len__(self)
调用此方法以实现内置函数 len() 。 __len__() 方法必须返回int类型或bool类型。。此外,如果一个对象未定义 __bool__() 方法而其 __len__() 方法返回值为零,则在布尔运算中会被视为假值。
对对象调用 bool() 函数时实质上调用的是 __bool__() 方法,调用 len() 函数时实质上调用的是 __len__() 方法。
装饰器的“副作用”
在函数对象中保存着一些函数的元数据,例如:
__name__ 函数的名字 __doc__ 函数文档字符串 __module__ 函数所属模块名 __dict__ 属性字典 __default__ 默认参数元组 ...
在使用装饰器后,再访问上面这些属性时,看到的是内部包裹函数的元数据,原来函数的元数据便丢失了。
示例:def decorator(func): def wrapper(): return func() return wrapper# @decoratordef f1(): print(f1.__name__)f1()f1 #结果
def decorator(func): def wrapper(): return func() return wrapper @decoratordef f1(): print(f1.__name__)f1()wrapper #结果
可以看到,在使用装饰器之后,原函数的的元数据丢失了。
解决“副作用”:可以把 functools.wraps() 函数作为装饰器,用来装饰原装饰器 decorator() 内部的包裹函数 wrapper() ,这样被包裹函数 f1() 的元数据就可以得到保留。
from functools import wrapsdef decorator(func): @wraps(func) def wrapper(): return func() return wrapper @decoratordef f1(): print(f1.__name__)f1()f1 #结果