У меня есть класс, экземпляры которого должны форматировать вывод в соответствии с инструкциями пользователя. Существует формат по умолчанию, который можно переопределить. Я реализовал это так:
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
создает это ограничение? Это, конечно, ощущается как неоправданная и существенная боль для конечного пользователя.