为什么变量值在Python中的闭包函数中有变化?

时间:2017-06-14 10:22:13

标签: python python-2.7 python-3.x closures decorator

所有!

我尝试编写装饰器来为方法创建别名。

我同时使用Python 2.7.8 和Python 3.4.3

我的代码:

from __future__ import print_function

def register_aliases(aliases):
    def wrapper(function):
        function._aliases = aliases
        return function
    return wrapper

def create_aliases(cls):
    for original_name, original_function in cls.__dict__.copy().items():
        if hasattr(original_function, '_aliases'):
            for alias_name, custom_args in original_function._aliases.items():
                print('Original function name:', original_name)
                print('Original function:', original_function)
                def alias_function(*args, **kwargs):
                    kwargs.update(custom_args)
                    print('Original function name:', original_name)
                    print('Original function:', original_function)
                    return original_function(*args, **kwargs)
                setattr(cls, alias_name, alias_function)
    return cls

@create_aliases
class MyClass(object):

    @register_aliases({
        'method10': {'b': 10},
        })
    def method(self, a, b):
        print('Result of method:', a+b)


if __name__ == '__main__':
    mc = MyClass()
    mc.method(1, 2)
    mc.method10(3)

但变量original_name和original_function在运行时已发生变化。

在Python 2.7.8上执行代码的示例(original_function总是在 doc 上更改):

$ python class_test.py 
Original function name: method
Original function: <function method at 0x7fb7ec7aac80>
Result of method: 3
Original function name: __doc__
Original function: None
Traceback (most recent call last):
  File "class_test.py", line 37, in <module>
    mc.method10(3)
  File "class_test.py", line 20, in alias_function
    return original_function(*args, **kwargs)
TypeError: 'NoneType' object is not callable

在Python 3.4.3上执行代码的示例(original_function随机更改):

on __dict __:

$ python3 class_test.py 
Original function name: method
Original function: &lt;function MyClass.method at 0x7f2235bbdea0>
Result of method: 3
Original function name: __dict__
Original function: &lt;attribute '__dict__' of 'MyClass' objects>
Traceback (most recent call last):
  File "class_test.py", line 37, in <module>
    mc.method10(3)
  File "class_test.py", line 20, in alias_function
    return original_function(*args, **kwargs)
TypeError: 'getset_descriptor' object is not callable

on __weakref __:

$ python3 class_test.py 
Original function name: method
Original function: &lt;function MyClass.method at 0x7faaa8de5ea0>
Result of method: 3
Original function name: __weakref__
Original function: &lt;attribute '__weakref__' of 'MyClass' objects>
Traceback (most recent call last):
  File "class_test.py", line 37, in <module>
    mc.method10(3)
  File "class_test.py", line 20, in alias_function
    return original_function(*args, **kwargs)
TypeError: 'getset_descriptor' object is not callable

或按预期保持:

$ python3 class_test.py 
Original function name: method
Original function: &lt;function MyClass.method at 0x7fa28d26aea0>
Result of method: 3
Original function name: method
Original function: &lt;function MyClass.method at 0x7fa28d26aea0>
Result of method: 13

0 个答案:

没有答案