代码之家  ›  专栏  ›  技术社区  ›  Nicolas Dumazet

跟我说那个模糊的多重工厂

  •  2
  • Nicolas Dumazet  · 技术社区  · 16 年前

    本周在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)
    

    对的?

    对于那些急于“这不是一个真正的问题”的人来说……再读一遍,我的问题是粗体+斜体

    1 回复  |  直到 16 年前
        1
  •  1
  •   Lennart Regebro    16 年前

    Q1。我们能一直以这种方式访问属性吗?

    不,只有那些属性以双下划线开头。它们以这种方式变得模糊,以防止从类外部意外访问/重写。

    问题2:我们只是在 __init__ 在这里?

    是的。

    Q2:对吗?

    正确的。

    推荐文章