2011-08-18 49 views
6

我了解如何提供对象的实例的非正式表示,但我有兴趣提供Class的非正式字符串表示形式名称。如何提供python类的非正式字符串表示形式(非实例)

特别是,我想覆盖当我打印类(__main __。SomeClass)时返回的内容。

>>> class SomeClass: 
... def __str__(self): 
...  return 'I am a SomeClass instance.' 
... 
>>> SomeClass 
<class __main__.SomeClass at 0x2ba2f0fd3b30> 
>>> print SomeClass 
__main__.SomeClass 
>>> 
>>> x = SomeClass() 
>>> x 
<__main__.SomeClass instance at 0x2ba2f0ff3f38> 
>>> print x 
I am a SomeClass instance. 

回答

8

你的问题叫做元类混淆。在A类中,如果A.__str__(self)是A实例方法的模板,我如何为A自身提供__str__()方法?元类救援。

下面的链接可以比我在这里更好地解释这一点。

http://gnosis.cx/publish/programming/metaclass_1.html

http://gnosis.cx/publish/programming/metaclass_2.html

简单例子在这里:

class AMeta(type): 
    def __str__(self): 
     return "I am the truly remarkable class A" 

class A(object): 
    __metaclass__ = AMeta 
    def __str__(self): 
     return "I am an A instance" 

print A 
I am the truly remarkable class A 
print A() 
I am an A instance 

顺便说一句,你可以为__repr__这样做。

+0

已编辑,增加了一个例子。 –

+0

优秀的文档和示例,谢谢! – adam

+0

我想你的意思是'def __str __(self):'在'class A'中而不是'def str(self):' –

1

改为取代__repr__

>>> class SomeClass(object): 
... def __repr__(self): 
...  return 'I am a SomeClass instance.' 
+0

不,这覆盖了实例表示。 –

+0

'__repr__'也适用于实例。它不会做他所说的,我尝试用@classmethod装饰'__repr__',但没有工作:)。 – utdemir

+0

你的代码仍然不起作用,因为对于repr(SomeClass)有用,你的'SomeClass .__ repr__'不能有自变量。 –

2

要更改类的字符串表示:

class MC(type): 
    def __repr__(cls): 
     return 'I am Test' 

class Test: 
    __metaclass__ = MC 
    pass 

print Test 

工作正常。

如果您在定义__str__时调用了repr(Test),它将不会使用您的自定义消息。

但是,如果你定义__repr__像我一样,和str(Test)被调用,它使用custimized消息,因为__repr__是后备和__str__type定义。

如果你想要做的是改变它的名字:

def renamer(name): 
    def wrapper(func): 
     func.__name__ = name 
     return func 
    return wrapper 

@renamer('Not Test') 
class Test: pass 
print Test.__name__ 

Test.__name__ = 'Test Again' 
print Test.__name__  

都将工作,改变类的名字。

+0

他想改变班级的印刷方式(如str),而不是名字。 –

+0

看看我的第一个代码示例,它确实如此。第二个例子是改变名称的例子。事实上,我的回答是在你之前做的。 – agf

1

你可以通过元类实现。

观察:

>>> class MyMeta(type): 
...  def __init__(cls, name, bases, dct): 
...    super(MyMeta, cls).__init__(name, bases, dct) 
... 
...  def __repr__(self): 
...    return "MyMeta is Cool: " + self.__name__ 
... 
>>> class FooType(metaclass=MyMeta): 
...  pass 
... 
>>> FooType 
MyMeta is Cool: FooType 
3

你就必须重写元类__str__方法。我不知道你为什么想要这样做,但是无论如何这都是。

>>> class InformalType(type): 
...  def __str__(self): 
...    return self.__name__ 
... 
>>> class MyFoo(object): 
...  __metaclass__ = InformalType 
...  pass 
... 
>>> MyFoo 
<class '__main__.MyFoo'> 
>>> print MyFoo 
MyFoo 
>>> foo = MyFoo() 
>>> foo 
<__main__.MyFoo object at 0x7fdf9581f910> 
>>> print foo 
<__main__.MyFoo object at 0x7fdf9581f910> 
>>> 
+0

+1比我的版本更干净。 – Skurmedel

相关问题