1

假设我有:

class User():
  def method(self):
    pass

u=User()

如何u.method通过access装饰器提取类?我得到的u.method只是它是一个函数......但我想知道从哪个class.

我对 python 2.7 解决方案感兴趣。

更新:我忘了提到我没有提供足够的细节:

class access():
    """
    Decorator for specifying which 'access right' must be enforced 
    at the object method level  
    """

    def __init__(self, right):
        self.right=right

    def __call__(self, method):
      ### need to grab the method's class name here

我实际上正在使用装饰器:

class User():
  @access("edit"
  def method(self):
    pass
4

3 回答 3

2

使用u.method.im_class

In [3]: u.method.im_class
Out[3]: __main__.User

文档

用户自定义方法 ... 特殊只读属性:im_self是类实例对象,im_func是函数对象;im_class是绑定方法的 im_self 类或请求未绑定方法的方法的类。

在 python 3 中,通过以下方式查找类__self__

>>> u.method.__self__.__class__
<class '__main__.User'>
于 2013-04-09T23:58:11.423 回答
2

您的装饰器不是用方法调用的,而是用函数调用的。

该类还不存在,将函数绑定到类的未绑定方法也不存在,更不用说类的任何实例以及将函数绑定到该实例的绑定方法。而且,即使这些方法确实存在,它们也会围绕装饰器返回的函数构建。

所以,你不能反省你收到的函数来尝试获取它的类,因为它没有一个。


您可以使用各种 hacky 技巧来确定您正在定义的内容(尽管它们可能特定于特定的 Python 实现和版本),但是没有干净的方法来做您想做的事情。例如,这是一个可怕的 hack:

self.classname = sys._getframe(1).f_code.co_name

这是什么意思?好吧,你的装饰器本身是第 0 帧;无论调用它是第 1 帧。如果调用它的事物是类定义,则其code对象将以类的名称作为其类。您仍然无法实际访问该类,因为它不存在(并且在执行代码之前不会存在,这正在发生中)。但是,如果您知道该名称永远不会被覆盖,您可以只存储该名称并稍后f_locals['__module__']在调用时查找它(您也可能想要查找它)以获取类。


然而,一个更好的解决方案是创建一个类装饰器和一个与之一起工作的方法装饰器。诀窍是方法装饰器以他们想要的某种方式“注册”(它们返回的函数)被“修复”。然后,类装饰器遍历注册的方法并修复它们。

例如:

def class_deco(cls):
    for name, method in inspect.getmembers(cls, callable):
        if hasattr(method, 'class_fixup'):
            method.class_fixup(cls)
    return cls

现在,您的方法装饰器在调用时仍然无法访问该类,但它可以创建一个“修复”函数,该函数在类准备好时完成装饰,然后就f.class_fixup = fixup在之前做return f

于 2013-04-10T00:20:47.307 回答
0

为什么不直接打印呢?

class User():
  def method(self):
    pass

u=User()

print(u.method)

输出:

<bound method User.method of <__main__.User object at 0x02D59510>>

或者,如果您想测试,您可以使用:

u.method.__self__.__class__

输出:

<class '__main__.User'>

两种方法都确认在 python2.7.3和 python中工作3.3

于 2013-04-10T00:05:06.143 回答