函数高级
迭代器
iterator = iter([0, 5, 10, 15])
print(iterator) # 迭代器
print(next(iterator)) # 使用next进行迭代
print(next(iterator))
print(next(iterator))
print(next(iterator))
<list_iterator object at 0x00000270CB3A9388>
0
5
10
15
生成器
# 计算数列每次都要从1开始算,保留函数运行装填,之后生成序列
def fibonacci(n):
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a # yield 代表该函数是生成器,返回一个数后暂停,需要下一个数时继续运行
a, b = b, a + b
counter += 1
fibonacci(10) # 生成器
<generator object fibonacci at 0x00000270CB3A58C8>
list(fibonacci(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
generator = fibonacci(10)
for i in range(10):
print(next(generator), end=',') # 生成使用next取值
0,1,1,2,3,5,8,13,21,34,
generator = fibonacci(10)
for i in generator: # 直接for也可以
print(i, end=',')
0,1,1,2,3,5,8,13,21,34,55,
闭包
# 闭包
def power(n):
def func(m):
return m**n
return func
power2 = power(2)
power5 = power(5)
power10 = power(10)
print(power2(4))
print(power5(4))
print(power10(4))
16
1024
1048576
装饰器
def square(n):
print(f'square {n}')
return n**2
square(2)
square 2
4
对函数进行加强,打印执行时的日期
import time
def decorator(func):
def wrapper(*args, **kwargs):
print(time.time())
return func(*args, **kwargs)
return wrapper
@decorator
def square(n):
print(f'square {n}')
return n**2
square(2)
1617971796.1864774
square 2
4
hello = lambda: print('hello')
hello = decorator(hello)
hello()
1617971847.2084067
hello
函数是一等公民
函数可以传递
# 使用字典完成类似cpp中的switch
def apple():
return 5
def banana():
return 3
def orange():
return 4
get_price = {'apple': apple, 'banana': banana, 'orange': orange}
get_price['apple']()
5
函数作用域
total = 2
arg = 10
def sum(arg1, arg2):
total = arg1+arg2+arg # 函数有自己的作用域,可引用外部值
return total
print(total)
print(sum(1, 2))
print(total)
2
13
2
total = 2
arg = 10
def sum(arg1, arg2):
global total # 使用全局变量中的total
total = arg1+arg2+arg # 函数有自己的作用域,可引用外部值
return total
print(total)
print(sum(1, 2))
print(total)
2
13
13
nonlocal 在一个局部作用域中使用外层的变量
def some(func):
a = 'I am a'
def some1(*args, **kwargs):
print(locals())
nonlocal a
print(locals())
print(a)
func(*args, **kwargs)
return some1
some(print)(10)
{'args': (10,), 'kwargs': {}, 'a': 'I am a', 'func': <built-in function print>}
{'args': (10,), 'kwargs': {}, 'a': 'I am a', 'func': <built-in function print>}
I am a
10
@some
def hello():
print('hello')
hello()
{'args': (), 'kwargs': {}, 'a': 'I am a', 'func': <function hello at 0x000001529947CB88>}
{'args': (), 'kwargs': {}, 'a': 'I am a', 'func': <function hello at 0x000001529947CB88>}
I am a
hello
globals()['hello']
<function __main__.some.<locals>.some1(*args, **kwargs)>
globals()['sssimon'] = 10
print(sssimon)
10
locals() is globals()
True
类
class A:
pass
a = A()
print(A)
print(a)
print(isinstance(a, A))
<class '__main__.A'>
<__main__.A object at 0x00000270CB354708>
True
class A:
def __init__(self, x):
self.x = x
a = A(5)
print(a.x)
print(getattr(a,'x'))
5
5
class A:
def __init__(self, x):
self.x = x
def get_x(self):
return self.x
a = A(5)
print(a.get_x()) # self只是个代号,用于传入该对象
5
A.get_x(a) # 其实这样也可以
5
a.y = 10 # 外面也可以设置属性
print(hasattr(a,'y'))
setattr(a,'z',15)
print(getattr(a,'z'))
delattr(a,'z')
True
15
class A:
z = 10
def __init__(self, x):
self.x = x
def get_x(self):
return self.x
a = A(5)
print(a.x)
print(a.z)
print(A.z)
print(A.x)
5
10
10
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-103-0496bfe801cf> in <module>
3 print(a.z)
4 print(A.z)
----> 5 print(A.x)
AttributeError: type object 'A' has no attribute 'x'
class A:
z = 10
def __init__(self, x):
self.x = x
def get_x(self):
return self.x
@classmethod
def get_z(cls):
return cls.z
@staticmethod
def hello():
return 'hello'
三种方法
- 实例方法,调用时会把实例作为第一个参数传递给self参数
- 类方法,调用时会把类作为第一个参数传递给cls参数
- 静态方法,调用时并不需要传递类或者实例
a = A(5)
print(a.get_x())
print(A.get_z())
print(a.hello())
print(A.hello())
5
10
hello
hello
类继承
#
class A:
z = 10
def __init__(self, x):
self.x = x
def get_x(self):
return self.x
class B(A):
def __init__(self, x, y):
self.y = y
# 也可以写成一下两种方式
# A.__init__(self, x) 指定父类进行初始化
# super(B,self).__init__(x) #B类的self自动寻找父类进行初始化
super().__init__(x) # 自动寻找父类进行初始化
def get_y(self):
return self.y
b = B(1, 2)
print(b.x, b.y)
1 2
print(b.get_x(), b.get_y())
1 2
B.__bases__ # 该变量存储了父类
(__main__.A,)
print(issubclass(B, A))
True
函数重写
class A:
def __init__(self, x):
self.x = x
def get_x(self):
return self.x
class B(A):
def __init__(self, x, y):
self.y = y
super().__init__(x) # 自动寻找父类进行初始化
def get_x(self):
return super().get_x()+100
def get_y(self):
return self.y
b = B(1, 2)
print(b.get_x())
101
魔法方法(dunder方法)
class A:
def __init__(self, length=10, value=0):
try:
length = int(length)
except:
raise Exception
self.x = [value for i in range(length)]
def __len__(self):
return len(self.x)
def __getitem__(self, key):
try:
key = int(key)
assert key < len(self.x)
except:
raise Exception
return self.x[key]
def __setitem__(self, key, value):
try:
key = int(key)
assert key < len(self.x)
except:
raise Exception
self.x[key] = value
return value
def __str__(self):
return f'{self.__class__.__name__} with value {self.x}'
__repr__ = __str__
a = A(5, 1)
print(a)
print(len(a))
print(a[3])
print(a['3'])
a['2'] = 10
print(a)
A with value [1, 1, 1, 1, 1]
5
1
1
A with value [1, 1, 10, 1, 1]
魔法方法较多,均为前后双下划线形式,不在赘述
python也支持多继承,多继承较为麻烦,不再教学
# 类型注释
# 执行的是静态类型检查
a: str = 'hello_world'
def hello(a: str) -> int:
print(a)
return 1
hello(a)
hello_world
1
hello(1) # 不是强制的
1
1
你可以使用pyright mypy pytype pyre的类型检查工具
class A:
def __init__(self, x, y):
self.x = x
self.y = y
a = A(1, 2)
a.z = 3
# __slots__ 规定类的属性和方法,不能动态增加
class A:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
a = A(1, 2)
a.z = 3
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-123-b84eba08908b> in <module>
1 a = A(1, 2)
----> 2 a.z = 3
AttributeError: 'A' object has no attribute 'z'
# property 解决属性暴露的问题
class A:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
class B:
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
b = B(1)
print(b.x)
b.x = 10
1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-127-0934f5f17514> in <module>
1 print(b.x)
----> 2 b.x = 10
AttributeError: can't set attribute
class B:
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
b._x = 10
print(b.x)
10
- 前置单下划线 _var :命名约定,用来表示该名称仅在内部使用。一般对 Python解释器没有特殊含义(通配符导入除外),只能作为对程序员的提示。
- 后置单下划线 var_ :命名约定,用于避免与 Python关键字发生命名冲突。
- 前置双下划线 __var :在类环境中使用时会触发名称改写,对 Python解释器有特殊含义。
- 前后双下划线 var :表示由 Python 语言定义的特殊方法。在自定义的属性中要避免使用这种命名方式。
- 单下划线 _ :有时用作临时或无意义变量的名称(“不关心”)。此外还能表示 Python REPL会话中上一个表达式的结果。
class Test:
def __init__(self):
self.foo = 11
self._bar = 23
self.__bar = 42
dir(Test())
['_Test__bar',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_bar',
'foo']
dir(__builtins__)
['ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'BlockingIOError',
'BrokenPipeError',
'BufferError',
'BytesWarning',
'ChildProcessError',
'ConnectionAbortedError',
'ConnectionError',
'ConnectionRefusedError',
'ConnectionResetError',
'DeprecationWarning',
'EOFError',
'Ellipsis',
'EnvironmentError',
'Exception',
'False',
'FileExistsError',
'FileNotFoundError',
'FloatingPointError',
'FutureWarning',
'GeneratorExit',
'IOError',
'ImportError',
'ImportWarning',
'IndentationError',
'IndexError',
'InterruptedError',
'IsADirectoryError',
'KeyError',
'KeyboardInterrupt',
'LookupError',
'MemoryError',
'ModuleNotFoundError',
'NameError',
'None',
'NotADirectoryError',
'NotImplemented',
'NotImplementedError',
'OSError',
'OverflowError',
'PendingDeprecationWarning',
'PermissionError',
'ProcessLookupError',
'RecursionError',
'ReferenceError',
'ResourceWarning',
'RuntimeError',
'RuntimeWarning',
'StopAsyncIteration',
'StopIteration',
'SyntaxError',
'SyntaxWarning',
'SystemError',
'SystemExit',
'TabError',
'TimeoutError',
'True',
'TypeError',
'UnboundLocalError',
'UnicodeDecodeError',
'UnicodeEncodeError',
'UnicodeError',
'UnicodeTranslateError',
'UnicodeWarning',
'UserWarning',
'ValueError',
'Warning',
'WindowsError',
'ZeroDivisionError',
'__IPYTHON__',
'__build_class__',
'__debug__',
'__doc__',
'__import__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'abs',
'all',
'any',
'ascii',
'bin',
'bool',
'breakpoint',
'bytearray',
'bytes',
'callable',
'chr',
'classmethod',
'compile',
'complex',
'copyright',
'credits',
'delattr',
'dict',
'dir',
'display',
'divmod',
'enumerate',
'eval',
'exec',
'filter',
'float',
'format',
'frozenset',
'get_ipython',
'getattr',
'globals',
'hasattr',
'hash',
'help',
'hex',
'id',
'input',
'int',
'isinstance',
'issubclass',
'iter',
'len',
'license',
'list',
'locals',
'map',
'max',
'memoryview',
'min',
'next',
'object',
'oct',
'open',
'ord',
'pow',
'print',
'property',
'range',
'repr',
'reversed',
'round',
'set',
'setattr',
'slice',
'sorted',
'staticmethod',
'str',
'sum',
'super',
'tuple',
'type',
'vars',
'zip']
try:
1/0
except ZeroDivisionError:
... # elipse
Ellipsis
class A:
a = 10
vars(A)
mappingproxy({'__module__': '__main__',
'a': 10,
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None})