在Python3.1的类构造过程中,如何找到绑定方法的类?

在Python3.1的类构造过程中,如何找到绑定方法的类?,python,python-3.x,Python,Python 3.x,我想编写一个装饰器,使类的方法对其他方可见;然而,我所描述的问题与细节无关。代码大致如下所示: def CLASS_WHERE_METHOD_IS_DEFINED( method ): ??? def foobar( method ): print( CLASS_WHERE_METHOD_IS_DEFINED( method ) ) class X: @foobar def f( self, x ): return x ** 2 我这里的问题是,当装饰程序foob

我想编写一个装饰器,使类的方法对其他方可见;然而,我所描述的问题与细节无关。代码大致如下所示:

def CLASS_WHERE_METHOD_IS_DEFINED( method ):
  ???

def foobar( method ):
  print( CLASS_WHERE_METHOD_IS_DEFINED( method ) )

class X:

  @foobar
  def f( self, x ):
    return x ** 2
我这里的问题是,当装饰程序
foobar()
看到该方法时,它还不可调用;相反,它会看到它的一个未绑定版本。也许这可以通过在类上使用另一个decorator来解决,这个decorator将负责对绑定方法所做的任何事情。下一步我将尝试做的是,在装饰方法通过装饰器时,简单地用属性标记装饰方法,然后使用类装饰器或元类来进行后处理。如果我能做到这一点,那么我就不必解开这个谜语,这个谜语仍然困扰着我:


在上面的代码中,任何人都可以在
CLASS\u下填写有意义的行,其中定义了\u方法\u
,这样装饰师就可以在定义
f
的那一刻打印出定义了
f
的类了吗?或者这种可能性在python 3中被排除了?

当调用装饰器时,它是以一个函数作为参数而不是一个方法来调用的——因此,装饰器尽可能多地检查和反省它的方法将毫无用处,因为它只是一个函数,并且不携带任何关于封闭类的信息。我希望这能解决你的“谜语”,尽管是消极的


可能会尝试其他方法,例如对嵌套堆栈框架进行深度内省,但它们是粗糙的、脆弱的,肯定不会延续到其他Python 3实现中,例如pynie;因此,我衷心建议您避免使用它们,而使用您已经在考虑的类装饰器解决方案,它更干净、更可靠。

这是一篇非常古老的文章,但内省并不是解决这个问题的方法,因为使用一点巧妙的类构造逻辑可以更轻松地解决这个问题

实现这一点的关键是元类——它搜索在它创建的类上定义的属性,以找到
foobar
描述符。一旦这样做了,它就会通过描述符的
init_self
init_cls
方法向他们传递有关他们所涉及的类的信息

init_self
仅对定义了描述符的类调用。这是应该对
foobar
进行修改的地方,因为该方法只调用一次。而
init_cls
是为所有有权访问修饰方法的类调用的。在这里可以引用对类
foobar
的修改

import inspect

class MetaX(type):

    def __init__(cls, name, bases, classdict):
        # The classdict contains all the attributes
        # defined on **this** class - no attribute in
        # the classdict is inherited from a parent.
        for k, v in classdict.items():
            if isinstance(v, foobar):
                v.init_self(k, cls)

        # getmembers retrieves all attributes
        # including those inherited from parents
        for k, v in inspect.getmembers(cls):
            if isinstance(v, foobar):
                v.init_cls(cls)
例子
#兼容性
进口六
类X(六个,带有_元类(MetaX,object)):
定义初始化(自):
self.value=1
@福巴
def f(自身,x):
返回self.value+x**2
Y(X)级:及格
#印刷品:
#我的名字叫“f”,属于
#我存在于实例的mro中
#我存在于实例的mro中
打印('CLASS-CONSTRUCTION OVER\n')
打印(Y().f(3))
#印刷品:
# 10
正如我在一些文章中提到的,由于Python 3.6,这个问题的解决方案非常简单,因为它可以通过定义的类对象调用

我们可以使用它定义一个装饰器,该装饰器可以通过以下方式访问该类:

class\u装饰器:
定义初始化(self,fn):
self.fn=fn
定义设置名称(自身、所有者、名称):
#与“所有者”(即类)一起做某事
打印(f“装饰{self.fn}并使用{owner}”)
#然后用原来的方法代替我们自己
setattr(所有者、名称、self.fn)
然后可以用作普通装饰器:

>>A类:
...     @高级装饰师
...     def hello(self,x=42):
...         返回x
...
装饰与使用
>>>你好

如果我想把一些参数传递给装饰师怎么办?至少有两种方法可以做到:1。对参数使用
\uuuu init\uuuu
,并定义一个
\uuu调用(self,fn)
方法,该方法设置
self.fn=fn
并返回
self
。2.将整个
class\u decorator
定义包装到另一个函数中,该函数接受您的参数并返回
class\u decorator
import inspect

class MetaX(type):

    def __init__(cls, name, bases, classdict):
        # The classdict contains all the attributes
        # defined on **this** class - no attribute in
        # the classdict is inherited from a parent.
        for k, v in classdict.items():
            if isinstance(v, foobar):
                v.init_self(k, cls)

        # getmembers retrieves all attributes
        # including those inherited from parents
        for k, v in inspect.getmembers(cls):
            if isinstance(v, foobar):
                v.init_cls(cls)
# for compatibility
import six

class X(six.with_metaclass(MetaX, object)):

    def __init__(self):
        self.value = 1

    @foobar
    def f(self, x):
        return self.value + x**2

class Y(X): pass

# PRINTS:
# I am named 'f' and owned by <class '__main__.X'>
# I exist in the mro of <class '__main__.X'> instances

# I exist in the mro of <class '__main__.Y'> instances

print('CLASS CONSTRUCTION OVER\n')

print(Y().f(3))
# PRINTS:
# 10