You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Python方法返回Point数据类集合?解决不可哈希错误

修复TypeError: unhashable type: 'Point'并满足set[Point]返回类型要求

错误原因

Python里集合(set)的元素必须是可哈希类型。默认用@dataclass装饰的类,因为自动生成了__eq__方法,会把__hash__设为None,导致实例不可哈希,没法添加到集合里。

另外你的代码还有几个小问题:

  • all_points_visited是局部变量,不是实例属性,类方法根本访问不到
  • visited()、visited_count()这些方法缺了self参数,没法获取实例里的数据
  • 直接修改self.m的属性,会改动传入的原始Point实例,容易引发意外问题

修复方案

1. 让Point类可哈希

给Point的dataclass装饰器加frozen=True参数,把它变成不可变数据类。这样Python会自动生成合适的__hash__方法,实例就能被添加到集合里了:

from dataclasses import dataclass

@dataclass(frozen=True)
class Point:
    x: int
    y: int
    z: int

2. 修正Movements类的属性与方法

把all_points_visited改成实例属性,给所有实例方法加上self参数,确保方法能正确访问实例数据:

class Movements:
    def __init__(self, p: Point):
        # 新建Point实例,避免修改传入的原始对象
        self.m = Point(p.x, p.y, p.z)
        self.all_points_visited = set()
        self.all_points_visited.add(self.m)
    
    def move_to(self, dir: str) -> None:
        # 计算新坐标,创建新的Point实例
        x, y, z = self.m.x, self.m.y, self.m.z
        if dir[1] == "x":
            x += 1 if dir[0] == "+" else -1
        elif dir[1] == "y":
            y += 1 if dir[0] == "+" else -1
        elif dir[1] == "z":
            z += 1 if dir[0] == "+" else -1
        
        self.m = Point(x, y, z)
        self.all_points_visited.add(self.m)
    
    def teleport_to(self, point: Point) -> None:
        self.m = Point(point.x, point.y, point.z)
        self.all_points_visited.add(self.m)
    
    def visited(self) -> set[Point]:
        return self.all_points_visited
    
    def visited_count(self) -> int:
        return len(self.all_points_visited)

关于“能否将Point转为元组处理”的问题

如果严格要求visited()必须返回set[Point],那不能用元组存储。因为内部存元组的话,返回的集合类型会是set[tuple[int, int, int]],不符合set[Point]的类型标注,过不了严格的类型检查。就算把元组再转回Point实例返回,也多此一举——直接让Point可哈希是最简洁合规的方案。

测试代码

# 测试
m = Movements(Point(10, -30, 0))
m.move_to("+x")
m.teleport_to(Point(5, 5, 5))
print(m.visited_count())  # 输出3
print(m.visited())        # 输出{Point(x=10, y=-30, z=0), Point(x=11, y=-30, z=0), Point(x=5, y=5, z=5)}

内容的提问来源于stack exchange,提问作者Avery

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:25:34