学習課題として、Python のビルトインの動作をエミュレートするクラスを実装しようとしていますが、メソッドとメソッドcomplex
の動作が異なります。__str__
__repr__
(1.0,2.0)
...それ以外の:
(1+2j)
最初に単純に and をサブクラス化しcomplex
て再定義しよう__str__
と__repr__
しましたが、これには、オーバーライドされていないメソッドが呼び出されると、標準complex
が返され、標準形式で出力されるという問題があります。
>>> a = ComplexWrapper(1.0,1.0)
>>> a
(1.0,1.0)
>>> b = ComplexWrapper(2.0,3.0)
>>> b
(2.0,3.0)
>>> a + b
(3+4j)
目的の出力が(3.0,4.0)
.
私はメタクラスについて読んでいて、メタクラスが私の問題を解決してくれると思っていました。Python Class Decoratorの回答から始めて、現在の実装は次のとおりです。
def complex_str(z):
return '(' + str(z.real) + ',' + str(z.imag) + ')'
def complex_repr(z):
return '(' + repr(z.real) + ',' + repr(z.imag) + ')'
class CmplxMeta(type):
def __new__(cls, name, bases, attrs):
attrs['__str__'] = complex_str
attrs['__repr__'] = complex_repr
return super(CmplxMeta, cls).__new__(cls, name, bases, attrs)
class ComplexWrapper(complex):
__metaclass__ = CmplxMeta
残念ながら、これは以前のソリューションと同じ動作をしているようです (たとえば、2 つのComplexWrapper
インスタンスが互いに追加された場合)。
確かに、私はメタクラスを完全には理解していません。多分私の問題は別の方法で解決できますか?
もちろん、 、 などの関連するメソッドを手動で再定義することもでき__add__
ます__subtract__
。
どんな助けでも感謝します。
編集: agf の回答への応答:
あなたのコードについて私が理解していない多くのこと:
__new__
メタクラスのメソッドはどこReturnTypeWrapper
から引数を取得しますか? それらが自動的に渡される場合、この場合、name = "Complex", bases = (complex), dict = {}
. あれは正しいですか?クラス データを自動的に渡すこの方法は、メタクラスに固有のものですか?cls = type.__new__(mcs, name, bases, dct)
の代わりに なぜ使用 するのcls = type(mcs, name, bases, dct)
ですか? の「他の意味」との混同を避けるためtype()
ですか?私はあなたのコードをコピーし、あなたのクラスに
__str__
との特別な実装を追加しました。しかし、うまくいきません。タイプの任意のオブジェクトを印刷すると、標準の Python 形式で印刷されます。メタクラスの for ループで 2 つのメソッドを取得する必要がありましたが、後で定義によってオーバーライドする必要があったため、私には理解できません。__repr__
ComplexWrapper
Complex
私のコードの関連セクション:
class Complex(complex):
__metaclass__ = ReturnTypeWrapper
wrapped_base = complex
def __str__(self):
return '(' + str(self.real) + ',' + str(self.imag) + ')'
def __repr__(self):
return '(' + repr(self.real) + ',' + repr(self.imag) + ')'
そしてその振る舞い:
>>> type(a)
<class 'Cmplx2.Complex'>
>>> a.__str__
<bound method Complex.wrapper of (1+1j)>
>>> a.__str__()
'(1+1j)'
>>>
回答に感謝します。回答でそれらに対処する場合は、上記を自由に編集/削除してください!