类可以通过__str__方法充当字符串,也可以通过__call__方法充当函数。它可以作为列表或元组吗?
class A (object):
def __???__ (self):
return (1, 2, 3)
>>> a = A()
>>> a * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3)
修改...
这是一个更好的例子来帮助澄清上述内容。
class Vector (object):
def __init__ (self):
self.vec = (1,2,3)
def __???__ (self):
# something like __repr__; non-string
return self.vec
class Widget (object):
def __init__ (self):
self.vector = Vector()
>>> w = Widget()
>>> w.vector
(1, 2, 3) # not a string representation (at least, before being repr'd here)
基本上,我想要__repr__之类的东西,它不会返回一个字符串,但是当我只是调用指向Vector实例的名称时,它会返回一个元组(或列表),但我不想丢失其余的实例中的异能,比如访问其他属性和方法。我也不想使用w.vector.vec
来获取数据。我希望vector可以像w的元组属性一样,同时仍然可以执行w.vector.whatever()
之类的操作,或者覆盖__mul__,这样我就可以通过w.vector * 5
缩放向量。可能的?
答案 0 :(得分:3)
根据您的目标,您可以创建一个继承自list
或tuple
等内置类的类:
>>> class A(tuple):
... def speak(self):
... print "Bark!"
...
>>> a = A((1,2,3)) # extra parens needed to distinguish single tuple arg from 3 scalar args
>>> a * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3)
>>> a.speak()
Bark!
考虑到你的Vector用例,子类化元组很可能会成功。
import math
class Vector(tuple):
def magnitude(self):
return math.sqrt( self[0]*self[0]+self[1]*self[1]+self[2]*self[2] )
答案 1 :(得分:2)
对于示例中的特定行为(A*3
提供了A
中数据的三个连续副本),您希望实现__mul__()
运算符。
例如,这些是等价的:
>>> a = [1,2,3]
>>> a*3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> a.__mul__(3)
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>>
更一般地说,如果要实现序列类型,则必须实现所有operations defined for sequence types。你必须定义 -
A[3]
的含义(__getitem__()
,__setitem__()
)A[1:10]
的含义(__getslice__()
)for item in A:
的含义(__iter__()
)等等。
以下是list
s上定义的完整方法列表:
>>> pprint.pprint(dict(list.__dict__))
{'__add__': <slot wrapper '__add__' of 'list' objects>,
'__contains__': <slot wrapper '__contains__' of 'list' objects>,
'__delitem__': <slot wrapper '__delitem__' of 'list' objects>,
'__delslice__': <slot wrapper '__delslice__' of 'list' objects>,
'__doc__': "list() -> new empty list\nlist(iterable) -> new list initialized from iterable's items",
'__eq__': <slot wrapper '__eq__' of 'list' objects>,
'__ge__': <slot wrapper '__ge__' of 'list' objects>,
'__getattribute__': <slot wrapper '__getattribute__' of 'list' objects>,
'__getitem__': <method '__getitem__' of 'list' objects>,
'__getslice__': <slot wrapper '__getslice__' of 'list' objects>,
'__gt__': <slot wrapper '__gt__' of 'list' objects>,
'__hash__': None,
'__iadd__': <slot wrapper '__iadd__' of 'list' objects>,
'__imul__': <slot wrapper '__imul__' of 'list' objects>,
'__init__': <slot wrapper '__init__' of 'list' objects>,
'__iter__': <slot wrapper '__iter__' of 'list' objects>,
'__le__': <slot wrapper '__le__' of 'list' objects>,
'__len__': <slot wrapper '__len__' of 'list' objects>,
'__lt__': <slot wrapper '__lt__' of 'list' objects>,
'__mul__': <slot wrapper '__mul__' of 'list' objects>,
'__ne__': <slot wrapper '__ne__' of 'list' objects>,
'__new__': <built-in method __new__ of type object at 0x1E1DACA8>,
'__repr__': <slot wrapper '__repr__' of 'list' objects>,
'__reversed__': <method '__reversed__' of 'list' objects>,
'__rmul__': <slot wrapper '__rmul__' of 'list' objects>,
'__setitem__': <slot wrapper '__setitem__' of 'list' objects>,
'__setslice__': <slot wrapper '__setslice__' of 'list' objects>,
'__sizeof__': <method '__sizeof__' of 'list' objects>,
'append': <method 'append' of 'list' objects>,
'count': <method 'count' of 'list' objects>,
'extend': <method 'extend' of 'list' objects>,
'index': <method 'index' of 'list' objects>,
'insert': <method 'insert' of 'list' objects>,
'pop': <method 'pop' of 'list' objects>,
'remove': <method 'remove' of 'list' objects>,
'reverse': <method 'reverse' of 'list' objects>,
'sort': <method 'sort' of 'list' objects>}
答案 2 :(得分:0)
当您致电 str 时,该课程不会充当字符串。它创建并返回一个NEW字符串对象。基本上当你在一个对象上调用str(something)
时,这才是真正发生的事情:
a = str(someObject)
a = someObject.__str__()
所以str
函数基本上可以被认为是这样做的:
def str(variable):
return variable.__str__()
当您致电list()
,tuple()
,set()
等时,情况也是如此。如果我认为你的问题是正确的:
tuple()
,list()
和set()
都调用了类的__iter__()
方法,所以您要做的是:
class MyClass(object):
...
def __iter__(self):
...
return myIterable