好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

13. Pythonic

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              #结果

查看更多关于13. Pythonic的详细内容...

  阅读:39次