метод сортировки

У меня есть класс, экземпляры которого должны отформатировать выходные данные, как указано пользователем. Существует формат по умолчанию, который можно переопределить. Я реализовал его так:

class A: def __init__(self, params): # ... # by default printing all float values as percentages with 2 decimals self.format_functions = {float: lambda x : '{:.2%}'.format(x)} def __str__(self): # uses self.format_functions to format output # ... a = A(params) print(a) # uses default output formatting # overriding default output formatting # float printed as percentages 3 decimal digits; bool printed as Y / N a.format_functions = {float : lambda x: '{:.3%}'.format(x), bool : lambda x: 'Y' if x else 'N'} print(a) 

Это нормально? Дайте мне знать, есть ли лучший способ разработать это.

К сожалению, мне нужно разжечь экземпляры этого класса. Но только функции, определенные на верхнем уровне модуля, можно мариновать; lambda функции недоступны, поэтому атрибут экземпляра format_functions прерывает травление.

Я попробовал переписать это, чтобы использовать метод класса вместо лямбда-функций, но по той же причине все равно не повезло:

 class A: @classmethod def default_float_format(cls, x): return '{:.2%}'.format(x) def __init__(self, params): # ... # by default printing all float values as percentages with 2 decimals self.format_functions = {float: self.default_float_format} def __str__(self): # uses self.format_functions to format output # ... a = A(params) pickle.dump(a) # Can't pickle <class 'method'>: attribute lookup builtins.method failed 

Обратите внимание, что травление здесь не работает, даже если я не переопределяю значения по умолчанию; просто тот факт, что я присвоил self.format_functions = {float : self.default_float_format} разрывает его.

Что делать? Я бы предпочел не загрязнять пространство имен и разрушать инкапсуляцию, определяя default_float_format на уровне модуля.

Кстати, почему в мире pickle создает это ограничение? Конечно, он чувствует себя как безвозмездная и существенная боль для конечного пользователя.

2 Solutions collect form web for “метод сортировки”

Для травления экземпляров или функций класса (и, следовательно, методов) пиренейский рассол зависит от того, что их имя доступно как глобальные переменные – ссылка на метод в словаре указывает на имя, которое недоступно в глобальном пространстве имен, которое лучше iis сказал «пространство имен модулей» –

Вы можете обойти это, настроив травление своего класса, создав методы «__setstate__» и «__getstate__», но я думаю, что вы лучше, поскольку функция форматирования не зависит от какой-либо информации объекта или самого класса ( и даже если какая-то функция форматирования делает это, вы можете передать это как параметры) и определить функцию вне области видимости класса.

Это работает (Python 3.2):

 def default_float_format( x): return '{:.2%}'.format(x) class A: def __init__(self, params): # ... # by default printing all float values as percentages with 2 decimals self.format_functions = {float: default_float_format} def __str__(self): # uses self.format_functions to format output pass a = A(1) pickle.dumps(a) 

Если вы используете модуль dill , любой из ваших двух подходов будет «работать» как есть . dill может мариновать lambda а также примеры классов, а также методы класса.

Не нужно загрязнять пространство имен и прерывать инкапсуляцию, поскольку вы сказали, что не хотите делать …, но другой ответ .

dill в основном составляет десять лет или около того, стоит найти правильную функцию copy_reg которая регистрирует, как сериализовать большинство объектов в стандартном питоне. Ничего особенного или сложного, это просто требует времени. Так почему же pickle это делать для нас? Почему у pickle есть это ограничение?

Ну, если вы посмотрите на документы pickle , ответ будет таков: https://docs.python.org/2/library/pickle.html#what-can-be-pickled-and-unpickled

В основном: функции и классы маринуются по ссылке.

Это означает, что pickle не работает над объектами, определенными в __main__ , и он также не работает на многих динамически модифицированных объектах. dill регистрирует __main__ как модуль, поэтому имеет допустимое пространство имен. dill также дал вам возможность не рассортировать по ссылке, поэтому вы можете сериализовать динамически измененные объекты … и экземпляры классов, методы класса (связанные и несвязанные) и т. д.

  • Как преобразовать список нескольких целых чисел в одно целое?
  • Удаление согласных из строки в Python
  • Python 3: отправить метод генераторов
  • python3 - узнав о поиске, этот очень простой пример не работает правильно
  • Правильное использование глобальных переменных в Python 3
  • Получить имя папки в Python
  • Python 3 Online Interpreter / Shell
  • Неправильно ли использовать встроенное имя функции в качестве атрибута или идентификатора метода?
  • Python - лучший язык программирования в мире.