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 = 0
switcher = {
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 #结果
False
False
False
False
False
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
# @decorator
def f1():
print(f1.__name__)
f1()
f1 #结果
def decorator(func):
def wrapper():
return func()
return wrapper
@decorator
def f1():
print(f1.__name__)
f1()
wrapper #结果
可以看到,在使用装饰器之后,原函数的的元数据丢失了。
- 解决“副作用”:
可以把functools.wraps()
函数作为装饰器,用来装饰原装饰器decorator()
内部的包裹函数wrapper()
,这样被包裹函数f1()
的元数据就可以得到保留。
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper():
return func()
return wrapper
@decorator
def f1():
print(f1.__name__)
f1()
f1 #结果