方法参数转换:'tuple'没有属性'attribute'

时间:2012-09-18 10:06:18

标签: python

我有一个简单的向量类,它覆盖了几个算术运算符:

class vec2:
    x = 0.0
    y = 0.0

    def __add__(self,other):
        self.x = other.x
        self.y = other.y

    def __mul__(self,scalar):
        self.x *= scalar
        self.y *= scalar

然而,在其他地方我称之为这样的方法:

class foo:
    position = vec2()
    velocity = vec2()

    def update(self,dt):
        self.position += self.velocity * dt;

但是,一旦我进入更新功能,解释器就会出错:

'tuple' object has no attribute 'x'

__add__函数内。

为什么__add__中的“other”作为元组而不是vec2传递?

整个代码为here

1 个答案:

答案 0 :(得分:1)

使用__add____mul__时返回新的向量,并处理'奇怪'类型:

class vec2:
    x = 0.0
    y = 0.0

    def __init__(self, x=0.0, y=0.0):
        self.x, self.y = x, y

    def __add__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        result = self.__class__(self.x, self.y)
        result.x += other.x
        result.y += other.y
        return result

    def __iadd__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        self.x += other.x
        self.y += other.y
        return self

    def __mul__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        result = self.__class__(self.x, self.y)
        result.x *= other.x
        result.y *= other.y
        return result

    def __imul__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        self.x *= other.x
        self.y *= other.y
        return self

要就地修改向量,请使用__iadd____imul__;这些仍然需要返回新值;这可以是self

请注意,这只是传入(x, y)坐标的元组而不是句柄。如果要支持该用例,则需要专门处理它:

class foo:
    def __init__(self, position=(0.0, 0.0), velocity=(1.0, 1.0)):
        self.position = vec2()
        self.velocity = vec2(*velocity)

    def update(self, dt):
        if isinstance(dt, tuple):
            dt = vec2(*dt)
        self.position += self.velocity * dt;

另请注意,您不应该为位置和力度值使用类属性;我在上面使用了实例属性,并借此机会将位置和速度设置为合理的值。

演示:

>>> f = foo()
>>> f.position.x, f.position.y
(0.0, 0.0)
>>> f.update((1, 2))
>>> f.position.x, f.position.y
(1.0, 2.0)