Reputation: 5533
Is there a builtin ABC for enforcing __str__
to be implemented in subclasses? Or a typing protocol?
I want a function that only accepts classes with __str__
__hash__
and __eq__
. I've found Hashable
but not Stringable
Upvotes: 1
Views: 2591
Reputation: 5349
There's no such a builtin abstract class, but you can enforce those requirements.
from abc import ABC, abstractmethod
class Required(ABC):
@abstractmethod
def __str__(self) -> str:
...
@abstractmethod
def __hash__(self) -> int:
...
@abstractmethod
def __eq__(self, other) -> bool:
...
>>> class Impl(Required): ...
>>> i = Impl()
TypeError: Can't instantiate abstract class Impl with abstract methods __eq__, __hash__, __str__
Also, you could check a specific structural subtyping for equality at runtime, and return a TypeError
if it's not the case (but it may not be a best practice):
from typing import Protocol, runtime_checkable
@runtime_checkable
class HasValue(Protocol):
value: int
class Impl(Required):
# also define __str__ and __hash__
@property
def value(self):
return 42
def __eq__(self, other):
if not isinstance(other, HasValue):
raise TypeError
return self.value == other.value
class Valued:
value = 42
class NotValued:
...
>>> i = Impl()
>>> v = Valued()
>>> n = NotValued()
>>> i == v # both have self.value
True
>>> v == n # self.value not enforced
False
>>> i == n # self.value enforced
TypeError
Upvotes: 0
Reputation: 3360
There is no such built-in ABC
. In fact, every class has this method inherited from object
:
The default implementation defined by the built-in type object calls object.repr().
See docs.
In [1]: class Foo: pass
In [2]: str(Foo())
Out[2]: '<__main__.Foo object at 0x7fcf10e219f0>'
In [3]: print(Foo())
<__main__.Foo object at 0x7fcf10e23d00>
In [4]: print(Foo().__str__())
<__main__.Foo object at 0x7fcf10e20d60>
In [5]: print(Foo().__repr__())
<__main__.Foo object at 0x7fcf10e20af0>
In [6]: object().__repr__()
Out[6]: '<object object at 0x7fcf119c6810>'
In [7]: object().__str__()
Out[7]: '<object object at 0x7fcf119c67c0>'
Upvotes: 3