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 in range(1,10))

 

posted on 2018-03-27 17:04  吱吱了了  阅读(216)  评论(0)    收藏  举报

导航