I have implemented a minimalistic enum by writing
class SymbolClass(type):
def __repr__(cls): return cls.__qualname__
class Symbol(metaclass=SymbolClass): pass
class Animal:
class Dog(Symbol): pass
class Cat(Symbol): pass
class Cow(Symbol): pass
It works perfectly well
>>> {Animal.Dog: 'Wan Wan', Animal.Cat: 'Nyaa', Animal.Cow: 'Moooh'}
{Animal.Dog: 'Wan Wan', Animal.Cat: 'Nyaa', Animal.Cow: 'Moooh'}
However, I wondered, if I could get rid of the metaclass by using a class method instead
class Symbol:
@classmethod
def __repr__(cls): return cls.__qualname__
class Animal:
class Dog(Symbol): pass
class Cat(Symbol): pass
class Cow(Symbol): pass
But it doesn't work as well :
>>> {Animal.Dog: 'Wan Wan', Animal.Cat: 'Nyaa', Animal.Cow: 'Moooh'}
{<class '__main__.Animal.Dog'>: 'Wan Wan', <class '__main__.Animal.Cat'>: 'Nyaa', <class '__main__.Animal.Cow'>: 'Moooh'}
Then I wrote a little piece of test code
class SymbolClass(type):
def __repr__(cls): return cls.__qualname__
def __str__(cls): return cls.__name__
class SymbolA(metaclass=SymbolClass): pass
class SymbolB:
@classmethod
def __repr__(cls): return cls.__qualname__
class SymbolC:
def __repr__(cls): return cls.__qualname__
class Animal:
class Dog(SymbolA): pass
class Cat(SymbolB): pass
class Cow(SymbolC): pass
import sys
def printcompare(n1, l1n, l1v, n2, l2n):
v1 = eval(n1)
v2 = eval(n2)
file = sys.stdout if v2==v1 else sys.stderr
print(f'{n1:>{l1n}} = {v1+",":<{l1v+2}} {n2:>{l2n}} = {v2}', file=file, flush=True)
for name in "SymbolClass", "SymbolA", "SymbolB", "SymbolC", "Animal", "Animal.Dog", "Animal.Cat", "Animal.Cow":
printcompare(f"{name}.__qualname__", 24, 11, f"repr({name})", 16)
Which provided me with the following result:
and I can't figure what make this difference. It looks like the @classmethod works as if it was a normal method...
