函数高级
迭代器
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>051015
生成器
# 计算数列每次都要从1开始算,保留函数运行装填,之后生成序列def fibonacci(n):a, b, counter = 0, 1, 0while True:if (counter > n):returnyield a # yield 代表该函数是生成器,返回一个数后暂停,需要下一个数时继续运行a, b = b, a + bcounter += 1fibonacci(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**nreturn func
power2 = power(2)power5 = power(5)power10 = power(10)print(power2(4))print(power5(4))print(power10(4))
1610241048576
装饰器
def square(n):print(f'square {n}')return n**2square(2)
square 24
对函数进行加强,打印执行时的日期
import timedef decorator(func):def wrapper(*args, **kwargs):print(time.time())return func(*args, **kwargs)return wrapper
@decoratordef square(n):print(f'square {n}')return n**2
square(2)
1617971796.1864774square 24
hello = lambda: print('hello')hello = decorator(hello)hello()
1617971847.2084067hello
函数是一等公民
函数可以传递
# 使用字典完成类似cpp中的switchdef apple():return 5def banana():return 3def orange():return 4get_price = {'apple': apple, 'banana': banana, 'orange': orange}get_price['apple']()
5
函数作用域
total = 2arg = 10def sum(arg1, arg2):total = arg1+arg2+arg # 函数有自己的作用域,可引用外部值return totalprint(total)print(sum(1, 2))print(total)
2132
total = 2arg = 10def sum(arg1, arg2):global total # 使用全局变量中的totaltotal = arg1+arg2+arg # 函数有自己的作用域,可引用外部值return totalprint(total)print(sum(1, 2))print(total)
21313
nonlocal 在一个局部作用域中使用外层的变量
def some(func):a = 'I am a'def some1(*args, **kwargs):print(locals())nonlocal aprint(locals())print(a)func(*args, **kwargs)return some1some(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 a10
@somedef 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 ahello
globals()['hello']
<function __main__.some.<locals>.some1(*args, **kwargs)>
globals()['sssimon'] = 10print(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'))
55
class A:def __init__(self, x):self.x = xdef 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')
True15
class A:z = 10def __init__(self, x):self.x = xdef get_x(self):return self.x
a = A(5)print(a.x)print(a.z)print(A.z)print(A.x)
51010---------------------------------------------------------------------------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 = 10def __init__(self, x):self.x = xdef get_x(self):return self.x@classmethoddef get_z(cls):return cls.z@staticmethoddef hello():return 'hello'
三种方法
- 实例方法,调用时会把实例作为第一个参数传递给self参数
- 类方法,调用时会把类作为第一个参数传递给cls参数
- 静态方法,调用时并不需要传递类或者实例
a = A(5)print(a.get_x())print(A.get_z())print(a.hello())print(A.hello())
510hellohello
类继承
#class A:z = 10def __init__(self, x):self.x = xdef get_x(self):return self.xclass 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 = xdef get_x(self):return self.xclass B(A):def __init__(self, x, y):self.y = ysuper().__init__(x) # 自动寻找父类进行初始化def get_x(self):return super().get_x()+100def 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 Exceptionself.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 Exceptionreturn self.x[key]def __setitem__(self, key, value):try:key = int(key)assert key < len(self.x)except:raise Exceptionself.x[key] = valuereturn valuedef __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'] = 10print(a)
A with value [1, 1, 1, 1, 1]511A with value [1, 1, 10, 1, 1]
魔法方法较多,均为前后双下划线形式,不在赘述
python也支持多继承,多继承较为麻烦,不再教学
# 类型注释
# 执行的是静态类型检查a: str = 'hello_world'def hello(a: str) -> int:print(a)return 1
hello(a)
hello_world1
hello(1) # 不是强制的
11
你可以使用pyright mypy pytype pyre的类型检查工具
class A:def __init__(self, x, y):self.x = xself.y = y
a = A(1, 2)a.z = 3
# __slots__ 规定类的属性和方法,不能动态增加class A:__slots__ = ('x', 'y')def __init__(self, x, y):self.x = xself.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 = 3AttributeError: 'A' object has no attribute 'z'
# property 解决属性暴露的问题class A:__slots__ = ('x', 'y')def __init__(self, x, y):self.x = xself.y = y
class B:def __init__(self, x):self._x = x@propertydef 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 = 10AttributeError: can't set attribute
class B:def __init__(self, x):self._x = x@propertydef x(self):return self._x@x.setterdef x(self, value):self._x = value@x.deleterdef x(self):del self._x
b._x = 10print(b.x)
10
- 前置单下划线 _var :命名约定,用来表示该名称仅在内部使用。一般对 Python解释器没有特殊含义(通配符导入除外),只能作为对程序员的提示。
- 后置单下划线 var_ :命名约定,用于避免与 Python关键字发生命名冲突。
- 前置双下划线 __var :在类环境中使用时会触发名称改写,对 Python解释器有特殊含义。
- 前后双下划线 var :表示由 Python 语言定义的特殊方法。在自定义的属性中要避免使用这种命名方式。
- 单下划线 _ :有时用作临时或无意义变量的名称(“不关心”)。此外还能表示 Python REPL会话中上一个表达式的结果。
class Test:def __init__(self):self.foo = 11self._bar = 23self.__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/0except 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})
