誰かがPythonでクラスを作成し、独自の__repr__()
メソッドを指定しなかった場合、デフォルトのメソッドが提供されます。ただし、デフォルトの__repr__()
と同じまたは類似の動作をする関数を作成するとします。ただし、クラスの実際の__repr__()
がオーバーロードされた場合でも、この関数にデフォルトの__repr__()
メソッドの動作を持たせる必要があります。つまり、誰かが__repr__()
メソッドをオーバーロードしたかどうかに関係なく、デフォルトの__repr__()
と同じ動作をする関数を記述したいとします。どうすればいいですか?
_class DemoClass:
def __init__(self):
self.var = 4
def __repr__(self):
return str(self.var)
def true_repr(x):
# [magic happens here]
s = "I'm not implemented yet"
return s
obj = DemoClass()
print(obj.__repr__())
print(true_repr(obj))
_
print(obj.__repr__())
は_4
_を出力しますが、print(true_repr(obj))
は次のように出力します。
_<__main__.DemoClass object at 0x0000000009F26588>
_
object.__repr__(obj)
を使用できます。これが機能するのは、デフォルトのrepr
の動作がobject.__repr__
で定義されているためです。
他の人が指摘しているように、最良の答えはおそらくobject.__repr__
を直接使用することです。しかし、大まかに次のように同じ機能を実装できます。
>>> def true_repr(x):
... type_ = type(x)
... module = type_.__module__
... qualname = type_.__qualname__
... return f"<{module}.{qualname} object at {hex(id(x))}>"
...
そう....
>>> A()
hahahahaha
>>> true_repr(A())
'<__main__.A object at 0x106549208>'
>>>
通常、そのために_object.__repr__
_を使用できますが、これは「 every アイテムのオブジェクトreprになります。したがって、次のようになります。
_>>> object.__repr__(4)
'<int object at 0xa6dd20>'
_
int
はobject
ですが、___repr__
_がオーバーライドされているためです。
one の上書きレベルを上げたい場合は、super(..)
を使用できます。
_>>> super(type(4), 4).__repr__() # going up one level
'<int object at 0xa6dd20>'
_
int
の場合、これも_<int object at ...>
_を出力することを意味しますが、たとえばint
をサブクラス化する場合は、次のようにint
の___repr__
_を再度使用します。
_class special_int(int):
def __repr__(self):
return 'Special int'
_
次に、次のようになります。
_>>> s = special_int(4)
>>> super(type(s), s).__repr__()
'4'
_
ここでは、super(..)
を使用して proxy オブジェクトを作成します。 Superは、オブジェクトのメソッド解決順序(MRO)をウォークし、関数をオーバーライドした最初の関数(s
のスーパークラスから)を見つけようとします。単一の継承を使用する場合、それは関数をオーバーライドする最も近い親ですが、多重継承が含まれる場合、これはより注意が必要です。したがって、その親の___repr__
_を選択し、その関数を呼び出します。
通常、クラス(ここではtype(s)
)は固定クラスであり、 not はsuper
自体のタイプに依存しないため、これもs
のかなり奇妙なアプリケーションです。そうしないと、そのようなsuper(..)
呼び出しが複数回発生すると、無限ループが発生するためです。
しかし、通常、とにかくオーバーライドを解除することは悪い考えです。プログラマーが関数をオーバーライドする理由は、動作を変更するです。もちろん、これを尊重しないと、いくつかの便利な機能が得られる場合がありますが、多くの場合、コードコントラクトが満たされないという事実が生じます。たとえば、プログラマーが___eq__
_をオーバーライドする場合、別のクラスのハッシュと実際の___hash__
_を使用する場合、プログラマーは___eq__
_もオーバーライドします。
マジック関数を直接呼び出すことも、アンチパターンと見なされることが多いため、これも避けた方がよいでしょう。