Python向量类别类型不可散列

时间:2019-08-03 16:07:10

标签: python oop hash

我喜欢理解我使用的所有代码,因此当我查看Vectorhere.时,我决定制作一个简化得多的版本,仅执行我认为需要的事情。 (我无法理解该类的__hash____slot__部分或设置了哈希的位置。

我的精简版本如下:

class vector:
    """Two-dimensional vector."""

    def __init__(self, x, y):
        """Initialize vector with coordinates: x, y."""

        self.x = x
        self.y = y

    def copy(self):
        """Return copy of vector."""

        # type_self = type(self)
        return vector(self.x, self.y)

    def move(self, other):
        """Move vector by other (in-place)."""

        self.__iadd__(other)

    def __eq__(self, other):
        """v.__eq__(w) -> v == w """
        if isinstance(other, vector):
            return self.x == other.x and self.y == other.y
        return NotImplemented

    def __iadd__(self, other):
        """v.__iadd__(w) -> v += w

        >>> v = vector(1, 2)
        >>> w = vector(3, 4)
        >>> v += w
        >>> v
        vector(4, 6)
        >>> v += 1
        >>> v
        vector(5, 7)

        """
        if isinstance(other, vector):
            self.x += other.x
            self.y += other.y
        else:
            self.x += other
            self.y += other
        return self

    def __repr__(self):
        """v.__repr__() -> repr(v)

        >>> v = vector(1, 2)
        >>> repr(v)
        'vector(1, 2)'

        """
        type_self = type(self)
        name = type_self.__name__
        return "{}({!r}, {!r})".format(name, self.x, self.y)

但是事实证明,我付出了比应有的努力,而当我尝试在下面的代码中使用该类时,我得到TypeError: unhashable type: 'vector'

from turtle import *
from random import randint
from utils import square, vector

p1xy = vector(-100, 0)
p1aim = vector(4, 0)
p1body = set()

p2xy = vector(100, 0)
p2aim = vector(-4, 0)
p2body = set()

def inside(head):
    "Return True if head inside screen."
    return -200 < head.x < 200 and -200 < head.y < 200

def get_best_move_flood_fill(aim):
    pass

def draw():
    "Advance players and draw game."
    p1xy.move(p1aim)
    p1head = p1xy.copy()

    change = get_best_move_flood_fill(p2aim)
    if change == 0:
        p2aim.rotate(90)
    elif change == 1:
        p2aim.rotate(-90)

    p2xy.move(p2aim)
    p2head = p2xy.copy()

    if not inside(p1head) or p1head in p2body:
        print('Player blue wins!')
        return

    if not inside(p2head) or p2head in p1body:
        print('Player red wins!')
        return

    print("xy: ", p1xy)
    print("head: ", p1head)
    print("Body: ", p1body)
    p1body.add(p1head)
    p2body.add(p2head)

    square(p1xy.x, p1xy.y, 3, 'red')
    square(p2xy.x, p2xy.y, 3, 'blue')
    update()
    ontimer(draw, 200)

setup(420, 420, 370, 0)
hideturtle()
tracer(False)
listen()
onkey(lambda: p1aim.rotate(90), 'a')
onkey(lambda: p1aim.rotate(-90), 'd')
onkey(lambda: p2aim.rotate(90), 'j')
onkey(lambda: p2aim.rotate(-90), 'l')
draw()
done()

有人可以告诉我为避免此错误而进行的最小调整,方法是修改类或使用它的方式?

我已经研究了给定的错误,但无法理解问题所在。可能是使用set(),但如果我不使用集合,则会有重复的元素。

1 个答案:

答案 0 :(得分:2)

问题是您的__eq__的{​​{1}}方法。定义该方法后,默认的vector by address方法将不再可用。您需要删除__hash__或定义__eq__,以使相等的向量也一样哈希。

还要注意,turtle本身定义了一个最小的__hash__类,您可能会发现它直接或作为您的Vec2D类的基类有用。