4

インタープリターが舞台裏で行うすべてのアクションの順序を知りたいです (明示的に宣言されているかどうかに関係なく)。

例えば:

  • __init__電話
  • super()電話
  • __new__電話
  • グローバル変数
  • コンストラクタ変数の初期化
  • デコレータの呼び出しなど

編集:それがすべてを備えたクラスであると仮定しましょう(名前を付けます)

global_var = 2468
class A(superA):
    class_var = 1234

    __init__(self):
        superA.__init__(self)
        another_var = 5678

    @random_decorator
    def method(self):
        # do stuff
4

2 に答える 2

4
class Foo(object):
    def __init__(self, *args, **kwargs):
        pass

>>> foo = Foo(a, b=c)
  1. それは呼び出しtype.__call__(Foo, a, b=c)です... (代わりtypeに、クラスのメタクラスにすることができます)
  2. ...Foo.__new__(a, b=c)のインスタンスを作成する呼び出しFoo
  3. ...そして呼び出しfoo.__init__(a, b=c)て返すfoo

つまり、whereは次b = B(*args)のように表現できます。type.__call__(B, *args)type.__call__

class type(object):

    def __call__(cls, *args, **kwargs)
         obj = cls.__new__(*args, **kwargs)
         obj.__init__(*args, **kwargs)
         return obj

関数superは、(通常の関数のように) 呼び出した場所で実行されます。

装飾は、クラスとメソッドの初期化で実行され、ラッパーで置き換えられます。

完全な例:

def dec(func):
    print 'decorate', func.__name__
    def wrapper(*args):
        print 'call wrapper of', func.__name__
        return func(*args)
    return wrapper

class A(object):

    def __new__(*args):
        print 'call A.__new__'
        return object.__new__(*args)

    def __init__(self, *args):
        print 'call A.__init__'


class MyMetaclass(type):

    def __call__(mcls, *args):
        print 'call MyMetaclass.__call__'
        return super(MyMetaclass, mcls).__call__(*args)

class B(A):

    __metaclass__ = MyMetaclass

    @dec
    def __new__(*args):
        print 'call B.__new__'
        return A.__new__(*args)

    @dec
    def __init__(self, *args):
        print 'call B.__init__'
        return super(B, self).__init__(*args)

print 'start creating instance'
b = B()
print 'end creating instance'

結果:

decorate __new__
decorate __init__
start creating instance
call MyMetaclass.__call__
call wrapper of __new__
call B.__new__
call A.__new__
call wrapper of __init__
call B.__init__
call A.__init__
end creating instance
于 2012-10-11T13:58:41.893 に答える
2

それはすべてかなり簡単です。モジュールがロードされると、コードは上から下に実行されます。したがって、グローバル変数は、モジュール コードに表示されるときにインスタンス化されます。関数が呼び出されると、その中のコードが上から下に実行されます。

デコレーターは、装飾する関数が定義された後に、下から上に順に呼び出されるという点で、多少の例外です。あなたが持っている場合:

@hits
@dies
@rofls
def watcher(): pass

それは次と同じです:

def watcher(): pass
watcher = hits(dies(rofls(watcher)))

これは、各デコレータがその下のすべてをラップしていると考えると理にかなっています。

オブジェクトが作成されると、最初__new__に が呼び出され、次に__init__. super()他のものと同じように、どこかでそれを呼び出した場合に呼び出されます...「コンストラクター変数」は、__init__.

編集:あなたの例を見るには:

class A(superA):
    class_var = 1234

    def __init__(self):
        superA.__init__(self)
        another_var = 5678

    @random_decorator
    def method(self):
        # do stuff

代わりに釣り方を教えます。

def random_decorator(f):
    print "random_decorator called"
    return f

def init_var(varname, val):
    print '%s being initialized' % (varname,)
    return val

class superA(object):
    def __new__(cls):
        print 'superA.__new__ called'
        return super(superA, cls).__new__(cls)
    def __init__(self): 
        print "superA.__init__ called"

class A(superA):
    class_var = init_var('class_var', 1234)

    def __new__(cls):
        print 'A.__new__ called'
        return super(A, cls).__new__(cls)

    def __init__(self):
        print 'A.__init__ called'
        superA.__init__(self)
        another_var = init_var('another_var', 5678)

    @random_decorator
    def method(self):
        print 'method called'
        # do stuff

    class_var2 = init_var('class_var2', 9012)

A().method()

print ステートメントがどのような順序で出力されるかを確認します。

于 2012-10-11T14:03:52.893 に答える