Какой лучше __repr__ для пользовательского класса Python? - PullRequest
7 голосов
/ 15 июня 2011

Кажется, что функция __repr__ может возвращаться разными способами.

У меня есть класс InfoObj, в котором хранится множество вещей, некоторые из которых я не хочу, чтобы пользователи этого класса устанавливали сами. Я понимаю, что в python ничего не защищено, и они все равно могут просто нырнуть и установить его, но, похоже, определение его в __init__ повышает вероятность того, что кто-то увидит его и предположит, что это просто - передать его.

(Пример: логические значения, которые устанавливаются функцией проверки, когда она определяет, что объект был полностью заполнен, и значения, которые вычисляются из других значений, когда для этого сохраняется достаточно информации ... например, A = B + C , поэтому, как только A и B установлены, C рассчитывается и объект помечается как Valid = True.)

Итак, учитывая все это, это лучший способ спроектировать вывод __ repr __?

    bob = InfoObj(Name="Bob")
    # Populate bob.

    # Output type A:
    bob.__repr__()
'<InfoObj object at 0x1b91ca42>'

    # Output type B:
    bob.__repr__()
'InfoObj(Name="Bob",Pants=True,A=7,B=5,C=2,Valid=True)'

    # Output type C:
    bob.__repr__()
'InfoObj.NewInfoObj(Name="Bob",Pants=True,A=7,B=5,C=2,Valid=True)'

... смысл типа C состоял бы в том, чтобы не с радостью воспринимать все вещи, которые я установил 'private' в C ++, в качестве аргументов для конструктора, и заставлять товарищей по команде, используя класс, настраивать его с помощью функций интерфейса, даже если это больше работа для них. В этом случае я бы определил конструктор, который не принимает определенные вещи, и отдельную функцию, которую немного сложнее заметить, для целей __repr__

Если это имеет какое-то значение, я планирую сохранить эти объекты Python в базе данных, используя их вывод __repr__, и извлечь их, используя eval(), по крайней мере, если я не придумаю лучший способ. Следствием того, что товарищ по команде создает полный объект вручную, а не выполняет надлежащие функции интерфейса, является просто то, что один тип поиска информации может быть нестабильным, пока кто-то не выяснит, что он сделал.

1 Ответ

9 голосов
/ 15 июня 2011

Метод __repr__ предназначен для получения наиболее полезного результата для разработчика, а не для конечного пользователя, поэтому только вы действительно можете ответить на этот вопрос.Однако обычно я бы выбрал вариант B. Вариант A не очень полезен, а параметр C излишне многословен - вы все равно не знаете, как импортируется ваш модуль.Другие могут предпочесть вариант C.

Однако, если вы хотите хранить объекты Python в качестве базы данных, используйте pickle.

import pickle
bob = InfoObj(Name="Bob")

> pickle.dumps(bob)
b'...some bytestring representation of Bob...'

> pickle.loads(pickle.dumps(bob))
Bob(...)

Если вы используете более старый Python (до 3.x), затем обратите внимание, что cPickle быстрее, но pickle более расширяемо.Pickle будет работать с некоторыми вашими классами без какой-либо конфигурации, но для более сложных объектов вы можете захотеть написать собственные сборщики.

...