相关疑难解决方法(0)

装饰Python类方法 - 如何将实例传递给装饰器?

这是Python 2.5,它也是GAE,并不重要.

我有以下代码.我正在使用dec_check类作为装饰器在bar中装饰foo()方法.

class dec_check(object):

  def __init__(self, f):
    self.func = f

  def __call__(self):
    print 'In dec_check.__init__()'
    self.func()

class bar(object):

  @dec_check
  def foo(self):
    print 'In bar.foo()'

b = bar()
b.foo()
Run Code Online (Sandbox Code Playgroud)

执行此操作时,我希望看到:

In dec_check.__init__()
In bar.foo()
Run Code Online (Sandbox Code Playgroud)

但我得到" TypeError: foo() takes exactly 1 argument (0 given)"作为.foo()一种对象方法,以自我为参数.我猜测问题是bar当我执行装饰器代码时,实例并不存在.

那么如何将一个实例传递bar给装饰器类呢?

python python-decorators

59
推荐指数
3
解决办法
3万
查看次数

如何在Python中记忆类实例化?

好吧,这是现实世界的场景:我正在编写一个应用程序,我有一个代表某种类型文件的类(在我的例子中,这是照片,但细节与问题无关).Photos类的每个实例对于照片的文件名应该是唯一的.

问题是,当用户告诉我的应用程序加载文件时,我需要能够识别文件何时已加载,并使用现有实例作为该文件名,而不是在同一文件名上创建重复实例.

对我而言,使用memoization似乎是一个很好的情况,并且有很多例子,但在这种情况下,我不只是记住一个普通的函数,我需要记忆__init__().这造成了一个问题,因为在__init__()被调用的时候已经太晚了,因为已经创建了一个新实例.

在我的研究中,我发现了Python的__new__()方法,我实际上能够编写一个简单的工作示例,但是当我尝试在我的真实世界对象上使用它时它就崩溃了,我不知道为什么(我唯一可以做到的)我想到的是我的真实世界对象是我无法控制的其他对象的子类,因此这种方法存在一些不兼容性.这就是我所拥有的:

class Flub(object):
    instances = {}

    def __new__(cls, flubid):
        try:
            self = Flub.instances[flubid]
        except KeyError:
            self = Flub.instances[flubid] = super(Flub, cls).__new__(cls)
            print 'making a new one!'
            self.flubid = flubid
        print id(self)
        return self

    @staticmethod
    def destroy_all():
        for flub in Flub.instances.values():
            print 'killing', flub


a = Flub('foo')
b = Flub('foo')
c = Flub('bar')

print a
print b
print c
print a is b, b is c

Flub.destroy_all()
Run Code Online (Sandbox Code Playgroud)

哪个输出:

making a new one! …
Run Code Online (Sandbox Code Playgroud)

python singleton caching unique memoization

21
推荐指数
2
解决办法
8052
查看次数

实例方法的装饰器

将类的方法包装在“样板”Python 装饰器中会将该方法视为常规函数,并使其失去__self__引用类实例对象的属性。这可以避免吗?

参加以下课程:

class MyClass(object):
    def __init__(self, a=1, b=2):
        self.a = a
        self.b = b
    def meth(self):
        pass
Run Code Online (Sandbox Code Playgroud)

如果meth()未修饰,MyClass().meth.__self__则引用实例方法并启用类似setattr(my_class_object.meth.__self__, 'a', 5).

但是当将任何东西包装在装饰器中时,只传递函数对象;它实际绑定的对象不会随之传递。(请参阅答案。)

import functools

def decorate(method):
    @functools.wraps(method)
    def wrapper(*args, **kwargs):
        # Do something to method.__self__ such as setattr
        print(hasattr(method, '__self__'))
        result = method(*args, **kwargs)
        return result
    return wrapper

class MyClass(object):
    def __init__(self, a=1, b=2):
        self.a = a
        self.b = b
    @decorate
    def meth(self):
        pass

MyClass().meth()
# False            <--------
Run Code Online (Sandbox Code Playgroud)

这可以被覆盖吗?

python python-3.x python-decorators

6
推荐指数
2
解决办法
3309
查看次数

使用类作为方法装饰器

虽然有很多关于使用类作为装饰器的资源,但我还没有找到任何处理装饰方法问题的资源。这个问题的目标是解决这个问题。我将发布我自己的解决方案,但当然也邀请其他所有人发布他们的解决方案。


为什么“标准”实现不起作用

标准装饰器类实现的问题在于,python 不会创建被装饰函数的绑定方法:

class Deco:
    def __init__(self, func):
        self.func= func
    
    def __call__(self, *args):
        self.func(*args)

class Class:
    @Deco
    def hello(self):
        print('hello world')

Class().hello() # throws TypeError: hello() missing 1 required positional argument: 'self'
Run Code Online (Sandbox Code Playgroud)

方法装饰器需要克服这个障碍。


要求

从前面的示例中获取类,预计以下事情会起作用:

>>> i= Class()
>>> i.hello()
hello world
>>> i.hello
<__main__.Deco object at 0x7f4ae8b518d0>
>>> Class.hello is Class().hello
False
>>> Class().hello is Class().hello
False
>>> i.hello is i.hello
True
Run Code Online (Sandbox Code Playgroud)

理想情况下,函数__doc__和签名以及类似的属性也被保留。

python class decorator python-decorators

3
推荐指数
1
解决办法
1811
查看次数