Python:如果静态 class 变量获得不同的函数引用指针,如何解决?

Python: How to fix, if a static class variable gets a different function reference pointer?

我想知道为什么我的 class 调用带有参数的引用函数(分配给静态 class 变量)。如果我将函数引用分配给普通 class 变量,它会像预期的那样工作。

这是我的示例代码:

# This function is not editable, because it's imported from an API
def getStuff(): 
    print "I do my stuff!!!"

class foo(object):
    GET_STUFF = getStuff

    def __init__(self):
        print "static var: ",self.GET_STUFF
        self.GET_STUFF()

print "outer func: ",getStuff
foo()

出现以下错误:

outer func:  <function getStuff at 0x0000000003219908>
static var:  <bound method foo.getStuff of <__main__.foo object at 0x00000000030AB358>>
Traceback (most recent call last):
  File "C:/example.py", line 13, in <module>
    foo()
  File "C:/example.py", line 10, in __init__
    self.GET_STUFF()
TypeError: getStuff() takes no arguments (1 given)

为了解决这个问题,我将构造函数中的函数引用指向 class 变量:

class foo(object):
    def __init__(self):
        self.GET_STUFF = getStuff
        print "static var: ",self.GET_STUFF
        self.GET_STUFF()

结果如预期,工作正常:

outer func:  <function getStuff at 0x000000000331F908>
static var:  <function getStuff at 0x000000000331F908>
I do my stuff!!!

但是:

我想使用静态 class 变量,因为它易于阅读,并且易于为不同的 API 设置。所以最后我会想出一些包装器 classes,如下所示:

from API01 import getStuff01
from API02 import getStuff02

# bar calculates stuff object from the API (it calls GET_STUFF)
# and stores the object into self.stuff
import bar 

class foo01(bar):
    GET_STUFF = getStuff01

    def DoSomething(self, volume):
        self.stuff.volume = volume

class foo02(bar):
    GET_STUFF = getStuff02

    def DoSomething(self, volume):
        self.stuff.volume = volume

# [...] and so on..

有没有办法让它以我想要设置包装器的方式工作 classes,或者我真的必须为每个包装器定义一个构造函数 class?

谢谢

错误的原因是

self.GET_STUFF()

其实就是

tmp = getattr(self, 'GET_STUFF')
tmp(self)

这意味着这两个class是等价的:

def foo(self): pass

class Foo(object):
     a = foo

class Bar(object):
     def a(self): pass

在这两种情况下,函数对象作为成员添加到 class,这意味着对于 Python,函数需要 self 作为第一个参数。

实现你想要的:

from API01 import getStuff01

def wrapper01(self):
    getStuff01()

class foo01(object):
    GET_STUFF = wrapper01

只是为了扩展 Aaron 的回答,如果你想拥有静态方法,你可以使用 @staticmethod 装饰器:

class Calc:

  @staticmethod
  def sum(x, y):
    return x + y

print (Calc.sum(3,4))

>>> 7

我已经想到我的对象正在调用引用的函数并将其自身作为参数。经过一番研究,我终于找到了解决方案。当我使用 class 变量指向函数时,它不会引用直接指针。它将函数引用为 class 的反弹方法。要摆脱使用 getattr 调用方法的默认调用,必须覆盖 class 本身的 getattr 调用函数(在本例中 class bar,因为 foo(包装器 classes)继承了 bar:

的功能
import inspect

class bar(object):
    GET_STUFF = None

    def __getattribute__(self, name):
        attr = object.__getattribute__(self,name)
        if name == "GET_STUFF":
            # Check: is method and is bounced?
            if inspect.ismethod(attr) and attr.im_self is not None:
                return attr.__func__
        return attr
bar

getattr 现在指向原始函数引用,但仅针对 class 变量 GET_STUFF,因为我想保留默认功能我的其余变量。

所以,当我现在执行以下命令时:

 class foo(bar):
    GET_STUFF = getStuff

    def __init__(self):
        print "inner func: ",self.GET_STUFF
        self.GET_STUFF()

foo()

我得到了预期的结果,并且可以编写我的包装器,而无需使用这些包装器为每个模块生成额外的代码 classes:

outer func:  <function getStuff at 0x00000000034259E8>
inner func:  <function getStuff at 0x00000000034259E8>
I do my stuff!!!