python从__new__转移到__init__

时间:2017-11-07 11:49:11

标签: python class

我试图在运行init之前更改args但它没有改变并保持为主要给出的第一个args,我如何更改 new 中的args?

class A(object):
            def __init__(self,ip,st):
                    print 'A arrived to init '+st
                    self.ip=ip

        def __new__(cls,ip,st):
                print "A arrived to new"
                if ip>10:
                        return object.__new__(cls,ip,"A")
while True:                
        s=input("input?")
        a=A(s,"a")
        print type(a)

输出:

input?88
A arrived to new
A arrived to init a
<class '__main__.A'>
input?44
A arrived to new
A arrived to init a
<class '__main__.A'>
input?22
A arrived to new
A arrived to init a
<class '__main__.A'>
input?12
A arrived to new
A arrived to init a
<class '__main__.A'>

1 个答案:

答案 0 :(得分:0)

这是元类的__call__()方法,每次调用它都会调用YourClass.__new__()YourClass.__init__()。因此,如果您希望在参数到达YourClass.__init__()之前更改它们,您有两个解决方案:装饰__init__()或使用自定义元类覆盖type.__call__()

(Q&amp; D)装饰者版本:

def changeargs(func):
    # fixme : make this a well-behaved decorator
    def wrapper(self, *args, **kw):
        print("changearg.wrapper(%s, %s)" % (args, kw))
        args = (1, 2)
        kw = {"hacked": True}
        return func(self, *args, **kw)
    return wrapper

class Bar(object):
    @changeargs
    def __init__(self, *args, **kw):
        self.args = args
        self.kw = kw

    def __repr__(self):
        return "<Bar(%s, %s)>" % (self.args, self.kw)

(Q&amp; D)元类版本(py 2.7.x):

class FooType(type):
    def __call__(self, *args, **kw):
        print("FooType.__call__(%s, %s)" % (args, kw))
        args = (1, 2)
        kw = {"hacked": True}
        # fixme : make this collaborative super() call
        return type.__call__(self, *args, **kw)

class Foo(object):
    __metaclass__ = FooType

    def __init__(self, *args, **kw):
        self.args = args
        self.kw = kw

    def __repr__(self):
        return "<Foo(%s, %s)>" % (self.args, self.kw)

但正如Rawing在评论中正确提到的那样,你可以直接在你的班级__init__方法中直接这样做。