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 = 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__()方法用来返回该迭代器对象自身,因此迭代器对象必定也是可迭代对象,但可迭代对象不一定是迭代器对象

  • IterableIterator区别:

判断是否是IterableIterator

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 varif not var对变量var进行判空,不建议使用if var is Noneif 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              #结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值