学習課題として、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__ComplexWrapperComplex
私のコードの関連セクション:
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)'
>>>
回答に感謝します。回答でそれらに対処する場合は、上記を自由に編集/削除してください!