Pythonで__new__
、クラスのメソッドをファクトリーとして使用する__init__
と、インスタンス化されたクラスのメソッドが2回呼び出されるという奇妙なバグが発生しました。
本来__new__
、クラスの外部でファクトリ関数を宣言する必要なしに、渡されたパラメータに応じて、母クラスのメソッドを使用して子の1つの特定のインスタンスを返すというアイデアでした。
ファクトリ関数を使用することがここで使用するのに最適なデザインパターンであることは知っていますが、プロジェクトのこの時点でデザインパターンを変更するとコストがかかります。したがって、私の質問は次のとおりです。そのようなスキーマでへの二重呼び出しを回避し__init__
て単一の呼び出しのみを取得する方法はあり__init__
ますか?
class Shape(object):
def __new__(cls, desc):
if cls is Shape:
if desc == 'big': return Rectangle(desc)
if desc == 'small': return Triangle(desc)
else:
return super(Shape, cls).__new__(cls, desc)
def __init__(self, desc):
print "init called"
self.desc = desc
class Triangle(Shape):
@property
def number_of_edges(self): return 3
class Rectangle(Shape):
@property
def number_of_edges(self): return 4
instance = Shape('small')
print instance.number_of_edges
>>> init called
>>> init called
>>> 3
どんな助けも大歓迎です。
オブジェクト__new__
を作成すると、Pythonはそのメソッドを呼び出してオブジェクトを作成し、次に__init__
返されたオブジェクトを呼び出します。あなたは内側からオブジェクトを作成するときに__new__
呼び出すことによりTriangle()
に対する更なる呼び出しになりますことを__new__
して__init__
。
あなたがすべきことは:
class Shape(object):
def __new__(cls, desc):
if cls is Shape:
if desc == 'big': return super(Shape, cls).__new__(Rectangle)
if desc == 'small': return super(Shape, cls).__new__(Triangle)
else:
return super(Shape, cls).__new__(cls, desc)
作成されたRectangle
かをTriangle
への呼び出しをトリガすることなく__init__
して、__init__
一度だけ呼ばれます。
スーパーがどのように機能するかについての@Adrianの質問に答えるように編集します。
super(Shape,cls)
検索cls.__mro__
見つけるためShape
当時と属性を見つけるために、配列の残りを下に検索します。
Triangle.__mro__
である(Triangle, Shape, object)
とRectangle.__mro__
され(Rectangle, Shape, object)
ている間Shape.__mro__
だけです(Shape, object)
。これらのいずれの場合でも、呼び出すsuper(Shape, cls)
と、mroシーケンス内のすべてのものが無視されるShape
ため、残っているのは単一の要素のタプルだけで(object,)
あり、それを使用して目的の属性を検索します。
ダイヤモンドの継承がある場合、これはさらに複雑になります。
class A(object): pass
class B(A): pass
class C(A): pass
class D(B,C): pass
これで、Bのメソッドが使用する可能性がsuper(B, cls)
あり、それがBインスタンスである場合は検索され(A, object)
ますが、D
インスタンスがある場合、isであるため、同じ呼び出しでB
検索さ(C, A, object)
れます。D.__mro__
(B, C, A, object)
したがって、この特定のケースでは、形状の構築動作を変更する新しいミックスインクラスを定義し、既存のものから継承するが異なる方法で構築された特殊な三角形と長方形を作成できます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加