确定方法的类

时间:2013-04-09 23:57:21

标签: python

让我说我有:

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

3 个答案:

答案 0 :(得分:2)

使用u.method.im_class

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

Documentation

  

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

在python 3中,通过__self__

查找课程
>>> u.method.__self__.__class__
<class '__main__.User'>

答案 1 :(得分:2)

你的装饰者没有用方法调用,而是用函数调用它。

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

所以,你不能自省你试图获得它的类,因为它没有。


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

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

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

答案 2 :(得分: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'>

两种方法都确认在python 2.7.3和python 3.3

中工作