a = [x * x for x in range(10)] # 列表生成式子生成一个list |
print(a) |
# 打印: |
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] |
g = (x * x for x in range(10)) # 列表生成式生成一个生成器,只需将[]替换为() |
print(g) |
# 打印: |
# <generator object <genexpr> at 0x1022ef630> |
编写一个简单的生成器
def fib(max): |
n, a, b = 0, 0, 1 |
while n < max: |
yield b # 经过迭代操作后生成一个迭代值 |
a, b = b, a + b |
n = n + 1 |
return 'done' # 如果已无迭代值,则输出'done' |
f1 = fib(10) |
# 最后一个迭代值出来后,将停止迭代,跳出for语句 |
for i in f1: |
print(i) |
# 打印: |
# 1 1 2 3 5 8 13 21 34 55 |
f2 = fib(10) |
# 如果想单个迭代,可使用next函数 |
print(next(f2)) |
# 打印: |
# 1 |
print(next(f2)) |
# 打印: |
# 1 |
print(next(f2)) |
# 打印: |
# 2 |
# 这里因为每次fib被next调用时都会生成一个临时的生成器对象,所以输出只会打印第一次的迭代值“1”。 |
print(next(fib(10))) |
print(next(fib(10))) |
print(next(fib(10))) |
map/reduce
map
def f(i): |
return i * i |
x = [1, 2, 3, 4, 5, 6, 7, 8] |
# map()函数接收两个参数,一个是函数,一个是Iterable。map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回 |
y = map(f, x) |
# 需将Iterator转换为list才能打印出里面的元素 |
print(list(y)) |
# 打印: |
# [1, 4, 9, 16, 25, 36, 49, 64] |
reduce
# reduce包含在functools包中,使用时需导入 |
from functools import reduce |
def fn(x, y): |
return x * 10 + y |
def str2int(x): |
strDict = { |
"0": 0, |
"1": 1, |
"2": 2, |
"3": 3, |
"4": 4, |
"5": 5, |
"6": 6, |
"7": 7, |
"8": 8, |
"9": 9, |
} |
return strDict[x] |
# reduce接受两个参数,一个是执行函数(需2个参数),一个是Iterable,其大概运行逻辑是:将Iterable按顺序分别传入执行函数中进行操作,然后将返回值执行函数的一个参数后继续与Iterable后面的元素进行操作,直到Iterable没有元素可迭代为止。 |
ans = reduce(fn, map(str2int, "13579")) |
print(ans) |
# 打印: |
# 13579 |
filter
def is_odd(n): |
return n % 2 == 1 |
# 和map()类似,filter()也接收一个函数和一个序列。不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。filter返回值是一个Iterator,不方便打印其中的元素,所以将其转换为一个Iterable |
print(list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))) |
# 打印: |
# [1, 5, 9, 15] |
装饰器
from functools import wraps |
# 一、装饰器的基本语法 |
def log(f): |
# 如果需要打印真正执行操作的函数名而不是wrapper函数名,则需要导入functiools里的wraps |
@wraps(f) |
# 如果需要添加装饰器的函数含有参数,则wrapper也需要填入参数(*args, **kw)。 |
def wrapper(*args, **kw): |
print('call %s():' % f.__name__) |
return f(*args, **kw) |
return wrapper |
# 这个函数用来筛出序列中的偶数,我们如果要针对这个操作插入一些测试/信息说明的话可以使用装饰器来实现。 |
@log |
def func(nums: list) -> list: |
return list(filter(lambda x: x % 2 == 0, nums)) |
print(func.__name__) |
print(func([x for x in range(10)])) |
# 打印: |
# call func(): |
# [0, 2, 4, 6, 8] |
# 二、带参数的装饰器语法 |
# 如果装饰器想要接受参数,则需要额外嵌套一层函数。 |
def log2(text): |
def decorator(f): |
@wraps(f) |
def wrapper(*args, **kw): |
print('%s %s():' % (text, f.__name__)) |
return f(*args, **kw) |
return wrapper |
return decorator |
@log2('execute') |
def func(nums: list) -> list: |
return list(filter(lambda x: x % 2 == 0, nums)) |
print(func.__name__) |
print(func([x for x in range(10)])) |
# 打印: |
# func |
# execute func(): |
# [0, 2, 4, 6, 8] |
偏函数
from functools import partial |
# 当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。 |
# 普通写法: |
# def int2(x, base=2) |
# return int(x, base) |
# 使用partial |
int2 = partial(int, base=2) |
print(int2('10010')) |
# 打印: |
# 18 |
__slots__
# python的灵活性可以使类中的属性能够随意添加,为了保证代码的工整和已读可在类中添加一个__slots__变量 |
class Student: |
__slots__ = ('name', 'age') |
s = Student() |
s.name = 'Sam' |
s.age = 16 |
print(s.name, s.age) |
# 打印: |
# Sam 16 |
s.university = "CMU" |
print(s.university) |
# 报出AttributeError异常,提示Student类中没有"university"属性,也无法设置新属性 |
@property
# python中对于类的属性getter/setter方法可用@property来代替,可读性更高。 |
class Student(object): |
@property |
def birth(self): |
return self._birth |
@birth.setter |
def birth(self, value): |
self._birth = value |
# age属性没有设置setter,所以如果对其赋值会报错 |
@property |
def age(self): |
return 2026 - self._birth |
枚举类
from enum import Enum |
# 构建一个枚举类后,可以直接使用Month.Jan......来引用一个常量,也可以像字典一样遍历它们(需访问__members__) |
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) |
for k, v in Month.__members__.items(): |
print(k, v.value) |
# 打印(value属性则是自动赋给成员的int常量,默认从1开始计数): |
# Jan 1 |
# Feb 2 |
# Mar 3 |
# Apr 4 |
# May 5 |
# Jun 6 |
# Jul 7 |
# Aug 8 |
# Sep 9 |
# Oct 10 |
# Nov 11 |
# Dec 12 |
print(Month.Jan) |
# 打印: |
# Month.Jan |
print(Month['Feb']) |
# 打印: |
# Month.Feb |
print(Month.Mar.value) |