问题
I have a bunch of classes which I'm using as singletons / enums / dict keys, e. g. like this:
class Side(object): pass
class Left(Side): pass
class Right(Side): pass
def show_state(distribution):
print "left is", distribution[Left]
print "right is", distribution[Right]
distribution = { Left: 3, Right: 7 }
show_state(distribution)
This works fine for me. But I'm having a small issue with debug output I sometimes do. Normally I use just print
for this like in print distribution
in the show_state()
function. I would love to have an output like:
{ Left: 3, Right: 7 }
But when I do this with these classes they are given out as something like this:
{<class '__main__.Right'>: 7, <class '__main__.Left'>: 3}
I tried to override the __repr__()
method of my classes to achieve this, but when I do it only influences instances of my classes (which I never create). I tried to use @classmethod
and @staticmethod
but nothing worked.
I assume that what I print is a Left
and therefore an instance of <type 'type'>
, so I would have to override the __repr__()
method of the type
class which is immutable, unfortunately.
Is there any other trick I could use so that print distribution
would print what I want?
Btw, according to the documentation, the __repr__()
method should return something which the Python parser would turn into an equal object again; this is definitely not the case with an output like <class '__main__.Right'>
but would definitely be the case with an output like Right
.
回答1:
You are correct that you'd have to override the __repr__
of the type of a class; you don't need to edit type
, you'd subclass type
to create a new metaclass:
class SimpleRepr(type):
def __repr__(cls):
return cls.__name__
then use that as your class metaclass; assuming you are using Python 3:
class Side(metaclass=SimpleRepr): pass
or if you are using Python 2 still:
class Side(object):
__metaclass__ = SimpleRepr
Subclasses of Side
inherit the metaclass too:
>>> class SimpleRepr(type):
... def __repr__(cls):
... return cls.__name__
...
>>> class Side(metaclass=SimpleRepr): pass
...
>>> class Left(Side): pass
...
>>> class Right(Side): pass
...
>>> { Left: 3, Right: 7 }
{Left: 3, Right: 7}
However, you could just have used instances:
class Side(object):
__slots__ = ('name',)
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
Left = Side('Left')
Right = Side('Right')
回答2:
Why not use an Enum with repr
from enum import Enum
class Side(Enum):
Left = 'Left'
Right = 'Right'
def __repr__(self):
return self.name
distribution = { Side.Left: 3, Side.Right: 7 }
print distribution # {Right: 7, Left: 3}
回答3:
The reason you're finding this difficult is that this is a strange use of classes, really. Have you considered just having one class, Side, and having left and right as instances?
class Side(object):
def __init__(self, direction):
self.direction = direction
def __repr__(self):
return self.direction
left = Side(left)
right = Side(right)
来源:https://stackoverflow.com/questions/42327233/defining-repr-of-classes-not-instances