Rug*_*rra 6 python class decorator descriptor
我有一个装饰功能(简化版):
class Memoize:
def __init__(self, function):
self.function = function
self.memoized = {}
def __call__(self, *args, **kwds):
hash = args
try:
return self.memoized[hash]
except KeyError:
self.memoized[hash] = self.function(*args)
return self.memoized[hash]
@Memoize
def _DrawPlot(self, options):
do something...
Run Code Online (Sandbox Code Playgroud)
现在我想将此方法添加到预先存在的类中.
ROOT.TChain.DrawPlot = _DrawPlot
Run Code Online (Sandbox Code Playgroud)
当我称这种方法时:
chain = TChain()
chain.DrawPlot(opts)
Run Code Online (Sandbox Code Playgroud)
我有:
self.memoized[hash] = self.function(*args)
TypeError: _DrawPlot() takes exactly 2 arguments (1 given)
Run Code Online (Sandbox Code Playgroud)
为什么不传播自我?
问题是您已经定义了自己的可调用类,然后尝试将其用作方法。当您使用函数作为属性时,将函数作为属性访问时会调用它的__get__方法来返回除函数本身之外的其他内容\xe2\x80\x94绑定方法。当您拥有自己的类而没有定义时__get__,它只是返回您的实例而不隐式传递self。
如果您不熟悉描述符,请在http://docs.python.org/reference/datamodel.html#descriptors上进行一些解释。、和方法改变了作为属性与对象交互的方式__get__。__set____delete__
您可以将其实现为函数并使用函数已有的memoize内置魔法__get__
import functools\n\ndef memoize(f):\n @functools.wraps(f)\n def memoized(*args, _cache={}): \n # This abuses the normally-unwanted behaviour of mutable default arguments.\n if args not in _cache:\n _cache[args] = f(*args)\n return _cache[args]\n return memoized\nRun Code Online (Sandbox Code Playgroud)\n\n或者按照以下方式修改你的课程
\n\nimport functools\n\nclass Memoize(object): #inherit object\n def __init__(self, function):\n self.function = function\n self.memoized = {}\n def __call__(self, *args): #don\'t accept kwargs you don\'t want.\n # I removed "hash = args" because it shadowed a builtin function and \n # because it was untrue--it wasn\'t a hash, it was something you intended for\n # Python to hash for you.\n try:\n return self.memoized[args]\n except KeyError:\n self.memoized[args] = self.function(*args)\n return self.memoized[args]\n def __get__(self, obj, type):\n if obj is None: #We looked up on the class\n return self\n\n return functools.partial(self, obj)\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,如果您传入的任何参数是可变的(嗯,从技术上讲是不可散列的),这两个都会阻塞。这可能适合您的情况,但您可能还想处理args不可散列的情况。