Python [3]

陷阱

Posted by ZYT on November 19, 2018

延迟绑定的闭包

def create_multipliers():
    return [lambda x : i * x for i in range(5)]

for multiplier in create_multipliers():
    print(multiplier(2))

""" output
8
8
8
8
8
"""

错误的解读:与 lambda 有关

def create_multipliers():
    multipliers = []

    for i in range(5):
        def multiplier(x):
            return i * x
        multipliers.append(multiplier)
    return multipliers

for multiplier in create_multipliers():
    print(multiplier(2))

""" output
8
8
8
8
8
"""

解决方案:

1、预先计算函数默认值

def create_multipliers():
    return [lambda x, i=i : i * x for i in range(5)]

for multiplier in create_multipliers():
    print(multiplier(2))

""" output
0
2
4
6
8
"""

2、functools.partial 函数

from functools import partial
from operator import mul

def create_multipliers():
    return [partial(mul, i) for i in range(5)]

for multiplier in create_multipliers():
    print(multiplier(2))

""" output
0
2
4
6
8
"""

可变的默认参数

def append_to(element, []):
    to.append(element)
    return to

first_list = append_to(10)
print(first_list)

""" output
[10]
"""

second_list = append_to(20)
print(second_list)

""" output
[10, 20]
"""

新列表仅会在函数定义时被创建一次,后续每次函数调用都是用同一个列表

解决方案:

def append_to(element, to=None):
    if to is None:
        to = []
    to.append(element)
    return to

创建一个包含 N 个相同对象的列表

create_list = [[] for __ in range(4)]

许多 Python 风格指南建议使用单下划线 _ 抛弃值,其问题在于它通常被用作 gettext.gettext() 函数的别名,同时在交互模式下用来保存上一次操作的值。