函数高级

迭代器

  1. iterator = iter([0, 5, 10, 15])
  2. print(iterator) # 迭代器
  3. print(next(iterator)) # 使用next进行迭代
  4. print(next(iterator))
  5. print(next(iterator))
  6. print(next(iterator))
  1. <list_iterator object at 0x00000270CB3A9388>
  2. 0
  3. 5
  4. 10
  5. 15

生成器

  1. # 计算数列每次都要从1开始算,保留函数运行装填,之后生成序列
  2. def fibonacci(n):
  3. a, b, counter = 0, 1, 0
  4. while True:
  5. if (counter > n):
  6. return
  7. yield a # yield 代表该函数是生成器,返回一个数后暂停,需要下一个数时继续运行
  8. a, b = b, a + b
  9. counter += 1
  10. fibonacci(10) # 生成器
  1. <generator object fibonacci at 0x00000270CB3A58C8>
  1. list(fibonacci(10))
  1. [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
  1. generator = fibonacci(10)
  2. for i in range(10):
  3. print(next(generator), end=',') # 生成使用next取值
  1. 0,1,1,2,3,5,8,13,21,34,
  1. generator = fibonacci(10)
  2. for i in generator: # 直接for也可以
  3. print(i, end=',')
  1. 0,1,1,2,3,5,8,13,21,34,55,

闭包

  1. # 闭包
  2. def power(n):
  3. def func(m):
  4. return m**n
  5. return func
  1. power2 = power(2)
  2. power5 = power(5)
  3. power10 = power(10)
  4. print(power2(4))
  5. print(power5(4))
  6. print(power10(4))
  1. 16
  2. 1024
  3. 1048576

装饰器

  1. def square(n):
  2. print(f'square {n}')
  3. return n**2
  4. square(2)
  1. square 2
  2. 4

对函数进行加强,打印执行时的日期

  1. import time
  2. def decorator(func):
  3. def wrapper(*args, **kwargs):
  4. print(time.time())
  5. return func(*args, **kwargs)
  6. return wrapper
  1. @decorator
  2. def square(n):
  3. print(f'square {n}')
  4. return n**2
  1. square(2)
  1. 1617971796.1864774
  2. square 2
  3. 4
  1. hello = lambda: print('hello')
  2. hello = decorator(hello)
  3. hello()
  1. 1617971847.2084067
  2. hello

函数是一等公民

函数可以传递

  1. # 使用字典完成类似cpp中的switch
  2. def apple():
  3. return 5
  4. def banana():
  5. return 3
  6. def orange():
  7. return 4
  8. get_price = {'apple': apple, 'banana': banana, 'orange': orange}
  9. get_price['apple']()
  1. 5

函数作用域

  1. total = 2
  2. arg = 10
  3. def sum(arg1, arg2):
  4. total = arg1+arg2+arg # 函数有自己的作用域,可引用外部值
  5. return total
  6. print(total)
  7. print(sum(1, 2))
  8. print(total)
  1. 2
  2. 13
  3. 2
  1. total = 2
  2. arg = 10
  3. def sum(arg1, arg2):
  4. global total # 使用全局变量中的total
  5. total = arg1+arg2+arg # 函数有自己的作用域,可引用外部值
  6. return total
  7. print(total)
  8. print(sum(1, 2))
  9. print(total)
  1. 2
  2. 13
  3. 13

nonlocal 在一个局部作用域中使用外层的变量

  1. def some(func):
  2. a = 'I am a'
  3. def some1(*args, **kwargs):
  4. print(locals())
  5. nonlocal a
  6. print(locals())
  7. print(a)
  8. func(*args, **kwargs)
  9. return some1
  10. some(print)(10)
  1. {'args': (10,), 'kwargs': {}, 'a': 'I am a', 'func': <built-in function print>}
  2. {'args': (10,), 'kwargs': {}, 'a': 'I am a', 'func': <built-in function print>}
  3. I am a
  4. 10
  1. @some
  2. def hello():
  3. print('hello')
  1. hello()
  1. {'args': (), 'kwargs': {}, 'a': 'I am a', 'func': <function hello at 0x000001529947CB88>}
  2. {'args': (), 'kwargs': {}, 'a': 'I am a', 'func': <function hello at 0x000001529947CB88>}
  3. I am a
  4. hello
  1. globals()['hello']
  1. <function __main__.some.<locals>.some1(*args, **kwargs)>
  1. globals()['sssimon'] = 10
  2. print(sssimon)
  1. 10
  1. locals() is globals()
  1. True

  1. class A:
  2. pass
  1. a = A()
  2. print(A)
  3. print(a)
  4. print(isinstance(a, A))
  1. <class '__main__.A'>
  2. <__main__.A object at 0x00000270CB354708>
  3. True
  1. class A:
  2. def __init__(self, x):
  3. self.x = x
  1. a = A(5)
  2. print(a.x)
  3. print(getattr(a,'x'))
  1. 5
  2. 5
  1. class A:
  2. def __init__(self, x):
  3. self.x = x
  4. def get_x(self):
  5. return self.x
  1. a = A(5)
  2. print(a.get_x()) # self只是个代号,用于传入该对象
  1. 5
  1. A.get_x(a) # 其实这样也可以
  1. 5
  1. a.y = 10 # 外面也可以设置属性
  2. print(hasattr(a,'y'))
  3. setattr(a,'z',15)
  4. print(getattr(a,'z'))
  5. delattr(a,'z')
  1. True
  2. 15
  1. class A:
  2. z = 10
  3. def __init__(self, x):
  4. self.x = x
  5. def get_x(self):
  6. return self.x
  1. a = A(5)
  2. print(a.x)
  3. print(a.z)
  4. print(A.z)
  5. print(A.x)
  1. 5
  2. 10
  3. 10
  4. ---------------------------------------------------------------------------
  5. AttributeError Traceback (most recent call last)
  6. <ipython-input-103-0496bfe801cf> in <module>
  7. 3 print(a.z)
  8. 4 print(A.z)
  9. ----> 5 print(A.x)
  10. AttributeError: type object 'A' has no attribute 'x'
  1. class A:
  2. z = 10
  3. def __init__(self, x):
  4. self.x = x
  5. def get_x(self):
  6. return self.x
  7. @classmethod
  8. def get_z(cls):
  9. return cls.z
  10. @staticmethod
  11. def hello():
  12. return 'hello'

三种方法

  • 实例方法,调用时会把实例作为第一个参数传递给self参数
  • 类方法,调用时会把类作为第一个参数传递给cls参数
  • 静态方法,调用时并不需要传递类或者实例
  1. a = A(5)
  2. print(a.get_x())
  3. print(A.get_z())
  4. print(a.hello())
  5. print(A.hello())
  1. 5
  2. 10
  3. hello
  4. hello

类继承

  1. #
  2. class A:
  3. z = 10
  4. def __init__(self, x):
  5. self.x = x
  6. def get_x(self):
  7. return self.x
  8. class B(A):
  9. def __init__(self, x, y):
  10. self.y = y
  11. # 也可以写成一下两种方式
  12. # A.__init__(self, x) 指定父类进行初始化
  13. # super(B,self).__init__(x) #B类的self自动寻找父类进行初始化
  14. super().__init__(x) # 自动寻找父类进行初始化
  15. def get_y(self):
  16. return self.y
  1. b = B(1, 2)
  1. print(b.x, b.y)
  1. 1 2
  1. print(b.get_x(), b.get_y())
  1. 1 2
  1. B.__bases__ # 该变量存储了父类
  1. (__main__.A,)
  1. print(issubclass(B, A))
  1. True
  1. 函数重写
  1. class A:
  2. def __init__(self, x):
  3. self.x = x
  4. def get_x(self):
  5. return self.x
  6. class B(A):
  7. def __init__(self, x, y):
  8. self.y = y
  9. super().__init__(x) # 自动寻找父类进行初始化
  10. def get_x(self):
  11. return super().get_x()+100
  12. def get_y(self):
  13. return self.y
  1. b = B(1, 2)
  2. print(b.get_x())
  1. 101

魔法方法(dunder方法)

  1. class A:
  2. def __init__(self, length=10, value=0):
  3. try:
  4. length = int(length)
  5. except:
  6. raise Exception
  7. self.x = [value for i in range(length)]
  8. def __len__(self):
  9. return len(self.x)
  10. def __getitem__(self, key):
  11. try:
  12. key = int(key)
  13. assert key < len(self.x)
  14. except:
  15. raise Exception
  16. return self.x[key]
  17. def __setitem__(self, key, value):
  18. try:
  19. key = int(key)
  20. assert key < len(self.x)
  21. except:
  22. raise Exception
  23. self.x[key] = value
  24. return value
  25. def __str__(self):
  26. return f'{self.__class__.__name__} with value {self.x}'
  27. __repr__ = __str__
  1. a = A(5, 1)
  2. print(a)
  3. print(len(a))
  4. print(a[3])
  5. print(a['3'])
  6. a['2'] = 10
  7. print(a)
  1. A with value [1, 1, 1, 1, 1]
  2. 5
  3. 1
  4. 1
  5. A with value [1, 1, 10, 1, 1]

魔法方法较多,均为前后双下划线形式,不在赘述

python也支持多继承,多继承较为麻烦,不再教学

  1. # 类型注释
  1. # 执行的是静态类型检查
  2. a: str = 'hello_world'
  3. def hello(a: str) -> int:
  4. print(a)
  5. return 1
  1. hello(a)
  1. hello_world
  2. 1
  1. hello(1) # 不是强制的
  1. 1
  2. 1

你可以使用pyright mypy pytype pyre的类型检查工具

  1. class A:
  2. def __init__(self, x, y):
  3. self.x = x
  4. self.y = y
  1. a = A(1, 2)
  2. a.z = 3
  1. # __slots__ 规定类的属性和方法,不能动态增加
  2. class A:
  3. __slots__ = ('x', 'y')
  4. def __init__(self, x, y):
  5. self.x = x
  6. self.y = y
  1. a = A(1, 2)
  2. a.z = 3
  1. ---------------------------------------------------------------------------
  2. AttributeError Traceback (most recent call last)
  3. <ipython-input-123-b84eba08908b> in <module>
  4. 1 a = A(1, 2)
  5. ----> 2 a.z = 3
  6. AttributeError: 'A' object has no attribute 'z'
  1. # property 解决属性暴露的问题
  2. class A:
  3. __slots__ = ('x', 'y')
  4. def __init__(self, x, y):
  5. self.x = x
  6. self.y = y
  1. class B:
  2. def __init__(self, x):
  3. self._x = x
  4. @property
  5. def x(self):
  6. return self._x
  1. b = B(1)
  1. print(b.x)
  2. b.x = 10
  1. 1
  2. ---------------------------------------------------------------------------
  3. AttributeError Traceback (most recent call last)
  4. <ipython-input-127-0934f5f17514> in <module>
  5. 1 print(b.x)
  6. ----> 2 b.x = 10
  7. AttributeError: can't set attribute
  1. class B:
  2. def __init__(self, x):
  3. self._x = x
  4. @property
  5. def x(self):
  6. return self._x
  7. @x.setter
  8. def x(self, value):
  9. self._x = value
  10. @x.deleter
  11. def x(self):
  12. del self._x
  1. b._x = 10
  2. print(b.x)
  1. 10
  • 前置单下划线 _var :命名约定,用来表示该名称仅在内部使用。一般对 Python解释器没有特殊含义(通配符导入除外),只能作为对程序员的提示。
  • 后置单下划线 var_ :命名约定,用于避免与 Python关键字发生命名冲突。
  • 前置双下划线 __var :在类环境中使用时会触发名称改写,对 Python解释器有特殊含义。
  • 前后双下划线 var :表示由 Python 语言定义的特殊方法。在自定义的属性中要避免使用这种命名方式。
  • 单下划线 _ :有时用作临时或无意义变量的名称(“不关心”)。此外还能表示 Python REPL会话中上一个表达式的结果。
  1. class Test:
  2. def __init__(self):
  3. self.foo = 11
  4. self._bar = 23
  5. self.__bar = 42
  1. dir(Test())
  1. ['_Test__bar',
  2. '__class__',
  3. '__delattr__',
  4. '__dict__',
  5. '__dir__',
  6. '__doc__',
  7. '__eq__',
  8. '__format__',
  9. '__ge__',
  10. '__getattribute__',
  11. '__gt__',
  12. '__hash__',
  13. '__init__',
  14. '__init_subclass__',
  15. '__le__',
  16. '__lt__',
  17. '__module__',
  18. '__ne__',
  19. '__new__',
  20. '__reduce__',
  21. '__reduce_ex__',
  22. '__repr__',
  23. '__setattr__',
  24. '__sizeof__',
  25. '__str__',
  26. '__subclasshook__',
  27. '__weakref__',
  28. '_bar',
  29. 'foo']
  1. dir(__builtins__)
  1. ['ArithmeticError',
  2. 'AssertionError',
  3. 'AttributeError',
  4. 'BaseException',
  5. 'BlockingIOError',
  6. 'BrokenPipeError',
  7. 'BufferError',
  8. 'BytesWarning',
  9. 'ChildProcessError',
  10. 'ConnectionAbortedError',
  11. 'ConnectionError',
  12. 'ConnectionRefusedError',
  13. 'ConnectionResetError',
  14. 'DeprecationWarning',
  15. 'EOFError',
  16. 'Ellipsis',
  17. 'EnvironmentError',
  18. 'Exception',
  19. 'False',
  20. 'FileExistsError',
  21. 'FileNotFoundError',
  22. 'FloatingPointError',
  23. 'FutureWarning',
  24. 'GeneratorExit',
  25. 'IOError',
  26. 'ImportError',
  27. 'ImportWarning',
  28. 'IndentationError',
  29. 'IndexError',
  30. 'InterruptedError',
  31. 'IsADirectoryError',
  32. 'KeyError',
  33. 'KeyboardInterrupt',
  34. 'LookupError',
  35. 'MemoryError',
  36. 'ModuleNotFoundError',
  37. 'NameError',
  38. 'None',
  39. 'NotADirectoryError',
  40. 'NotImplemented',
  41. 'NotImplementedError',
  42. 'OSError',
  43. 'OverflowError',
  44. 'PendingDeprecationWarning',
  45. 'PermissionError',
  46. 'ProcessLookupError',
  47. 'RecursionError',
  48. 'ReferenceError',
  49. 'ResourceWarning',
  50. 'RuntimeError',
  51. 'RuntimeWarning',
  52. 'StopAsyncIteration',
  53. 'StopIteration',
  54. 'SyntaxError',
  55. 'SyntaxWarning',
  56. 'SystemError',
  57. 'SystemExit',
  58. 'TabError',
  59. 'TimeoutError',
  60. 'True',
  61. 'TypeError',
  62. 'UnboundLocalError',
  63. 'UnicodeDecodeError',
  64. 'UnicodeEncodeError',
  65. 'UnicodeError',
  66. 'UnicodeTranslateError',
  67. 'UnicodeWarning',
  68. 'UserWarning',
  69. 'ValueError',
  70. 'Warning',
  71. 'WindowsError',
  72. 'ZeroDivisionError',
  73. '__IPYTHON__',
  74. '__build_class__',
  75. '__debug__',
  76. '__doc__',
  77. '__import__',
  78. '__loader__',
  79. '__name__',
  80. '__package__',
  81. '__spec__',
  82. 'abs',
  83. 'all',
  84. 'any',
  85. 'ascii',
  86. 'bin',
  87. 'bool',
  88. 'breakpoint',
  89. 'bytearray',
  90. 'bytes',
  91. 'callable',
  92. 'chr',
  93. 'classmethod',
  94. 'compile',
  95. 'complex',
  96. 'copyright',
  97. 'credits',
  98. 'delattr',
  99. 'dict',
  100. 'dir',
  101. 'display',
  102. 'divmod',
  103. 'enumerate',
  104. 'eval',
  105. 'exec',
  106. 'filter',
  107. 'float',
  108. 'format',
  109. 'frozenset',
  110. 'get_ipython',
  111. 'getattr',
  112. 'globals',
  113. 'hasattr',
  114. 'hash',
  115. 'help',
  116. 'hex',
  117. 'id',
  118. 'input',
  119. 'int',
  120. 'isinstance',
  121. 'issubclass',
  122. 'iter',
  123. 'len',
  124. 'license',
  125. 'list',
  126. 'locals',
  127. 'map',
  128. 'max',
  129. 'memoryview',
  130. 'min',
  131. 'next',
  132. 'object',
  133. 'oct',
  134. 'open',
  135. 'ord',
  136. 'pow',
  137. 'print',
  138. 'property',
  139. 'range',
  140. 'repr',
  141. 'reversed',
  142. 'round',
  143. 'set',
  144. 'setattr',
  145. 'slice',
  146. 'sorted',
  147. 'staticmethod',
  148. 'str',
  149. 'sum',
  150. 'super',
  151. 'tuple',
  152. 'type',
  153. 'vars',
  154. 'zip']
  1. try:
  2. 1/0
  3. except ZeroDivisionError:
  4. ... # elipse
  1. Ellipsis
  1. class A:
  2. a = 10
  1. vars(A)
  1. mappingproxy({'__module__': '__main__',
  2. 'a': 10,
  3. '__dict__': <attribute '__dict__' of 'A' objects>,
  4. '__weakref__': <attribute '__weakref__' of 'A' objects>,
  5. '__doc__': None})