创建可以看到当前类方法的装饰器

发布于 2024-09-19 17:50:28 字数 707 浏览 4 评论 0原文

您可以在类中创建一个可以看到类方法和变量的装饰器吗?

这里的装饰器没有看到: self.longcondition()

class Foo:
    def __init__(self, name):
        self.name = name

    # decorator that will see the self.longcondition ???
    class canRun(object):
            def __init__(self, f):
                self.f = f

            def __call__(self, *args):
                if self.longcondition(): # <-------- ???
                    self.f(*args)

    # this is supposed to be a very long condition :)
    def longcondition(self):
        return isinstance(self.name, str)

    @canRun # <------
    def run(self, times):
        for i in xrange(times):
            print "%s. run... %s" % (i, self.name)

Can you create a decorator inside a class that will see the classes methods and variables?

The decorator here doesnt see: self.longcondition()

class Foo:
    def __init__(self, name):
        self.name = name

    # decorator that will see the self.longcondition ???
    class canRun(object):
            def __init__(self, f):
                self.f = f

            def __call__(self, *args):
                if self.longcondition(): # <-------- ???
                    self.f(*args)

    # this is supposed to be a very long condition :)
    def longcondition(self):
        return isinstance(self.name, str)

    @canRun # <------
    def run(self, times):
        for i in xrange(times):
            print "%s. run... %s" % (i, self.name)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

掩饰不了的爱 2024-09-26 17:50:28

没有真正需要将此装饰器实现为类,也无需在 Foo 类的定义中实现它。以下内容就足够了:

def canRun(meth):
    def decorated_meth(self, *args, **kwargs):
        if self.longcondition():
            print 'Can run'
            return meth(self, *args, **kwargs)
        else:
            print 'Cannot run'
            return None
    return decorated_meth

使用该装饰器似乎可行:

>>> Foo('hello').run(5)
Can run
0. run... hello
1. run... hello
2. run... hello
3. run... hello
4. run... hello
>>> Foo(123).run(5)
Cannot run

There's no real need to implement this decorator as a class, and there's no need to implement it inside the definition of the Foo class. The following will suffice:

def canRun(meth):
    def decorated_meth(self, *args, **kwargs):
        if self.longcondition():
            print 'Can run'
            return meth(self, *args, **kwargs)
        else:
            print 'Cannot run'
            return None
    return decorated_meth

Using that decorator seems to work:

>>> Foo('hello').run(5)
Can run
0. run... hello
1. run... hello
2. run... hello
3. run... hello
4. run... hello
>>> Foo(123).run(5)
Cannot run
情绪失控 2024-09-26 17:50:28

您可以将其作为一个类,但需要使用描述符协议

 import types

 class canRun(object):
    def __init__(self, f):
        self.f = f
        self.o = object  # <-- What the hell is this about? 

    def __call__(self, *args):
        if self.longcondition():
            self.f(*args)

    def __get__(self, instance, owner):
         return types.MethodType(self, instance)

当您想要使用 __call__ 方法用类实例装饰类方法时,始终需要使用描述符。这样做的原因是,只会传入一个 self ,它引用装饰类的实例,而不是被装饰方法的实例。

You can have it be a class but you need to use the descriptor protocol

 import types

 class canRun(object):
    def __init__(self, f):
        self.f = f
        self.o = object  # <-- What the hell is this about? 

    def __call__(self, *args):
        if self.longcondition():
            self.f(*args)

    def __get__(self, instance, owner):
         return types.MethodType(self, instance)

You always need to use a descriptor when you want to decorate class methods with a class instance using the __call__ method. The reason for this is that there will only be one self passed in which refers to the instance of the decorating class and not the instance of the decorated method.

迷路的信 2024-09-26 17:50:28

我之前的回答是仓促的。如果您想编写一个装饰器,那么您应该使用 functools 模块中的 wraps 。它会为您处理困难的事情。

定义 canRun 装饰器的正确方法是:

from functools import wraps
def canRun(f):
  @wraps(f)
  def wrapper(instance, *args):
    if instance.longcondition():
      return f(instance, *args)
  return wrapper

canRun 函数应该在类外部定义。

My previous answer was made in haste. If you're wanting to write a decorator you should really use wraps from the functools module. It takes care of the hard stuff for you.

A proper way to define the canRun decorator is:

from functools import wraps
def canRun(f):
  @wraps(f)
  def wrapper(instance, *args):
    if instance.longcondition():
      return f(instance, *args)
  return wrapper

The canRun function should be defined outside of the class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文