我可以这样做:
class Person:
def __init__(self, firstName, lastName):
self.firstName = firstName
self.lastName = lastName
def __str__(self):
print self.firstName
bob = Person('Robert', 'Smith')
print bob
>>> Robert
但我想更普遍地做,而不是手动覆盖每个班级__str__
。我尝试过使用装饰器和元类,但我很困惑。我认为应该可以做类似的事情,但我不知道如何使装饰器或元类接受一个参数,仍然创建一个正确的可实例化对象:
class strAs:
def __init__(self, prop):
self.prop = prop
def __call__(self, cls):
decoratorSelf = self
def wrapper(*args, **kwargs):
def __str__(s):
return getattr(s, decoratorSelf.prop)
c = cls(*args, **kwargs)
c.__str__ = __str__
return c
return wrapper
@strAs(prop='firstName')
class Person:
def __init__(self, firstName, lastName):
self.firstName = firstName
self.lastName = lastName
@strAs(prop='name')
class Dog:
def __init__(self, name):
self.name = name
bob = Person('Robert', 'Smith')
fido = Dog('Fido')
print bob
print fido
>>> Robert
Fido
但这失败了:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/tmp/py6495xVN", line 33, in <module>
print bob
TypeError: __str__() takes exactly 1 argument (0 given)
我无法弄清楚__str__()
未将self
传递给它的原因。我注意到bob
类的Person
实例似乎缺少一些典型的对象方法,所以我试着像这样继承object
(并添加了两个print语句):
class strAs(object):
def __init__(self, prop):
self.prop = prop
def __call__(self, cls):
decoratorSelf = self
def wrapper(*args, **kwargs):
print 'in wrapper'
def __newstr__(s):
print 'in newstr'
return getattr(s, decoratorSelf.prop)
c = cls(*args, **kwargs)
c.__str__ = __newstr__
return c
return wrapper
@strAs(prop='firstName')
class Person(object):
def __init__(self, firstName, lastName):
self.firstName = firstName
self.lastName = lastName
@strAs(prop='name')
class Dog(object):
def __init__(self, name):
self.name = name
bob = Person('Robert', 'Smith')
fido = Dog('Fido')
print bob
print fido
现在我得到了一些显然正确调用__str__
的输出:
>>> in wrapper
in wrapper
<__main__.Person object at 0x7f179389e450>
<__main__.Dog object at 0x7f179389e510>
但它没有按原样打印属性,并且它甚至不会使用__newstr__
函数,因为它不打印{{1} }。但是,如果我检查in newstr
,我发现它确实是bob.__str__
。
我一定错过了一些明显的东西,但我觉得现在这已经过去了。 :/
答案 0 :(得分:3)
在你的情况下,我只是让装饰者修改这个类。如
class strAs:
def __init__(self, prop):
self.prop = prop
def __call__(self, cls):
prop = self.prop
def __str__(s):
return getattr(s, prop)
cls.__str__ = __str__
return cls