How should I implement __hash__ and __str__
I have a class called WeakBoundMethod (source on codereview.se). I'd like some guidelines about how I should implement __hash__()
. Also, Python 3 automatically provides a __repr__()
function, so I guess I shouldn't bother redefining it then (?). What about __str__()
, which I u开发者_C百科nderstand is a human readable text representation of the object; should I define that as well? any guidelines?
About the hashing function...
I'd like it to generate the hash based on the__self__
and __func__
of the bound method it is wrapping. How can I do that? If in doubt, don't implement magic methods. The defaults are there for a reason and will be fine. In your case, it's completely unnecessary to implement __hash__
(and if you would implement it, you'd have to implement __eq__
as well) unless you expect someone to have a set or dictionary of methods.
__str__
can be useful. In your case, its result should include:
- The class name, to avoid confusion with anything else
- Whether the function is alive or not
- If it is alive, its
str()
result to identify the function, say, by name
9 years late to the party, but since this came up at the top of search results for me...
Regarding:
Also, Python 3 automatically provides a repr() function, so I guess I shouldn't bother redefining it then (?). What about str(), which I understand is a human readable text representation of the object; should I define that as well? any guidelines?
The default implementations are fine until they aren't (ie. until you want something more useful).
Case in point:
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>'
Sure, the defaults exist, but if you have something that's helpful to print to screen, logs, etc. is the <module.class object at address>
format really helpful?
Contrast that with...
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)
The advice above, "If in doubt, don't implement magic methods." is partially true (if you don't need functionality, why implement it?) but it also seems to indicate that you probably shouldn't. Magic methods are actually meant to be overwritten - it's how we enrich our classes with useful behavior that is 'built in' to Python and avoid a lot of otherwise necessary boilerplate to serialize to strings, create custom iterators or context managers, etc.
精彩评论