shr*_*are 4 python oop methods class class-method
我试图覆盖__str__和__repr__类,如下面的代码所示。每当我调用 instance_method 时都会调用新方法,但对 class_method 的对象调用保持不变(请参阅下面的代码片段和输出,以便于了解)。有没有办法可以覆盖__str__and __repr__for@classmethod以便cls可以更改的值?
我也尝试添加__str__和__repr__as@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))
Run Code Online (Sandbox Code Playgroud)
上面代码的输出:
class method '<class '__main__.Abc'>'
static method
instance method class method
static method
class method '<class '__main__.Abc'>'
6
Run Code Online (Sandbox Code Playgroud)
Python 不会__str__在类本身上查找 a ,就像它不会__str__在实例上使用set一样。这适用于所有特殊方法,请参阅Python 数据模型中的特殊方法查找:
对于自定义类,特殊方法的隐式调用只有在对象类型上定义时才能保证正常工作,而不是在对象的实例字典中。
简而言之,str(something)不使用something.__str__(),它本质上使用type(something).__str__(something) (*)正是因为您不希望__str__类上的定义在您使用时中断str(class_object),其中class_object.__str__()没有实例传入 as self。
您必须定义一个metaclass,因为这是创建类并由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"
Run Code Online (Sandbox Code Playgroud)
该metaclass=MetaAbc语法告诉Python来使用MetaAbc,而不是仅仅type作为的元类Abc类; 现在type(Abc)返回MetaAbc:
>>> type(Abc)
<class '__main__.MetaAbc'>
Run Code Online (Sandbox Code Playgroud)
and 和MetaAbc.__repr__andMetaAbc.__str__用于表示类,或将其转换为字符串;处理实例时使用类上的方法:
>>> Abc
__repr__ on the metaclass
>>> print(Abc)
__str__ on the metaclass
>>> Abc('foo')
instance method repr
>>> print(Abc('foo'))
Added foo
Run Code Online (Sandbox Code Playgroud)
该@classmethod装饰并没有把一个方法到不同的命名空间; 类方法是一个类的普通属性,只是被不同地绑定。@classmethod例如,仍然可以在实例上访问,但将始终传递给类对象,即使通过实例访问时也是如此:
>>> Abc.class_method()
class method '__str__ on the metaclass'
>>> Abc("foo").class_method()
class method '__str__ on the metaclass'
Run Code Online (Sandbox Code Playgroud)
(*) Python 使用描述符绑定来实现方法、类方法和静态方法。特殊方法查找通过遍历类层次结构直接查找函数对象,以避免触发正常绑定过程,然后手动绑定它们。所以str(something)翻译成next(c.__dict__['__str__'] for c in type(something).__mro__ if '__str__' in c.__dict__).__get__(something, type(something))(). 这有点啰嗦,对于普通方法,这可以简化type(something).__str__(something)为具有相同效果。