2017-02-19 3 views
1

У меня есть куча классов, которые я использую в качестве одноименных/enums/dict ключей, например. г. например:определение repr() классов (а не экземпляров)

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) 

Это прекрасно работает для меня. Но у меня небольшая проблема с выходом отладки, которую я иногда делаю. Обычно я использую только print для этого как в print distribution в функции show_state(). Я хотел бы иметь выход как:

{ Left: 3, Right: 7 } 

Но когда я делаю это с этими классами они приведены как нечто вроде этого:

{<class '__main__.Right'>: 7, <class '__main__.Left'>: 3} 

Я попытался переопределить __repr__() метод моих классов для этого, но когда я это делаю, это влияет только на экземпляров моих классов (которые я никогда не создавал). Я пытался использовать @classmethod и @staticmethod, но ничего не получилось.

Я предполагаю, что я печатаю это Left и поэтому экземпляр <type 'type'>, так что я бы переопределить __repr__() метод type класса, который неизменен, к сожалению.

Есть ли какой-либо другой трюк, который я мог бы использовать, чтобы print distribution распечатывал то, что я хочу?

Btw, согласно документации, метод __repr__() должен возвращать то, что парсер Python снова превратится в равный объект; это определенно не так с выходом, как <class '__main__.Right'>, но определенно будет иметь дело с выходом, например Right.

ответ

3

Вы правы, что вы должны переопределить __repr__ типа класса; Вам не нужно редактировать type, вы подклассtype создать new metaclass:

class SimpleRepr(type): 
    def __repr__(cls): 
     return cls.__name__ 

затем использовать его в качестве класса метакласса; если вы используете Python 3:

class Side(metaclass=SimpleRepr): pass 

или если вы используете Python 2 еще:

class Side(object): 
    __metaclass__ = SimpleRepr 

Подклассы Side наследуют метакласса тоже:

>>> 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} 

Однако, вы могли бы просто использовались экземпляры:

class Side(object): 
    __slots__ = ('name',) 
    def __init__(self, name): 
     self.name = name 
    def __repr__(self): 
     return self.name 

Left = Side('Left') 
Right = Side('Right') 
+0

И я думаю, вы могли бы сэкономить несколько байт, определяя '__slots__' –

+0

Конечно, но я имел в виду 2-й вариант, где вы создаете экземпляры. –

+0

Ну, конечно, да. * Facepalm *. –

0

Причина, по которой вам трудно, заключается в том, что это странное использование классов. Считаете ли вы, что у вас есть только один класс, Сторона, и как влево, так и вправо?

class Side(object): 
    def __init__(self, direction): 
     self.direction = direction 

    def __repr__(self): 
     return self.direction 

left = Side(left) 
right = Side(right) 
1

Почему бы не использовать Enum с предст

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} 
+0

У меня будет '__repr__' return' '{}. {}'. format (self .__ class__, self .__ name __) 'в этом случае, но в остальном хорошая идея! –

+0

@MartijnPieters Спасибо. Требование OP только для того, чтобы напечатать имя стороны. – gipsy

+1

Не * довольно *. Они хотят показать одно и то же выражение Python, которое было использовано для создания словаря в первую очередь. В случае Enum это 'Side.Left', а не' Left'. –

Смежные вопросы