本周在comp.lang.python上,Steven D'Aprano的一段“有趣”代码是posted,作为家庭作业问题的笑话答案。这是:
class MultiplierFactory(object):
def __init__(self, factor=1):
self.__factor = factor
@property
def factor(self):
return getattr(self, '_%s__factor' % self.__class__.__name__)
def __call__(self, factor=None):
if not factor is not None is True:
factor = self.factor
class Multiplier(object):
def __init__(self, factor=None):
self.__factor = factor
@property
def factor(self):
return getattr(self,
'_%s__factor' % self.__class__.__name__)
def __call__(self, n):
return self.factor*n
Multiplier.__init__.im_func.func_defaults = (factor,)
return Multiplier(factor)
twice = MultiplierFactory(2)()
我们知道twice
等同于答案:
def twice(x):
return 2*x
从名称Multiplier
和MultiplierFactory
我们知道代码在做什么,但我们不确定确切的内部结构。我们先简化一下。
if not factor is not None is True:
factor = self.factor
not factor is not None is True
相当于not factor is not None
,也是factor is None
。结果:
if factor is None:
factor = self.factor
到现在为止,这很容易:)
另一个有趣的观点是好奇的factor
访问者。
def factor(self):
return getattr(self, '_%s__factor' % self.__class__.__name__)
在初始化MultiplierFactory
期间,self.__factor
已设置。但稍后,代码访问self.factor
。
然后似乎:
getattr(self, '_%s__factor' % self.__class__.__name__)
正在做“self.__factor
”。
我们是否可以始终以这种方式访问属性?
def mygetattr(self, attr):
return getattr(self, '_%s%s' % (self.__class__.__name__, attr))
无论如何,此时,这是简化的代码:
class MultiplierFactory(object):
def __init__(self, factor=1):
self.factor = factor
def __call__(self, factor=None):
if factor is None:
factor = self.factor
class Multiplier(object):
def __init__(self, factor=None):
self.factor = factor
def __call__(self, n):
return self.factor*n
Multiplier.__init__.im_func.func_defaults = (factor,)
return Multiplier(factor)
twice = MultiplierFactory(2)()
现在代码几乎干净了。可能唯一令人费解的是:
Multiplier.__init__.im_func.func_defaults = (factor,)
那里有什么?我查看了datamodel doc,发现func_defaults
是“一个包含默认参数的元组,这些参数有默认值,如果没有参数有默认值,则为None ” 。 我们只是在 factor
中更改 __init__
参数的默认值吗? 结果代码将是:
class MultiplierFactory(object):
def __init__(self, factor=1):
self.factor = factor
def __call__(self, factor=None):
if factor is None:
factor = self.factor
class Multiplier(object):
def __init__(self, innerfactor=factor):
self.factor = innerfactor
def __call__(self, n):
return self.factor*n
return Multiplier(factor)
twice = MultiplierFactory(2)()
这意味着动态设置默认值只是无用的噪音,因为Multiplier
从未在没有默认参数的情况下调用, 正确 ?
我们可以将其简化为:
class MultiplierFactory(object):
def __init__(self, factor=1):
self.factor = factor
def __call__(self, factor=None):
if factor is None:
factor = self.factor
def my_multiplier(n):
return factor*n
return my_multiplier
twice = MultiplierFactory(2)() # similar to MultiplierFactory()(2)
正确?
对于那些急于“这不是一个真正的问题”的人......再次阅读,我的问题是粗体+斜体
答案 0 :(得分:1)
Q1。我们可以一直以这种方式访问属性吗?
答:不可以。只有那些以双下划线开头的属性。他们会以这种方式进行混淆,以防止从课堂外意外访问/覆盖。
Q2:我们只是在这里更改__init__
中因子参数的默认值吗?
答:是的。
Q2:对吗?
右。