Python笔记17---------魔法方法
魔法方法也为特殊方法,即用两个下划线形成的(__方法__)。自己定义的方法最好不要采用这种方式,因为这些方法会在一些特殊的情况下直接被调用。
1、第一个魔法方法:
类中常用的__init__()方法:相当于其他语言中的构造函数,用来初始化参数
当类的一个对象被创建之后会立即调用构造函数。
2. __new__方法:
__new__方法的第一个参数是这个类,而其余的参数会在调用成功后全部传递给__init__方法初始化
__new__方法(第一个执行)先于__init__方法执行:
1 class A: 2 pass 3 4 class B(A): 5 def __new__(cls): 6 print("__new__方法被执行") 7 return super().__new__(cls) 8 def __init__(self): 9 print("__init__方法被执行") 10 11 b = B() 12 ''' 13 执行结果为: 14 15 __new__方法被执行 16 __init__方法被执行 17 '''
__new__方法是传入类(cls),
__init__方法传入类的实例化对象(self),
__new__方法返回的值就是一个实例化对象
(ps:如果__new__方法返回None,则__init__方法不会被执行,并且返回值只能调用父类中的__new__方法,而不能调用毫无关系的类的__new__方法)。
我们可以这么理解它们之间的关系,__new__是开辟疆域的大将军,而__init__是在这片疆域上辛勤劳作的小老百姓,只有__new__执行完后,开辟好疆域后,__init__才能工作。
绝大多数情况下,我们都不需要自己重写__new__方法,但在当继承一个不可变的类型(例如str类,int类等)时,它的特性就尤显重要了。我们举下面这个例子:
class CapStr(str): def __init__(self,string): string = string.upper() a = CapStr("I love China!") print(a) ''' 执行结果为: I love China! '''
class CapStr(str): def __new__(cls,string): string = string.upper() return super().__new__(cls,string) a = CapStr("I love China!") print(a) ''' 执行结果为: I LOVE CHINA! '''
我们可以根据上面的理论可以这样分析,我们知道字符串是不可改变的,
所以第一个例子中,传入的字符串相当于已经被打下的疆域,而这块疆域除了将军其他谁也无法改变,
__init__只能在这块领地上干瞪眼,此时这块疆域就是”I love China!“。
而第二个例子中,__new__大将军重新去开辟了一块疆域,所以疆域上的内容也发生了变化,此时这块疆域变成了”I LOVE CHINA!“。
__new__和__init__相互配合才是python中真正的类构造器。
转载自: https://www.cnblogs.com/demiao/p/11461349.html
3、迭代器:__iter__
所谓的迭代器就是具有next方法的对象。在调用next方法时会返回它的下一个值,若next函数被调用时没有值被返回会引发一个StopIteration异常。
迭代器协议:对象需要提供next()函数返回迭代下一项的值,如果没有值了,就输出一个StopIteration异常终止迭代。
可迭代对象:实现了迭代器协议的对象。比如:列表、元祖、字典等,但需要用iter()作用于它们才可以成为迭代对象。
for item in Iterable原理:先调用iter()函数将Iterable(可迭代对象)变成一个迭代器,然后调用next()作用于生成的迭代器来获取下一项赋值给item,当遇到StopIteration异常就停止迭代。
迭代器首先需要提供一个可迭代对象,比如一个列表
g为一个迭代器,此时调用next(g)可以输出1,再调用next(g)输出2,再调用next(g)输出3,即遍历了一次迭代器,如果再调用next(g)输出StopIteration异常。
4、生成器:
任何包含yield语句的函数成为生成器,生成器也是一个迭代器。yield作用类似return但很不同,yield返回的是生成器,每次产生很多值。
作用:延迟产生结果,不是立即产生结果,而是使用时才产生。
生成器只能遍历一次。
第一类:生成器函数:使用 def 定义函数,但是,使用yield而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
for i in range(1,5):
yield i**2
第二类:生成器表达式:类似于列表推导,只不过是把一对大括号[]变换为一对小括号()。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。
# 生成器generator,类似于list,但是是把[]改为()
gen=(a for a in range(1,10))