python中__init__()、__new__()、__call__()几个魔法方法的用法

关于__new__()的用法参考:

http://www.myhack58.com/Article/68/2014/48183.htm

正文:

一、__new__()的用法:

__new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__()负责将类的实例化,而在__init__()启动之前,__new__()决定是否 要使用该__init__()方法,因为__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例。

如果将类比喻为工厂,那么__init__()方法则是该工厂的生产工人,__init__()方法接受的初始化参 数则是生产所需原料,__init__()方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而 __new__()则是生产部经理,__new__()方法可以决定是否将原料提供给该生产部工人,同时它还决定着出 货产品是否为该生产部的产品,因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。

__new__()方法的特性:

__new__()方法是在类准备将自身实例化时调用。

__new__()方法始终都是类的静态方法,即使没有被加上静态方法装饰器。

类的实例化和它的构造方法通常都是这个样子:

class MyClass(object):

def __init__(self, *args, **kwargs):

...

# 实例化

myclass = MyClass(*args, **kwargs)

正如以上所示,一个类可以有多个位置参数和多个命名参数,而在实例化开始之后,在调用 __init__()方法之前,Python首先调用__new__()方法:

def __new__(cls, *args, **kwargs):

...

第一个参数cls是当前正在实例化的类。

如果要得到当前类的实例,应当在当前类中的__new__()方法语句中调用当前类的父类 的__new__()方法。

例如,如果当前类是直接继承自object,那当前类的__new__()方法返回的对象应该为:

def __new__(cls, *args, **kwargs):

...

return object.__new__(cls)

注意:

事实上如果(新式)类中没有重写__new__()方法,即在定义新式类时没有重新定义__new__()时 ,Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,如果该类的父类也没有重写 __new__(),那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。

而如果新式类中重写了__new__()方法,那么你可以自由选择任意一个的其他的新式类(必定要是 新式类,只有新式类必定都有__new__(),因为所有新式类都是object的后代,而经典类则没有__new__() 方法)的__new__()方法来制造实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死 循环。具体看以下代码解释:

class Foo(object):

def __init__(self, *args, **kwargs):

...

def __new__(cls, *args, **kwargs):

return object.__new__(cls, *args, **kwargs)

# 以上return等同于

# return object.__new__(Foo, *args, **kwargs)

# return Stranger.__new__(cls, *args, **kwargs)

# return Child.__new__(cls, *args, **kwargs)

class Child(Foo):

def __new__(cls, *args, **kwargs):

return object.__new__(cls, *args, **kwargs)

# 如果Child中没有定义__new__()方法,那么会自动调用其父类的__new__()方法来制造实例,即Foo.__new__(cls, *args, **kwargs)。

# 在任何新式类的__new__()方法,不能调用自身的__new__()来制造实例,因为这会造成死循环。因此必须避免类似以下的写法:

# 在Foo中避免:return Foo.__new__(cls, *args, **kwargs)或return cls.__new__(cls, *args, **kwargs)。Child同理。

# 使用object或者没有血缘关系的新式类的__new__()是安全的,但是如果是在有继承关系的两个类之间,应避免互调造成死循环,例如:(Foo)return Child.__new__(cls), (Child)return Foo.__new__(cls)。

class Stranger(object):

...

# 在制造Stranger实例时,会自动调用 object.__new__(cls)

通常来说,新式类开始实例化时,__new__()方法会返回cls(cls指代当前类)的实例,然后该类的 __init__()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入__new__ ()方法中接收的位置参数和命名参数。

注意:如果__new__()没有返回cls(即当前类)的实例,那么当前类的__init__()方法是不会被调用 的。如果__new__()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方 法。

class Foo(object):

def __init__(self, *args, **kwargs):

...

def __new__(cls, *args, **kwargs):

return object.__new__(Stranger, *args, **kwargs)

class Stranger(object):

...

foo = Foo()

print type(foo)

# 打印的结果显示foo其实是Stranger类的实例。

# 因此可以这么描述__new__()和__ini__()的区别,在新式类中__new__()才是真正的实例化方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法__init__()使其丰满。

# 如果以建房子做比喻,__new__()方法负责开发地皮,打下地基,并将原料存放在工地。而__init__()方法负责从工地取材料建造出地皮开发招标书中规定的大楼,__init__()负责大楼的细节设计,建造,装修使其可交付给客户;

二、__init__()的用法

  __init__()是python的一个构造方法,在定义类时,用于初始化的一些操作;它能实现的功能及原理相对来讲也是比较简单一点,就是在实例化该类时,自动执行__init__()方法定义的内容;但是注意__init__()一般不用户返回return;

>>>
>>> class A(object):
    def __init__(self, x):
        self.x = x
        print ‘__init__ called.‘
    def foo(self):
        print self.x

>>>
>>> a = A(‘123‘)
__init__ called.
>>>
>>> a.foo()
123
>>> 

  在A(‘123‘)实例化类时,自动调用__init__()方法定义的self.x = x和print ‘__init__ called.‘,我们能看到‘__init__ called.’被打印,看不到self.x = x的执行,但是在调用a.foo()时,能执行成功,就是拜self.x = x的功能所赐;因为如果没有__init__()方法中的self.x = x,实例对象将无法追溯到foo()函数中的self.x是从哪里来的,从而会报错;也就是在__init__()函数中将外部传入的参数x赋值给self.x,从而是self.x在类A中畅行无阻;

三.__call__()的用法

  __call__()方法能够让类的实例对象,像函数一样被调用;

>>>
>>> class A(object):
    def __call__(self, x):
        print ‘__call__ called, print x: ‘, x

>>>
>>> a = A()
>>> a(‘123‘)
__call__ called, print x:  123
>>> 

  看a(‘123‘)这是函数的调用方法,这里a实际上是类对象A的实例对象,实例对象能想函数一样传参并被调用,就是__call__()方法的功能;

接下来用一段简单的代码,来总体感受一下三个方法的用法和区别:

>>>
>>> class A(object):
    def __init__(self, x):
        print ‘x in __init__‘, x
    def __new__(cls, y):
        print ‘y in __new__‘, y
        return super(A, cls).__new__(cls)
    def __call__(self, z):
        print ‘z in __call__‘, z

>>>
>>> A(‘123‘)(‘abc‘)
y in __new__ 123
x in __init__ 123
z in __call__ abc
>>> 

  由执行结果可以看出,虽然__init__()方法定义在__new__()方法之前,但是结果中先展示了__new__()方法的执行结果;

时间: 2024-10-11 03:28:09

python中__init__()、__new__()、__call__()几个魔法方法的用法的相关文章

python中的__new__与__init__,新式类和经典类(2.x)

在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1. 新式类对象可以直接通过__class__属性获取自身类型:type 2. 继承搜索的顺序发生了改变,经典类多继承时属性搜索顺序: 先深入继承树左侧,再返回,开始找右侧(即深度优先搜索);新式类多继承属性搜索顺序: 先水平搜索,然后再向上移动 例子: 经典类: 搜索顺序是(D,B,A,C)>>&

__new__、__init__、__call__三个特殊方法

用双下划线包围的特殊方法在Python中又被成为魔术方法,类似于C++等语言中的构造函数,这里我们就来详解Python中的__new__.__init__.__call__三个特殊方法: 1.__new__(cls, *args, **kwargs)  创建对象时调用,是一个静态方法,返回当前对象的一个实例;   注意:这里的第一个参数是cls即class本身 2.__init__(self, *args, **kwargs) 创建完对象后调用,对当前对象的实例的一些初始化,无返回值,即在调用_

Python中的__new__()方法与实例化

@Python中的__new__()方法与实例化 __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__()负责将类的实例化,而在__init__()启动之前,__new__()决定是否 要使用该__init__()方法,因为__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例. 如果将类比喻为工厂,那么__init__()方法则是该工厂的生产工人,__init__()方法接受

Python中__init__方法

注意1.__init__并不相当于C#中的构造函数,执行它的时候,实例已构造出来了. 1 2 3 4 5 class A(object):     def __init__(self,name):         self.name=name     def getName(self):         return 'A '+self.name 当我们执行 1 a=A('hello') 时,可以理解为 1 2 a=object.__new__(A) A.__init__(a,'hello')

Python中执行系统命令常见的几种方法--转载

Python中执行系统命令常见的几种方法 Python中执行系统命令常见的几种方法有: (1)os.system # 仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息 # 如果再命令行下执行,结果直接打印出来 例如: >>> import os >>> os.system('ls') chk_err_log.py CmdTool.log  install_log.txt  install_zabbix.sh  manage_deploy.sh  MegaSA

So easy:Python中的__new__、__init__、__call__

(望结交天下才士 ,Contact:UVEgMTkwNDUyOTQzOA==) __new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪来的self)__init__ : 对象的初始化, 是一个实例方法,第一个参数是self.__call__ : 对象可call,注意不是类,是对象. 先有创建,才有初始化.即先__new__,而后__init__.上面说的不好理解,看例子. 1.对于__new__ 1 class Bar(object):

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

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

python中__init__()、__new__()、__call__()、__del__()用法

http://www.myhack58.com/Article/68/2014/48183.htm 正文: 一.__new__()的用法: __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__()负责将类的实例化,而在__init__()启动之前,__new__()决定是否 要使用该__init__()方法,因为__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例. 如果将类

一个案例深入Python中的__new__和__init__

准备 在Python中,一切皆对象. 既然一切皆对象,那么类也是对象,我们暂且称之为 类对象.来个简单例子(本篇文章的所有案例都是运行在Python3.4中): class foo(): pass print(id(foo)) print(type(foo)) # 结果: # 46627056 # <class 'type'> 如果想深入了解一下,可以看:深刻理解Python中的元类(metaclass) 引入 最近在阅读tornado源码,发现在其源码中有很多类是这样的: class HTT