Python的__init__, __new__魔法方法以及在__metaclass__元类中的使用

Python中类的实例化是由Python解释器先后调用__new__,__init__这两个魔法方法来完成的,前者用来完成实例化后的对象的“骨架”(比如,解释器会为对象分配地址,并返回一个指向该对象的引用值,该引用值会被紧接着传递给__init__函数),后者用“ self.属性名 = 属性值 ”这样的方式对实例化的对象进行“填充”。

1.__new__

在一个类(假设为类A)实例化出一个对象的过程中,__new__()方法先于__init__()方法调用,它返回一个A的实例的引用,这个引用值会被传递给接下来执行的方法,如果,__new__()没有返回一个实例的引用,则__init__()不会被执行,若它返回一个非A的实例(语法上可以,但是没有实际意义)b(假设是B的一个实例),它则继续执行b的__init__()方法。

__new__(cls[, ...])__new__()方法的函数形式如左边所示。它是一个静态方法(虽然没有使用静态方法的修饰符),cls的值为类,其他参数为初始化时传递给构造器的参数(就是传递给__init__()的参数),例如,a = A(”Jonhn”,20)这样的语句,解释器在实例化A的时候会自动调用__new__(A,,”Jonhn”,20 ),解释器会把A和收集到的参数传递给__new__(),让它有操作这些数据的能力。所以在定义__new__()的时候,形参的设置最好和__init__()保持一致,尤其是在使用了*args,**kwargs,默认值之后,确保定义的形参能够恰当的接受实参。

class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __new__(cls, *args, **kwargs):
        print("__new__ Method is invoking")
        return super(Person, cls).__new__(cls)
p = Person("John", 30)
print(p.name)
print(p.age)

运行结果:

__new__ Method is invoking
John
30

涉及到继承的话,调用祖先类的__new__()方法的一般形式为“

Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using super(currentclass, cls).__new__(cls[, ...]) with appropriate arguments and then modifying the newly-created instance as necessary before returning it.

涉及到继承时,派生类实例化的时候按照MRO搜索__new__(__init__也是一样)并调用,这是设计类体系的时候也应该注意的。

2.__new__的用例

“__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.”

一般的自定义类,是对同一类事物的抽象,而这些所有这些自定义的类,对他们进行抽象,他们的共同特征就是:可以实例化,自定义的类又可以抽象为type的一个实例(好辩证的想法,一会儿是类,一会儿又变成实例),type实例化话后得到一个类,type就被称为元类,我们可以根据需求创建自己的元类,使用在模块里,项目里,使这些类具有某些共同的我们想实现的特征。

这篇文章给出了许多的用例:

浅析python的metaclass

时间: 2024-08-24 11:17:26

Python的__init__, __new__魔法方法以及在__metaclass__元类中的使用的相关文章

java的toString是一个什么方法,为什么我在类中重写他,当输出该类对象的时候却能显示里面的结果?(转)

例如:我输出的是一个对象,却调用到了toString方法 public class TTT { private String id; private String name; public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } public String toString() { return "学号:" + id + "\n

Python学习笔记之魔法方法

魔法方法(特殊方法):名称以双下划线和双下划线结尾的方法. 这些方法会在特殊情况下被Python直接调用,几乎没有直接调用的必要. __init__():构造函数 __del__():析构函数 在其他语言中对象可能被要求属于某一个类,或被要求实现接口,但在Python中只是简单的要求它遵守几个给定的规则. 如一个序列类,为了实现规则,则需要实现以下魔法方法: __len__(self):返回集合中所含项目的数量 __getitem__(self,key):返回与所给键对应的值 __setitem

简析 __init__ __new__ __call__ 方法

任何事物都有一个从创建,被使用,再到消亡的过程,在程序语言面向对象编程模型中,对象也有相似的命运:创建.初始化.使用.垃圾回收,不同的阶段由不同的方法(角色)负责执行. 定义一个类时,大家用得最多的就是 __init__ 方法,而 __new__ 和 __call__ 使用较少 __init__方法 该方法负责对象的初始化,系统执行该方法前,其实该对象已经存在了,要不然初始化什么呢?先看例子: # class A(object): python2 必须显示第继承object class A: d

Python——property(使一个方法看起来就像类属性一样)

""" 装饰器property:     使一个方法看起来就像类属性一样 """ #例子1 class A:     def __init__(self,  x, y):         self.__x = x #私有变量         self.__y = y def __add(self): #私有方法         return self.__x + self.__y @property     def sum(self): #通过p

Python全栈开发之9、面向对象、元类以及单例

前面一系列博文讲解的都是面向过程的编程,如今是时候来一波面向对象的讲解了 一.简介 面向对象编程是一种编程方式,使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用.类就是一个模板,模板里可以包含多个方法(函数),方法里实现各种各样的功能,,对象则是根据模板创建的实例,通过实例,对象可以执行类中的方法,每个对象都拥有相同的方法,但各自的数据可能不同. 二.类.对象和方法 在Python中,定义类是通过class关键字,class后面紧接着是类名,类名通常

python面向对象高级:反射、魔法方法、元类

自省/反射什么是反射?自省也称作反射,这个性质展示了某对象是如何在运行期取得自身信息的.并且在python里,反射可以使得程序运行时对象拥有增删改查它本身属性或行为的一种能力如果Python不支持某种形式的自省功能,dir和type内建函数,将很难正常工作.还有那些特殊属性,像__dict__,__name__及__doc__反射的使用场景? 即插即用,即可以事先定义好接口,接口只有在被完成后才会真正执行 比如:如果和别人共同合作开发项目,但是需要用到对方的类的方法,对方还没完成 f1=FtpC

Python – 魔法方法

魔法方法 有触发时机在满足条件时自动触发就是魔术方法 __init__:对象初始化方法 __new__:创建对象时候执行的方法,单列模式会用到 __str__:当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在 这个方法中return的数据 __del__:删除对象执行的方法 简述面向对象中__new__和__init__区别 __init__是初始化方法,创建对象后,就立刻被默认调用了,可接收参数,如图 1.__new__至少要有一个参数cls,代表

python魔法方法、构造函数、序列与映射、迭代器、生成器

在Python中,所有以__双下划线包起来的方法,都统称为"魔术方法".比如我们接触最多的__init__,魔法方法也就是具有特殊功能的方法. 构造函数 构造函数不同于普通方法,将在对象创建后自动调用它们.也就是在对象创建完成后,自动会调用__init__方法来初始化. 创建一个构造方法 构造方法传参 >>> class FooBar: def __init__(self,value=42): #默认参数 self.somevar = value >>&g

【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理

原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attributes_dict)" 这种语法来使用时, 在__call__方法内使用又会调用type的__new__和__init__方法来创建classname_string的具体类,并初始化类信息.当type(***)调用完成, classname_string代表的类可以用来创建实例了. 元类调用过程