覆盖 python 中@classmethods 的 __str__ 方法
Overriding the __str__ method for @classmethods in python
我试图为 class 覆盖 __str__
和 __repr__
,如下面的代码所示。每当我调用 instance_method 时都会调用新方法,但对 class_method 的对象调用保持不变(为清楚起见,请参阅下面的代码片段和输出)。有没有一种方法可以覆盖 @classmethod
的 __str__
和 __repr__
以便可以更改 cls
的值?
我也尝试添加 __str__
和 __repr__
作为 @classmethod
但没有任何改变。
class Abc:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Added {self.name}"
def __repr__(self):
return f"instance method repr"
def instance_method(self):
print(f"instance method {self}")
@classmethod
def __repr__(cls):
return f"class method"
@classmethod
def __str__(cls):
return f"class method"
@classmethod
def class_method(cls):
print(f"class method '{cls}'")
@staticmethod
def static_method():
print(f"static method")
def add(self, a: int,b: int,c: int) -> int:
return a+b+c
o = Abc("alpha")
o.class_method()
o.static_method()
o.instance_method()
Abc.static_method()
Abc.class_method()
print(o.add(1,2,3))
以上代码的输出:
class method '<class '__main__.Abc'>'
static method
instance method class method
static method
class method '<class '__main__.Abc'>'
6
Python 不会在 class 本身上寻找 __str__
,就像它不会在实例上使用 __str__
集一样。这适用于 所有 特殊方法,请参阅 Python 数据模型中的 Special method lookup:
For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
简而言之,str(something)
不使用 something.__str__()
,它本质上使用 type(something).__str__(something)
(*) 正是因为您不想要class 上 __str__
的定义在您使用 str(class_object)
时会中断,其中 class_object.__str__()
没有要作为 self
.[= 传入的实例41=]
您必须定义一个 metaclass,因为那是 'thing' 生成 classes 并由 type(class_object)
:
返回
class MetaAbc(type):
def __repr__(cls):
return "__repr__ on the metaclass"
def __str__(cls):
return "__str__ on the metaclass"
class Abc(metaclass=MetaAbc):
def __init__(self, name):
self.name = name
def __str__(self):
return f"Added {self.name}"
def __repr__(self):
return "instance method repr"
metaclass=MetaAbc
语法告诉 Python 使用 MetaAbc
而不是 type
作为 Abc
[=71] 的元 class =];现在 type(Abc)
returns MetaAbc
:
>>> type(Abc)
<class '__main__.MetaAbc'>
和MetaAbc.__repr__
和MetaAbc.__str__
用于表示一个class,或将其转换为字符串; class 上的方法在处理实例时使用:
>>> Abc
__repr__ on the metaclass
>>> print(Abc)
__str__ on the metaclass
>>> Abc('foo')
instance method repr
>>> print(Abc('foo'))
Added foo
@classmethod
装饰器不会将方法放入不同的命名空间; class 方法是 class 的普通属性,只是绑定方式不同。 @classmethod
仍然可以在实例上访问,例如,但是 总是 被传递给 class 对象,即使通过实例访问时也是如此:
>>> Abc.class_method()
class method '__str__ on the metaclass'
>>> Abc("foo").class_method()
class method '__str__ on the metaclass'
(*) Python 使用 descriptor binding 实现方法,class 方法和静态方法。特殊方法查找直接遍历class层级查找函数对象,避免触发正常的绑定过程,然后手动绑定。所以 str(something)
转换为 next(c.__dict__['__str__'] for c in type(something).__mro__ if '__str__' in c.__dict__).__get__(something, type(something))()
。这有点啰嗦,对于 normal 方法,这可以简化为 type(something).__str__(something)
,因为它具有相同的效果。
我试图为 class 覆盖 __str__
和 __repr__
,如下面的代码所示。每当我调用 instance_method 时都会调用新方法,但对 class_method 的对象调用保持不变(为清楚起见,请参阅下面的代码片段和输出)。有没有一种方法可以覆盖 @classmethod
的 __str__
和 __repr__
以便可以更改 cls
的值?
我也尝试添加 __str__
和 __repr__
作为 @classmethod
但没有任何改变。
class Abc:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Added {self.name}"
def __repr__(self):
return f"instance method repr"
def instance_method(self):
print(f"instance method {self}")
@classmethod
def __repr__(cls):
return f"class method"
@classmethod
def __str__(cls):
return f"class method"
@classmethod
def class_method(cls):
print(f"class method '{cls}'")
@staticmethod
def static_method():
print(f"static method")
def add(self, a: int,b: int,c: int) -> int:
return a+b+c
o = Abc("alpha")
o.class_method()
o.static_method()
o.instance_method()
Abc.static_method()
Abc.class_method()
print(o.add(1,2,3))
以上代码的输出:
class method '<class '__main__.Abc'>'
static method
instance method class method
static method
class method '<class '__main__.Abc'>'
6
Python 不会在 class 本身上寻找 __str__
,就像它不会在实例上使用 __str__
集一样。这适用于 所有 特殊方法,请参阅 Python 数据模型中的 Special method lookup:
For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
简而言之,str(something)
不使用 something.__str__()
,它本质上使用 type(something).__str__(something)
(*) 正是因为您不想要class 上 __str__
的定义在您使用 str(class_object)
时会中断,其中 class_object.__str__()
没有要作为 self
.[= 传入的实例41=]
您必须定义一个 metaclass,因为那是 'thing' 生成 classes 并由 type(class_object)
:
class MetaAbc(type):
def __repr__(cls):
return "__repr__ on the metaclass"
def __str__(cls):
return "__str__ on the metaclass"
class Abc(metaclass=MetaAbc):
def __init__(self, name):
self.name = name
def __str__(self):
return f"Added {self.name}"
def __repr__(self):
return "instance method repr"
metaclass=MetaAbc
语法告诉 Python 使用 MetaAbc
而不是 type
作为 Abc
[=71] 的元 class =];现在 type(Abc)
returns MetaAbc
:
>>> type(Abc)
<class '__main__.MetaAbc'>
和MetaAbc.__repr__
和MetaAbc.__str__
用于表示一个class,或将其转换为字符串; class 上的方法在处理实例时使用:
>>> Abc
__repr__ on the metaclass
>>> print(Abc)
__str__ on the metaclass
>>> Abc('foo')
instance method repr
>>> print(Abc('foo'))
Added foo
@classmethod
装饰器不会将方法放入不同的命名空间; class 方法是 class 的普通属性,只是绑定方式不同。 @classmethod
仍然可以在实例上访问,例如,但是 总是 被传递给 class 对象,即使通过实例访问时也是如此:
>>> Abc.class_method()
class method '__str__ on the metaclass'
>>> Abc("foo").class_method()
class method '__str__ on the metaclass'
(*) Python 使用 descriptor binding 实现方法,class 方法和静态方法。特殊方法查找直接遍历class层级查找函数对象,避免触发正常的绑定过程,然后手动绑定。所以 str(something)
转换为 next(c.__dict__['__str__'] for c in type(something).__mro__ if '__str__' in c.__dict__).__get__(something, type(something))()
。这有点啰嗦,对于 normal 方法,这可以简化为 type(something).__str__(something)
,因为它具有相同的效果。