Python:如果静态类变量获得不同的函数引用指针,如何修复?

时间:2015-03-19 15:13:26

标签: python reference static function-pointers class-variables

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

这是我的示例代码:

# 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 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!!!

可是:

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

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..

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

由于

3 个答案:

答案 0 :(得分:3)

错误的原因是

self.GET_STUFF()

实际上意味着

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

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

def foo(self): pass

class Foo(object):
     a = foo

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

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

实现您的目标:

from API01 import getStuff01

def wrapper01(self):
    getStuff01()

class foo01(object):
    GET_STUFF = wrapper01

答案 1 :(得分:0)

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

class Calc:

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

print (Calc.sum(3,4))

>>> 7

答案 2 :(得分:0)

我认为我的对象是将自己作为参数调用引用的函数。经过一番研究,我终于找到了解决方案。当我使用类变量指向函数时,它不会引用直接指针。它将函数引用为它的类的反弹方法。要删除使用getattr调用方法的默认调用,必须覆盖getattr对类本身的调用函数(在本例中为类bar,因为{{ 1}}(包装类)继承了foo

的功能
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 的{​​{1}}现在指向原始函数引用,但仅针对类变量getattr,因为我想保留其余变量的默认功能。

所以,当我现在执行以下内容时:

bar

我得到了预期的结果,可以编写我的包装器,而不会为每个包含这些包装类的模块生成额外的代码:

GET_STUFF