Python 语言特殊特性

如果你发现了任何特殊特性,请留言,我会更新的,对于元编程的特性我不打算做列举,大部分的情况不会使用

  • 三目运算符:
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
  1. 因为列表是可迭代对象,所以 for 语句才能正常的工作,基本的实现原理是 while 语句块,首先使用 iter() 函数生成一个迭代器,然后,使用 next() 返回一个当前迭代的对象,重点是,当所有对象都被迭代了,next() 函数会抛出 StopIteration 异常。
  2. 所谓的可迭代对象,是因为内部实现了 __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()

你可能感兴趣的:(Python 语言特殊特性)