本周在comp.lang.python上,一段“有趣的”代码是
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__)
在初始化期间
多重工厂
,
self.__factor
被设置。但后来,代码访问
self.factor
.
这样看来:
getattr(self, '_%s__factor' % self.__class__.__name__)
正在做的正是”
自我因子
“。
我们能一直以这种方式访问属性吗?
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
是
包含具有默认值的参数的默认参数值的元组,如果没有参数具有默认值,则为无。
“。
我们只是更改默认值吗?
因素
论点
__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)()
这意味着动态设置默认值只是无用的噪声,因为
乘数
从不在没有默认参数的情况下调用,
正确的
?
我们可以将其简化为:
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)
对的?
对于那些急于“这不是一个真正的问题”的人来说……再读一遍,我的问题是粗体+斜体