我该如何实现__hash__和__str__

时间:2011-09-04 11:59:41

标签: python

我在codereview.se上有一个名为WeakBoundMethod(source的类)。我想了解一下如何实施__hash__()的指导原则。此外,Python 3自动提供__repr__()函数,所以我想我不应该费心去重新定义它(?)。那么__str__()怎么样,我理解的是对象的人类可读文本表示;我也应该定义它吗?任何指导方针?

关于散列函数...
我希望它根据它包装的绑定方法的__self____func__生成哈希。我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

如果有疑问,请不要实施魔术方法。默认是有原因的,并且没问题。在您的情况下,完全没有必要实现__hash__(如果您要实现它,您还必须实现__eq__),除非您希望有人拥有方法集或字典。< / p>

__str__可能很有用。在您的情况下,其结果应包括:

  • 班级名称,以避免与其他任何内容混淆
  • 该功能是否有效
  • 如果它还活着,则其str()结果用于标识函数,例如,按名称

答案 1 :(得分:0)

聚会晚了9年,但是对于我来说,这才是搜索结果的顶部...

关于:

此外,Python 3自动提供了 repr ()函数,所以我想我应该再为它重新定义(?)。关于 str (),我理解的是对象的人类可读文本表示形式;我也应该定义吗?有任何准则吗?

除非没有,否则默认的实现是好的(例如,直到您想要更有用的东西为止)。

关键点:

class Message:
    _msg: str

    def __init__(self, msg: str):
        self._msg = msg

    # ... other custom behavior that makes this more useful than just a string


print(Message("asdf"))       # '<__main__.Wat object at 0x104a99128>'
print(str(Message("asdf")))  # '<__main__.Wat object at 0x104a991d0>'
print(repr(Message("asdf"))) # '<__main__.Wat object at 0x104a991d0>'

当然,存在默认值,但是如果您有一些有助于打印到屏幕,日志等的内容,<module.class object at address>格式真的有用吗?

与...进行对比

class Message:
    _msg: str
    _urgent: bool

    def __init__(self, msg: str, urgent:bool = False):
        self._msg = msg
        self._urgent = urgent

    @classmethod
    def urgent(cls, msg: str) -> "Message":
        return cls(msg, urgent=True)

    def __str__(self) -> str:
        if not self._urgent:
            return self._msg

        return f"URGENT: {self._msg.upper()}"

    def __repr__(self) -> str:
        return f"{type(self).__name__}({self})"

    # ... other custom behavior that makes this more useful than just a string


print(Message("hey there!"))                   # hey there!
print(str(Message("hey there!")))              # hey there!
print(str(Message.urgent("look behind you")))  # URGENT: LOOK BEHIND YOU
print(repr(Message.urgent("look behind you"))) # Message(URGENT: LOOK BEHIND YOU)

以上建议“如果有疑问,请不要实施魔术方法。”是部分正确的(如果您不需要功能,为什么要实现它?),但这似乎也表明您可能不需要。魔术方法实际上是要被覆盖的-这是我们通过在Python中“内置”的有用行为来丰富我们的类,并避免了很多其他必要的样板化序列化为字符串,创建自定义迭代器或上下文管理器等。