string = "I can fly" new_list = [i for i in string] new_list1 = [i+"1"for i in string] new_list2 = [ord(i) for i in string] print(new_list) print(new_list1) print(new_list2)
color = ["black", "white"] size = ["S", "M", "L"]
shirt = [(i, j) for i in color for j in size] print(shirt)
>>> string = "i can fly" >>> (char for char in string) <generator object <genexpr> at 0x7f7a5bac17d8> >>> tuple(ord(char) for char in string) (105, 32, 99, 97, 110, 32, 102, 108, 121)
如果 genexps 是一个函数调用过程中的唯一参数,就不需要再用括号把它围起来
用生成器表达式实现一个笛卡尔积:
1 2 3 4 5 6 7 8
for tshirt in ("%s %s"%(c,s) for c in colors for s in sizes): print(tshirt)
print("-"*10)
for i in colors: for j in sizes: print(i, j)
输出结果
1 2 3 4 5 6 7 8 9 10 11 12 13
black S black M black L white S white M white L ---------- black S black M black L white S white M white L
元组的相对不可变性
元组中不可变的是元素的标识(id), 而元组的值会随着引用的可变对象的变化而变化
1 2 3 4 5 6 7 8
>>> tu = (1,2,[3,4]) >>> tu[0] = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple'object does not support item assignment >>> tu[-1].append(10) >>> tu (1, 2, [3, 4, 10])
>>> Point = namedtuple('Point', ['x', 'y']) # ('Point', 'x y') is ok >>> Point.__doc__ # docstring for the new class 'Point(x, y)' >>> p = Point(11, y=22) # instantiate with positional args or keywords >>> p[0] + p[1] # indexable like a plain tuple 33 >>> x, y = p # unpack like a regular tuple >>> x, y (11, 22) >>> p.x + p.y # fields also accessible by name 33 >>> d = p._asdict() # convert to a dictionary >>> d['x'] 11 >>> Point(**d) # convert from a dictionary Point(x=11, y=22) >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields Point(x=100, y=22)
>>> my_proxy['1'] = 10 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'mappingproxy'object does not support item assignment
# CPython报错: # UnboundLocalError: local variable 'g_name' referenced before assignment
nonlocal
函数嵌套定义时,内部函数想要修改外部函数的变量,需要使用 nonlocal关键字,其大致与 global 使用方法相同。 在内部函数中,如果没用 nonlocal, 用的是 global, 则会从全局变量中寻找
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defGreet(): hi = "hi" hello = "hello" keep = True defOne(): nonlocal hi hi = 1 hello = 1 print("in One: ",hi,hello,keep)
One() print("in Greet:", hi,hello,keep) return One
Greet()
输出:
1 2
in One: 1 1 True in Greet: 1 hello True
嵌套函数
嵌套函数的内部函数有其生命周期,在其外部函数的内才可以调用
例如:
1 2 3 4 5 6 7 8 9
defA(): print("A") defB(): print("B") defC(): print("C") B() C() # NameError: name 'C' is not defined A()
闭包 (closure)
Fluent Python: a closure is function with an extended scope that encompasses non-global variables referenced in the body of the function but not defined there
#原始函数 defEvenCounter( min_num: int = 0, max_num: int = 10**6, ):
count = 0 for i inrange(min_num, max_num): if i%2 == 0: count += 1 print(" this is OriginalFunction, count is %d" %count) return count
#不用语法糖,调用TimerDecorator来增强原始的EvenCounter Function = TimerDecorator(EvenCounter)
# 调用函数
num = Function(max_num = 10) print("\nCalled ImprovedFunction") print("return num is ", num)
使用语法糖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# 原始函数 # 添加@xxx @TimerDecorator defEvenCounter( min_num: int = 0, max_num: int = 10**6, ):
count = 0 for i inrange(min_num, max_num): if i%2 == 0: count += 1 print(" this is OriginalFunction, count is %d" %count) return count
# 直接用原始函数的名字就行 num = EvenCounter(max_num = 10) print("\nCalled ImprovedFunction") print("return num is ", num)
效果
两种使用方法效果一样, 终端输出如下:
1 2 3 4 5 6 7
<wrapper_head is here>, start_time is 0.022420 this is OriginalFunction, count is 5 <wrapper_tail is here>, end_time is 0.022449 <cost in time>: 2.9000000000001247e-05
defImprovedFunction(*args, **kargs): #增强后的函数 print("in ImprovedFunction", text) start_time = time.clock() print("<wrapper_head is here>, start_time is %f" %start_time)
ret = Func(*args, **kargs) #原始函数
end_time = time.clock() print("<wrapper_tail is here>, end_time is %f" %end_time) print("<cost in time>: ", end_time - start_time) return ret
return ImprovedFunction return Decorator
不使用语法糖的用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defOddCounter( min_num: int = 0, max_num: int = 10**5, ): count = 0 for i inrange(min_num, max_num): if i%2 != 0: count += 1 print(" this is OriginalFunction, count is %d" %count) return count
#不用语法糖 Function = (LogDecorator("2021.5.30", 2))(OddCounter) Function()
使用语法糖
1 2 3 4 5 6 7 8 9 10 11 12 13 14
@LogDecorator(text="2021.5.30",num=2) defOddCounter( min_num: int = 0, max_num: int = 10**5, ): count = 0 for i inrange(min_num, max_num): if i%2 != 0: count += 1 print(" this is OriginalFunction, count is %d" %count) return count
# 同理,直接使用原函数名 OddCounter()
效果
两种使用方法效果一样, 终端输出如下:
1 2 3 4 5 6 7
2021.5.30 2021.5.30 in ImprovedFunction 2021.5.30 <wrapper_head is here>, start_time is 0.023687 this is OriginalFunction, count is 50000 <wrapper_tail is here>, end_time is 0.028648 <cost in time>: 0.004961
import time # 使用递归================================================================ defFibonacci(n): if n < 2: return n return Fibonacci(n-1) + Fibonacci(n-2)
# 使用循环 + 数组========================================================= from array import array defLoopFibonacci(n): if n < 2: return n fibo = array('i') fibo.append(0) fibo.append(1) index = 2 while index <= n: fibo.append(fibo[index-1] + fibo[index-2]) index += 1 return fibo[-1]