2017-11-07 3 views
0

私はinitを実行する前にargsを変更しようとしていますが、それは変更されず、メインに与えられた最初のargsのままです。どうすればargsを変更するのですか?new__new__から__init__へのPythonの転送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'> 

答えて

0

それは、両方のは、それが受け取った引数を渡すYourClass.__new__()YourClass.__init__()、毎回呼び出すメタクラスの__call__()方法です。したがって、引数がYourClass.__init__()に達する前に引数を変更したい場合は、__init__()をデコレートするか、またはtype.__call__()をオーバーライドするカスタムメタクラスを使用するという2つの解決策があります。

(Q & 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 & D)メタクラス版(PYの2.7.35):

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はrightouslyコメントに言及してあなたのクラス__init__の方法で直接これを行うことができます。

+0

デコレータが必要ないことを指摘したいだけです。あなたは '__init__'の中で同じことをすることができます。 –

+0

@Rawing確かに。 –

+0

@Rawingは答えにあなたのコメントを追加しました。 –

関連する問題