如果你发现了任何特殊特性,请留言,我会更新的,对于元编程的特性我不打算做列举,大部分的情况不会使用
- 三目运算符:
def abs(n):
return n if n >= 0 else -n
if __name__ == '__main__':
print(abs(-10))
- 列表推导公式
def filte(mylist):
return [n for n in mylist if n > 0]
if __name__ == '__main__':
print(filte([1, 4, -5, 10, -7, 2, 3, -1]))
- 生成器表达式
def filte(mylist):
return (n for n in mylist if n > 0)
if __name__ == '__main__':
for item in filte([1, 4, -5, 10, -7, 2, 3, -1]):
print(item, end=', ')
- 字典推导公式
def filter(mydict):
return {key: value for key, value in prices.items() if value > 200}
if __name__ == '__main__':
prices = {
'ACME' : 45.23,
'AAPL' : 612.78,
'IBM' : 205.55,
'HPQ' : 37.20,
'FB' : 10.75
}
print(filter(prices))
- 多值赋值
if __name__ == '__main__':
a, b = 1, 2
print(a, b)
- 交换数值
if __name__ == '__main__':
a, b = 1, 2
a, b = b, a
print(a, b)
- 列表赋值
if __name__ == '__main__':
a, b = [1, 2]
print(a, b)
- 元组赋值
if __name__ == '__main__':
a, b = (1, 2)
print(a, b)
- * 表达式
if __name__ == '__main__':
a, *b, c = 1, 2, 3, 4
print(a, b, c)
运行结果
1 [2, 3] 4
该表达式可以运用在列表和元组中
- 函数返回多值
def fun():
return 1, 2
if __name__ == '__main__':
a, b = fun()
print(a, b)
函数返回多值的本质是返回了一个元组
- 迭代器和可迭代对象
if __name__ == '__main__':
l = [1, 2 ,3, 4]
for item in l:
print(item, end=',')
print()
it = iter(l)
while True:
try:
item = next(it)
print(item, end=',')
except StopIteration:
break
- 因为列表是可迭代对象,所以 for 语句才能正常的工作,基本的实现原理是 while 语句块,首先使用 iter() 函数生成一个迭代器,然后,使用 next() 返回一个当前迭代的对象,重点是,当所有对象都被迭代了,next() 函数会抛出 StopIteration 异常。
- 所谓的可迭代对象,是因为内部实现了 __iter__() 方法和 __next__() 方法,前者是 iter() 函数使用的,后者是 next() 函数使用的,StopIteration 也就是在 __next__() 方法中抛出的。
- 生成器
下面的网址很好的解释了生成器的原理,如果不理解这个原理,很难理解生成器相关的其他知识
https://segmentfault.com/a/1190000011330511
https://github.com/aosabook/500lines/blob/master/crawler/crawler.markdown#how-python-generators-work
yield 关键字可以将普通函数或者普通方法变成一个生成器类,当调用这个函数或者方法的时候,会返回一个生成器对象,重点是生成器对象封装了 __iter__() 方法和 __next__() 方法, 所以生成器对象是可迭代对象,实现的基本原理参考上述网址,简单的说就是生成器类封装了函数的调用堆栈,所有的函数调用信息被保留在一个内部栈成员中
class Node:
def __init__(self, value):
self.value = value
self.children = []
def __repr__(self):
return 'None({!r})'.format(self.value)
def add_child(self, node):
self.children.append(node)
def __iter__(self):
return iter(self.children)
def depth_first(self):
yield self
for c in self:
yield from c.depth_first()
if __name__ == '__main__':
root = Node(0)
child1 = Node(1)
child2 = Node(2)
root.add_child(child1)
root.add_child(child2)
child1.add_child(Node(3))
child1.add_child(Node(4))
child2.add_child(Node(5))
for ch in root.depth_first():
print(ch, end=',')
这段代码中 实现了 __iter__ 表明 Node 类是可迭代的,重点是,depth_first() 方法是一个生成器的函数,这个方法的调用会返回一个生成器的对象,其中 yield from 会把语句的返回值返回给 main 函数的 for 语句,供 for 语句消费,总体来说,我不觉得这个代码好理解,如果是我,我会把 depth_first() 的方法中的 for 语句,替换成对成员变量 children 的直接访问,这样或许好理解一点。
- 以索引-值对的形式迭代序列 (内建函数 enumerate())
if __name__ == '__main__':
my_list = ['a', 'b', 'c']
for idx, val in enumerate(my_list):
print(idx, val)
运行结果:
0 a
1 b
2 c
- 同时迭代多个序列(内建函数 zip())
if __name__ == '__main__':
a = [1, 2, 3]
b = ['a', 'b', 'c', 'd']
for i in zip(a, b):
print(i)
运行结果:
(1, 'a')
(2, 'b')
(3, 'c')
注意 zip 的迭代长度是最短的输入序列的长度,如果不想使用这个特性,可以使用 itertools.ziplongest() 来代替 zip()