__new__ 和 __init__

new 在新式类中负责真正的实例化对象,而__init__只是负责初始化 __new__创建的对象。一般来说 new 创建一个内存对象,也就是实例化的对象的实体,交给__init__进行进一步加工。官方文档如下:

https://docs.python.org/2/reference/datamodel.html#object.new

object.__new__(cls[, ...])
Called to create a new instance of class cls. __new__() is a static method (special-cased so you need not declare it as such) that takes the class of which an instance was requested as its first argument. The remaining arguments are those passed to the object constructor expression (the call to the class). The return value of __new__() should be the new object instance (usually an instance of cls).

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.

If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__().

If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked.

__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.

这里有几条非常重要

  1. new 接受的参数除了 cls 还可以有很多。 剩余的参数其实是会传递给__init__
  2. new 返回的对象是 cls 的实例,才会调用__init__ 否则就不调用了。

知道了以上信息,我们可以写一个proxy类, 该类的作用是代理其它任何类。 比如:

proxy = Proxy(apple)

我们这里接受了一个对象apple作为参数,那么proxy 就应该有apple的所有属性。 实现方式如下:

首先定义一个类,new 方法会接受 cls, target, *args, **kwargs为参数。这里cls 就是Proxy自己,但我们在真正实例化对象的时候用target的类来实例化。

class Proxy(object):
    def __new__(cls, target, *args, **kwargs):
        return target.__class__(*args, **kwargs)

接下来定义两个类,有自己的方法

class A(object):
    def run(self):
        return 'run'


class B:
    def fly(self):
        return 'fly'

可以看到,我们可以用proxy 来代理 a,b 因为proxy在实例化的时候实际上借助了a/b

a = A()
b = B()

pa = Proxy(a)
pb = Proxy(b)
print "pa.run is ", pa.run()
print "pb.fly is ", pb.fly()

posted on 2017-05-12 14:20  kramer  阅读(151)  评论(0编辑  收藏  举报

导航