【问题标题】:Assign external function to class variable in Python在Python中将外部函数分配给类变量
【发布时间】:2016-06-29 10:59:43
【问题描述】:

我正在尝试将在别处定义的函数分配给类变量,以便以后可以在实例的方法之一中调用它,如下所示:

from module import my_func

class Bar(object):
    func = my_func
    def run(self):
        self.func()  # Runs my function

问题是这会失败,因为在做self.func()时,实例是作为第一个参数传递的。

我想出了一个技巧,但我觉得很难看,有人有替代方案吗?

In [1]: class Foo(object):
   ...:     func = lambda *args: args
   ...:     def __init__(self):
   ...:         print(self.func())
   ...:

In [2]: class Foo2(object):
   ...:     funcs = [lambda *args: args]
   ...:     def __init__(self):
   ...:         print(self.funcs[0]())
   ...:

In [3]: f = Foo()
(<__main__.Foo object at 0x00000000044BFB70>,)

In [4]: f2 = Foo2()
()

编辑:行为与内置函数不同!

In [13]: from math import pow

In [14]: def pow_(a, b):
   ....:     return pow(a, b)
   ....:

In [15]: class Foo3(object):
   ....:     func = pow_
   ....:     def __init__(self):
   ....:         print(self.func(2, 3))
   ....:

In [16]: f3 = Foo3()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-16-c27c8778655e> in <module>()
----> 1 f3 = Foo3()

<ipython-input-15-efeb6adb211c> in __init__(self)
      2     func = pow_
      3     def __init__(self):
----> 4         print(self.func(2, 3))
      5

TypeError: pow_() takes exactly 2 arguments (3 given)

In [17]: class Foo4(object):
   ....:     func = pow
   ....:     def __init__(self):
   ....:         print(self.func(2, 3))
   ....:

In [18]: f4 = Foo4()
8.0

【问题讨论】:

    标签: python oop python-2.x


    【解决方案1】:

    Python 函数是descriptor objects,当类上的属性访问它们时,实例会导致它们被绑定为方法。

    如果您想防止这种情况发生,请使用staticmethod function 将函数包装在不绑定到实例的不同描述符中:

    class Bar(object):
        func = staticmethod(my_func)
        def run(self):
            self.func()
    

    或者,通过方法上的__func__ 属性访问未绑定的函数:

    def run(self):
        self.func.__func__()
    

    或者直接进入类__dict__属性完全绕过描述符协议:

    def run(self):
        Bar.__dict__['func']()
    

    至于math.pow,那不是Python 函数,因为它是用C 代码编写的。大多数内置函数都是用 C 编写的,而且大多数不是描述符。

    【讨论】:

    • 最后一个代码块失败(Bar object has no attribute Bar),如果我删除self,我会得到TypeError: unbound method must be called with instance as first argument
    • @astrojuanlu:啊,是的,对不起,Python 2。我将更新该选项以绕过描述符协议。
    • 如果我可能会滥用您的耐心,您能解释一下为什么当我们使用内置函数时描述符的行为会有所不同吗?我刚刚尝试了math.pow,但实例没有作为第一个参数传递!我用额外的信息更新了我的问题
    • @astrojuanlu: math.pow 不是一个普通的 Python 函数,它不是一个描述符对象。并非所有内置函数(用 C 代码编写)都是描述符。
    猜你喜欢
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-18
    相关资源
    最近更新 更多