Python __repr__ и None - PullRequest
       51

Python __repr__ и None

4 голосов
/ 13 октября 2011

Я довольно новичок в Python, и в настоящее время мне нужно иметь __repr__ для класса SqlAlchemy.У меня есть целочисленный столбец, который может принимать значение Null, и SqlAlchemy преобразует его в None.Например:

class Stats(Base):
   __tablename__ = "stats"
   description = Column(String(2000))
   mystat = Column(Integer, nullable=True)

Как правильно представить поле «mystat» в функции __repr__, когда SqlAlchemy возвращает None?

Ответы [ 5 ]

10 голосов
/ 13 октября 2011

__repr__ должен возвращать строку, которая описывает объект. Если возможно, это должно быть допустимое выражение Python, которое оценивается как равный объект. Это верно для встроенных типов, таких как int или str:

>>> x = 'foo'
>>> eval(repr(x)) == x
True

Если это невозможно, это должна быть строка '<...>', однозначно описывающая объект. По умолчанию __repr__ является примером этого:

>>> class Foo(object):
        pass
>>>
>>> repr(Foo())
'<__main__.Foo object at 0x02A74E50>'

Он использует адрес объекта в памяти, чтобы однозначно идентифицировать его. Конечно, адрес ничего не говорит нам об объекте, поэтому полезно переопределить __repr__ и вернуть строку, описывающую состояние объекта.

Состояние объекта определяется другими объектами, которые он содержит, поэтому имеет смысл включить их repr в ваш. Это именно то, что list или dict делает:

>>> repr(['bar', Foo()])
"['bar', <__main__.Foo object at 0x02A74710>]"

В вашем случае состояние находится в ваших Column свойствах, поэтому вы хотите использовать их repr. Для этого вы можете использовать форматирование %r, оно вставит repr() аргумента:

def __repr__(self):
    return '<Stats: description=%r, mystat=%r>' % (self.description, self.mystat)

Эквивалент с использованием нового форматирования:

def __repr__(self):
    return '<Stats: description={0.description!r}, mystat={0.mystat!r}>'.format(self)
4 голосов
/ 10 апреля 2013

Я пытался найти общий метод __repr__, который можно было бы использовать с любым объектом SQLAlchemy, и нашел только эту страницу.Итак, я решил написать свое собственное, и вот что я сделал:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

if __debug__:
    # monkey-patch in useful repr() for all objects, but only in dev
    def tablerepr(self):
        return "<{}({})>".format(
            self.__class__.__name__,
            ', '.join(
                ["{}={}".format(k, repr(self.__dict__[k]))
                    for k in sorted(self.__dict__.keys())
                    if k[0] != '_']
            )
        )
    Base.__repr__ = tablerepr

Это расширяет класс Base для распечатки содержимого конкретного экземпляра.Итак, теперь каждый созданный мной объект, расширяющий Base, будет иметь __repr__ метод, который печатает не только имя класса и хэш экземпляра.if __debug__, так как это изменение может привести к утечке информации, которую вы, возможно, не хотите, чтобы утечка в производственной среде.Я также добавил sorted, чтобы отображение было согласованным.

0 голосов
/ 22 мая 2018

Разве не является generic_repr декоратором sqlalchemy-utils, предоставляющим решение для сообщества, соответствующее вашим потребностям?

Он оставляет это как None.

0 голосов
/ 13 октября 2011

'Ноль', если mystat - это None else mystat

0 голосов
/ 13 октября 2011

возможно repr(mystat) это то, что вы хотите?

...