decypher和我混淆了MultiplierFactory

时间:2009-09-27 08:11:25

标签: python obfuscation python-datamodel

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

从名称MultiplierMultiplierFactory我们知道代码在做什么,但我们不确定确切的内部结构。我们先简化一下。

逻辑

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)

正确?

对于那些急于“这不是一个真正的问题”的人......再次阅读,我的问题是粗体+斜体

1 个答案:

答案 0 :(得分:1)

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

答:不可以。只有那些以双下划线开头的属性。他们会以这种方式进行混淆,以防止从课堂外意外访问/覆盖。

Q2:我们只是在这里更改__init__中因子参数的默认值吗?

答:是的。

Q2:对吗?

右。