考虑这个类:
class foo(object):
pass
默认的字符串表示形式是这样的:
>>> str(foo)
"<class '__main__.foo'>"
如何使此显示自定义字符串?
参见如何使用print()打印类的实例?有关类实例的相应问题。
事实上,这个问题实际上是那个问题的一个特例——因为在Python中,类本身也是属于它们自己类的对象——但如何应用这个建议并不直接明显,因为默认的“类的类”是预定义的。
考虑这个类:
class foo(object):
pass
默认的字符串表示形式是这样的:
>>> str(foo)
"<class '__main__.foo'>"
如何使此显示自定义字符串?
参见如何使用print()打印类的实例?有关类实例的相应问题。
事实上,这个问题实际上是那个问题的一个特例——因为在Python中,类本身也是属于它们自己类的对象——但如何应用这个建议并不直接明显,因为默认的“类的类”是预定义的。
当前回答
因为你需要一个元类来做这件事,但是你需要元类本身有一个参数,你可以用一个元类来通过词法作用域捕获名字。
我发现这比一些替代方案更容易阅读/遵循。
class type_: pass
def create_type(name):
# we do this so that we can print the class type out
# otherwise we must instantiate it to get a proper print out
class type_metaclass(type):
def __repr__(self):
return f'<{name}>'
class actual_type(type_, metaclass=type_metaclass):
pass
return actual_type
my_type = create_type('my_type')
print(my_type)
# prints "<my_type>"
其他回答
另一个答案是:
装饰 类型(在ide中保持自动补全) 从v3.10起生效
import typing
class ClassReprMeta(type):
def __repr__(self):
attrs_str = ", ".join(
f"{key}={getattr(self, key)}"
for key in dir(self)
if not key.startswith("_")
)
return f"{self.__name__}({attrs_str})"
T = typing.TypeVar("T")
def printable_class(cls: T) -> T:
"""Decorator to make a class object printable"""
return ClassReprMeta(cls.__name__, cls.__bases__, dict(cls.__dict__))
@printable_class
class CONFIG:
FIRST = 1
SECOND = 2
print(CONFIG) # CONFIG(FIRST=1, SECOND=2)
如果你必须在__repr__或__str__之间选择,请选择第一个,因为默认实现__str__在未定义时调用__repr__。
自定义Vector3示例:
class Vector3(object):
def __init__(self, args):
self.x = args[0]
self.y = args[1]
self.z = args[2]
def __repr__(self):
return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)
def __str__(self):
return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)
在这个例子中,repr再次返回一个可以直接使用/执行的字符串,而str作为调试输出更有用。
v = Vector3([1,2,3])
print repr(v) #Vector3([1,2,3])
print str(v) #x:1, y:2, z:3
只是在所有的好答案之外,加上我的装饰版本:
from __future__ import print_function
import six
def classrep(rep):
def decorate(cls):
class RepMetaclass(type):
def __repr__(self):
return rep
class Decorated(six.with_metaclass(RepMetaclass, cls)):
pass
return Decorated
return decorate
@classrep("Wahaha!")
class C(object):
pass
print(C)
stdout:
Wahaha!
缺点:
你不能在没有超类的情况下声明C(没有类C:) C实例将是一些奇怪的派生实例,因此为实例添加__repr__可能是一个好主意。
因为你需要一个元类来做这件事,但是你需要元类本身有一个参数,你可以用一个元类来通过词法作用域捕获名字。
我发现这比一些替代方案更容易阅读/遵循。
class type_: pass
def create_type(name):
# we do this so that we can print the class type out
# otherwise we must instantiate it to get a proper print out
class type_metaclass(type):
def __repr__(self):
return f'<{name}>'
class actual_type(type_, metaclass=type_metaclass):
pass
return actual_type
my_type = create_type('my_type')
print(my_type)
# prints "<my_type>"
class foo(object):
def __str__(self):
return "representation"
def __unicode__(self):
return u"representation"