酸洗课方法 [英] pickling class method
问题描述
class A:
def __init __(self,params):
# ...
#默认情况下将所有浮点值打印为2位小数的百分比
self.format_functions = {float:lambda x:'{:.2%}'。format(x)}
def __str __(self):
#使用self.format_functions格式输出
#...
a = A(params)
print(a)#uses默认输出格式
#覆盖默认输出格式
#float打印为百分比3位数字; bool打印为Y / N
a.format_functions = {float:lambda x:'{:.3%}'。format(x),
bool:lambda x:'Y'if x else' N'}
print(a)
是吗?让我知道如果有更好的方法来设计这个。
不幸的是,我需要pickle这个类的实例。但只有在模块顶层定义的功能可以被酸洗; lambda
函数是不可以的,所以我的 format_functions
实例属性打破了酸洗。
我尝试重写这个以使用类方法而不是lambda函数,但是由于同样的原因仍然没有运气:
class A:
@classmethod
def default_float_format(cls,x):
return'{:.2%}'。format(x)
def __init __(self, params):
#...
#默认情况下将所有浮点值打印为2位小数的百分比
self.format_functions = {float:self.default_float_format}
def __str __(self ):
#使用self.format_functions格式输出
#...
a = A(params)
pickle.dump(a)#不能腌< class'method'> ;:属性查询builtins.method失败
请注意,即使我不覆盖默认值也可以工作;只是事实上,我分配了 self.format_functions = {float:self.default_float_format}
打破它。
做?我不想污染命名空间并通过在模块级别定义 default_float_format
来打破封装。
顺便提一下,为什么在世界上, pickle
创建这个限制?
对于酸洗实例或函数(因此,方法),Python的pickle取决于它们的名称可用作全局变量 - 对字典中的方法的引用指向全局名称空间中不可用的名称 - 我更好地说module namespace -
通过创建__setstate__和__getstate__方法,可以定制你的类的酸洗,但是我认为你会更好,因为格式化函数不依赖于任何对象或类本身的信息(即使某些格式化函数可以将其作为参数传递),也可以在类范围之外定义一个函数。
这样做(Python 3.2):
def default_float_format(x):
return'{:.2% }'。format(x)
class A:
def __init __(self,params):
#...
#默认情况下将所有浮点值打印为2位小数的百分比
self.format_functions = {float: default_float_format}
def __str __(self):
#使用self.format_functions格式输出
pass
a = A(1)
pickle.dumps a)
I have a class whose instances need to format output as instructed by the user. There's a default format, which can be overridden. I implemented it like this:
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)
Is it ok? Let me know if there is a better way to design this.
Unfortunately, I need to pickle instances of this class. But only functions defined at the top level of the module can be pickled; lambda
functions are unpicklable, so my format_functions
instance attribute breaks the pickling.
I tried rewriting this to use a class method instead of lambda functions, but still no luck for the same reason:
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
Note that pickling here doesn't work even if I don't override the defaults; just the fact that I assigned self.format_functions = {float : self.default_float_format}
breaks it.
What to do? I'd rather not pollute the namespace and break encapsulation by defining default_float_format
at the module level.
Incidentally, why in the world does pickle
create this restriction? It certainly feels like a gratuitous and substantial pain to the end user.
For pickling of class instances or functions (and therefore methods), Python's pickle depend that their name is available as global variables - the reference to the method in the dictionary points to a name that is not available in the global name space - which iis better said "module namespace" -
You could circunvent that by customizing the pickling of your class, by creating teh "__setstate__" and "__getstate__" methods - but I think you be better, since the formatting function does not depend on any information of the object or of the class itself (and even if some formatting function does, you could pass that as parameters), and define a function outside of the class scope.
This does work (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)
这篇关于酸洗课方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!