クラス コンストラクター ( init )で値を返そうとしました。
class A:
def __init__(self):
return 1
しかし、 initは None を返す必要があるという実行時エラーが発生します。この場合、理解する方法は次のとおりです。
a=A()
クラスインスタンスとして「a」が割り当てられている場所はどこですか?
クラス コンストラクター ( init )で値を返そうとしました。
class A:
def __init__(self):
return 1
しかし、 initは None を返す必要があるという実行時エラーが発生します。この場合、理解する方法は次のとおりです。
a=A()
クラスインスタンスとして「a」が割り当てられている場所はどこですか?
厳密に言えば、A.__new__()
インスタンスを作成しているわけではありませんa
。
定義するときclass A(object):
(またはclass A:
、Python3 を使用している場合は廃止されclass A:
た古いスタイルのクラスです)、インスタンスを作成するために呼び出されるのは__new__
継承されたものです。object.__new__()
a
がa = A()
実行されると、次のことが起こります。
A()
の省略形ですA.__call__
object.__new__(cls, *args, **kwargs)
where はcls=A
、インスタンスを作成するために内部で実際に行われることa
です。新しいオブジェクトにメモリを割り当て、新しいオブジェクト (インスタンス) を返す必要があります。__init__(self)
れたオブジェクトが渡されて呼び出され、オブジェクトを「初期化」します。次のデモを検討してください。
オーバーライド__new__
してオブジェクトを返さなくなった場合、__init__
呼び出されません。
class A(object):
def __new__(cls, *args, **kwargs):
print cls, args, kwargs
def __init__(self):
self.x = 'init!'
print self.x
In : a = A()
<class '__main__.A'> () {}
# note that "init!" has not appeared here because __new__ didn't return an
# new instance
を使用して新しいインスタンスを返すと、 afterも呼び出されるobject.__new__
ことがわかります。__new__
__init__
class A(object):
def __new__(cls, *args, **kwargs):
print cls, args, kwargs
return object.__new__(cls, args, kwargs)
def __init__(self):
self.x = 'init!'
print self.x
In : a = A()
<class '__main__.A'> () {}
init!
違いを表示する別のデモを次に示します。インスタンスa
は を呼び出さずに作成できることに注意して__init__()
ください。
class A(object):
def __init__(self):
self.x = "init!"
print self.x
In : a = object.__new__(A)
In : a
Out: <__main__.A at 0x103466450>
In : a.__dict__
Out: {}
In : aa = A()
init!
In : aa
Out: <__main__.A at 0x1033ddf50>
In : aa.__dict__
Out: {'x': 'init!'}
大まかに言えば、Python で新しいオブジェクトを作成するには、主に 2 つの方法があります。
class
ステートメントは Python に新しい型/クラスオブジェクトを作成するように指示します (既存の型/クラスをサブクラス化することによりobject
):
class Hello(object):
pass
>>> Hello.__class__
<type 'type'>
実際、すべてのクラス/型オブジェクトには type がありtype
ます。type
( )の型type(type)
はまだ type です。
タイプ/クラスオブジェクトをサブクラス化できます。
既存の型オブジェクトをインスタンス化することによって、新しいオブジェクトを作成することもできます。これは、__call__
演算子 (省略形()
) を使用して行われます。
>>> h = hello()
>>> type(h)
<class '__main__.Hello'>
>>> type(int('1'))
<type 'int'>
インスタンス オブジェクトをサブクラス化することはできません。
(リスト演算子を使用するなど、他の方法で新しいインスタンスオブジェクトを作成することもできます[1,2,3]
。この場合、リスト インスタンスが作成されます)
type(my_obj)
またはでオブジェクトのタイプを確認できますmy_object.__class__
。
実際、これらのオブジェクトはインスタンス化によっても作成されますが、前述のインスタンス化とは少し異なる種類のインスタンス化です。
class
ステートメントとは
別にtype(cls_name, parent_class_tuple, attr_dict)
、新しいクラスを作成するために使用することもできます。例:
type('Hello', (object,), {})
Hello
前に示したものと同じクラスを作成します。
とはtype
? メタクラスを入力します。
type
class のクラスであるmetaclassです。つまり、クラスはメタクラスのインスタンスです。のはまだです。__class__
type
type
これは、 metaclass、class、 instanceの間の関係を示すグラフです。
instantiate instantiate
metaclass --------------> class ----------------> instance
type.__new__() object.__new__()
type
新しいクラスを作成するためにメタクラスが呼び出されると、同様のフローが行われます。
type.__call__()
実行されますtype.__new__()
メモリを割り当て、新しいクラス (メタクラス インスタンス) を返し、 を呼び出しますtype.__init__()
。type.__init__()
ステップ 2 から渡された新しく作成されたクラスを初期化します。サブクラス化することで新しいメタクラスを作成することもできますtype
:
class MyMeta(type):
def __new__(meta, name, bases, dct):
# do something
return super(MyMeta, meta).__new__(meta, name, bases, dct)
def __init__(cls, name, bases, dct):
# do something
super(MyMeta, cls).__init__(name, bases, dct)
MyMeta
次に、このメタクラスから、次のように新しいクラスを作成できますtype
。
MyClass = MyMeta('MyClass', (object, ), {'x': 1})
または、__metaclass__
クラスを定義するときに使用します。これは、上に示したものとまったく同じ効果があります。
class MyClass(object):
__metaclass__ = MyMeta
x = 1
それはこのように動作します:
あなたがやる:
a = A()
A.__new__()
が呼び出され、クラスのインスタンスを返しますA
。
同様に:
a = A.__new__(A)
次にPythonが呼び出します
a.__init__()
エラーメッセージが示すように、値を返すべきではありません。
ご存知のように、Python ではすべてがオブジェクトであり、クラスも例外ではありません。クラスは、 のようなものを書くことができるA
メソッドを持つオブジェクトです。内部的には、最初に静的メソッド (適切なデフォルト実装を持つ) を使用してオブジェクトを作成し、次に適切なコンストラクター引数を使用して新しいオブジェクトを呼び出します。__call__(...)
a = A()
A.__call__
__new__
__init__
__init__
返す必要がある要件None
は、意識的な実装の選択です。これにより、クラス型のオブジェクトがクラスのインスタンス型のオブジェクトを一貫して返すという事実に依存できます。C++ などの他の多くの言語でも同じです。
異なる方法で実装すると、無用な混乱が生じます。