摘要:本文旨在澄清里和的概念。的创建并返回的这个实例,是裸的。然后我们的的再接手这个裸的实例去进一步加工,比如加上各种,或再执行一些别的这个过程就是。如果用了,那么就可以无视这个,因为就可以理解成一个普通的函数表示这个类本身。
本文旨在澄清 python 里 __new__ vs __init__ 和 cls vs self 的概念。
很多初学者会困扰,python的“魔法函数” __new__ 有啥用? 跟__init__有啥区别? 为什么有的函数第一个输入变量是self, 有的却是cls? 这有啥区别?
好,废话不多说,先看一个例子:
class A(object): def __new__(cls): print("A.__new__ called") return super(A, cls).__new__(cls) def __init__(self): print("A.__init__ called") A() print("finished")
运行结果为:
A.__new__ called A.__init__ called finished
为什么结果是这样呢?
因为:__new__ 负责创建一个 object;之后 __init__ 负责初始化这个 object。
有点绕是吧,再说具体点:
当A()被 call 的时候,__new__ 就自动执行了, 它创建了一个object(class的具体实例)并返回这个object,然后__init__接手这个实例再接着执行。
每当__new__ 创建并返回一个实例时,__init__ 就接手这个实例然后执行,这个实例就是__init__ 的第一个输入变量,永远不变的, 默认的self。 说到这里,self怎么来的应该很清楚了吧。
在平常应用中,我们定义某个class时几乎不会去写它的__new__方法,于是当我们call这个class时,python会一直往上追溯到有__new__的父辈class, 通常我们自定义的class都是object的子类,所以执行的都是它的__new__。
object的__new__创建并返回的这个实例,是裸的。 然后我们的class的__init__再接手这个裸的实例去进一步加工,比如加上各种 self.xxx = xxx, 或再执行一些别的code, 这个过程就是initialization。注意它和creation的区别,应该说的很清晰了吧。
那假如我们自己定义一个坏了的__new__, 它没有返回一个实例,这事会发生什么呢?比如:
class A(object): def __new__(cls): print("A.__new__ called") #return super(A, cls).__new__(cls) def __init__(self): print("A.__init__ called") A()
运行一下,发现结果是:
A.__new__ called finished
哈哈当然啦,__new__没有返回一个创建好的实例,那么__init__自然就执行不了了。 上头没有提供食材,厨子就揭不开锅做饭嘛。
这个时候有人会问了,为啥 __init__() 里面是 self, 而__new__()里面是cls呢?
首先,我们澄清一下概念:
1、self表示一个具体的实例(instance)本身。(如果用了@staticmethod,那么就可以无视这个self,因为staticmethod就可以理解成一个普通的函数)
2、cls表示这个类(class)本身。
OK, __init__() 里面的self已经说清楚了,是刚刚__new__出炉的一个创建好的实例(object / instance); 那__new__()里面是cls又是指哪个class呢?
简单说来:哪个class召唤了__new__, cls就默认是哪个class。
再看一个例子 (Singleton 单例模式的实现):
class Singleton(object): def __new__(cls, *args, **kw): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) print(" ") print("cls is ", cls) print(type(cls._instance), cls._instance) else: print(" {} already exists".format(cls._instance)) return cls._instance class Bus(Singleton): def sendData(self,data): pass class BusSon(Bus): def sendData(self,data): pass if __name__ == "__main__": busson1 = BusSon() bus1 = Bus() print("------------------------ ") busson2 = BusSon() bus2 = Bus() print("------------------------ ") Bus.__new__(BusSon) Bus() x = Singleton.__new__(Bus) print(x)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/43944.html
摘要:本篇文章总结了目前主流的实现单例模式的方法供读者参考。使用实现单例模式同样,我们在类的创建时进行干预,从而达到实现单例的目的。 很多初学者喜欢用 全局变量 ,因为这比函数的参数传来传去更容易让人理解。确实在很多场景下用全局变量很方便。不过如果代码规模增大,并且有多个文件的时候,全局变量就会变得比较混乱。你可能不知道在哪个文件中定义了相同类型甚至重名的全局变量,也不知道这个变量在程序的某...
摘要:南京现在算是我的一个治愈城市了,带着重重的悲伤去,幸好落雪的瞬间将我治愈。年,世界和平,平安喜乐。继承与多态继承就是从现有的类进行继承,被继承的为超类或者父类也就是爸爸,新的类为子类。 叨叨点啥 2018年的最后一天。回顾这一年,获得很多也失去很多。今年去了很多的地方,成都,重庆,峨眉山,天津,杭州,南京。杭州是我特别喜欢的城市,有很多美好的记忆,也有很多失落的时刻。南京现在算是我的一...
摘要:最前面那个,解释器实际的流程是解析这段代码,得知它需要创建一个类对象,这个类的名字叫做它的父类列表用表示是,它的属性用一个来表示就是。解决方法很简单关键就是前面被特别标记了的应当返回这个的父类的方法返回的对象。 (原发于我的blog:Python: metaclass小记 ) 友情提示:本文不一定适合阅读,如果执意要读,请备好晕车药。 题记 Metaclasses are deepe...
摘要:它首先被程序语言的设计领域所采用并在和面向对象方面取得了成绩。面向对象中的反射通过字符串的形式操作对象相关的属性。注构造方法的执行是由创建对象触发的,即对象类名而对于方法的执行是由对象后加括号触发的,即对象或者类执行执行逻辑题 isinstance和issubclass 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 #!/usr/bin/env py...
摘要:最近在学习设计模式而开发的语言中比较中意的就是了在这里总结下设计模式一般分为三大类构造型结构型行为型先从创建型设计模式开始创建型设计模式包括单例模式抽象工厂模式工厂方法模式生成器模式惰性初始化模式对象池模式原型模式单例模式单例模式的定义是保 最近在学习设计模式,而开发的语言中比较中意的就是python了,在这里总结下. 设计模式一般分为三大类:构造型,结构型,行为型 先从创建型设计模式...
阅读 1941·2021-08-11 11:13
阅读 994·2021-07-25 21:37
阅读 2546·2019-08-29 18:42
阅读 2491·2019-08-26 12:18
阅读 844·2019-08-26 11:29
阅读 1662·2019-08-23 17:17
阅读 2637·2019-08-23 15:55
阅读 2581·2019-08-23 14:34