通过函数和类引用和上下文

时间:2018-05-02 13:59:40

标签: python python-3.x

首先说我是python的新手,我使用的是python版本3.6.5 我不太喜欢python将函数输入作为“对象引用”处理的方式。

这里给出的例子非常简单,只是为了说明我的观点。

这是我正在运行的第一个代码(错误的行为):

integer = 0

def func(t): return integer

class FooClass(object):
    def __init__(self, input_function):
        self.function = input_function

    def give_value(self, index):
        print(self.function(index))

foo_object = FooClass(func)

foo_object.give_value(0)
# Output >> 0

integer = 1

foo_object.give_value(0)
# Output >> 1

我希望我的FooClass对象完全独立于外部变化。

这是我正在运行的第二个代码(正确行为):

integer = 0

def step_function(integer_input):   
    def func(t): return integer_input

    return FooClass(func)

class FooClass(object):
    def __init__(self, input_function):
        self.function = input_function

    def give_value(self, index):
        print(self.function(index))

foo_object = step_function(integer)

foo_object.give_value(0)
# Output >> 0

integer = 1

foo_object.give_value(0)
# Output >> 0

我很满意,但我不明白为什么会这样。实际上,我担心我的self.function引用了step_function调用期间定义的'integer_input'。所以它引用了一个可以覆盖的可用内存空间(如果在python中有任何意义)。

提前致谢!

1 个答案:

答案 0 :(得分:0)

因此,要解释为什么您的代码的功能不同:ERR_CONNECTION_REFUSED是一个引用整数的名称。在您的第一个示例中,您在integer中使用此名称,这将创建一个闭包,该闭包从全局范围中包含对func的引用并将其传递。因此,所有将来的调用都会引用全局范围内名称integer所持有的内容。

在第二个示例中,您创建了新名称integer以引用integer_input并引用integer中的integer_input。这会创建一个闭包,用于封装 function 范围内对func的引用并将其传递。

如果你能以某种方式改变integer_input范围内引用的integer_input,你会遇到同样的问题,但这很难做到(而且几乎不可能无意中做到)。

如果您希望更新第一个示例以按预期工作,则可以使用以下代码:

step_function

这会手动创建一个闭包,以将名称 func = (lambda value: lambda t: value)(integer) integer引用的对象分离,类似于您的第二个示例。

或者,要更新当前的结构以执行类似的操作:

integer

请注意,这两种方法是等效的,只是语法不同。