python父类方法的装饰器,Python-装饰器-尝试访问方法的父类

This doesn't work:

def register_method(name=None):

def decorator(method):

# The next line assumes the decorated method is bound (which of course it isn't at this point)

cls = method.im_class

cls.my_attr = 'FOO BAR'

def wrapper(*args, **kwargs):

method(*args, **kwargs)

return wrapper

return decorator

Decorators are like the movie Inception; the more levels in you go, the more confusing they are. I'm trying to access the class that defines a method (at definition time) so that I can set an attribute (or alter an attribute) of the class.

Version 2 also doesn't work:

def register_method(name=None):

def decorator(method):

# The next line assumes the decorated method is bound (of course it isn't bound at this point).

cls = method.__class__ # I don't really understand this.

cls.my_attr = 'FOO BAR'

def wrapper(*args, **kwargs):

method(*args, **kwargs)

return wrapper

return decorator

The point of putting my broken code above when I already know why it's broken is that it conveys what I'm trying to do.

解决方案

I don't think you can do what you want to do with a decorator (quick edit: with a decorator of the method, anyway). The decorator gets called when the method gets constructed, which is before the class is constructed. The reason your code isn't working is because the class doesn't exist when the decorator is called.

jldupont's comment is the way to go: if you want to set an attribute of the class, you should either decorate the class or use a metaclass.

EDIT: okay, having seen your comment, I can think of a two-part solution that might work for you. Use a decorator of the method to set an attribute of the method, and then use a metaclass to search for methods with that attribute and set the appropriate attribute of the class:

def TaggingDecorator(method):

"Decorate the method with an attribute to let the metaclass know it's there."

method.my_attr = 'FOO BAR'

return method # No need for a wrapper, we haven't changed

# what method actually does; your mileage may vary

class TaggingMetaclass(type):

"Metaclass to check for tags from TaggingDecorator and add them to the class."

def __new__(cls, name, bases, dct):

# Check for tagged members

has_tag = False

for member in dct.itervalues():

if hasattr(member, 'my_attr'):

has_tag = True

break

if has_tag:

# Set the class attribute

dct['my_attr'] = 'FOO BAR'

# Now let 'type' actually allocate the class object and go on with life

return type.__new__(cls, name, bases, dct)

That's it. Use as follows:

class Foo(object):

__metaclass__ = TaggingMetaclass

pass

class Baz(Foo):

"It's enough for a base class to have the right metaclass"

@TaggingDecorator

def Bar(self):

pass

>> Baz.my_attr

'FOO BAR'

Honestly, though? Use the supported_methods = [...] approach. Metaclasses are cool, but people who have to maintain your code after you will probably hate you.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值