动态地将类方法添加到类中 [英] Dynamically adding class methods to a class

查看:140
本文介绍了动态地将类方法添加到类中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码段:

FEED_TYPES = [
    ('fan_mail',     'Fan Mail'),
    ('review',       'Review'),
    ('tip',          'Tip'),
    ('fan_user',     'Fan User'),
    ('fan_song',     'Fan Song'),
    ('fan_album',    'Fan Album'),
    ('played_song',  'Played Song'),
    ('played_album', 'Played Album'),
    ('played_radio', 'Played Radio'),
    ('new_event',    'New Event'),
]

class Feed:
    @classmethod
    def do_create(cls, **kwargs):
        print kwargs

    @classmethod
    def create(cls, type, **kwargs):
        kwargs['feed_type'] = type
        cls.do_create(**kwargs)

for type_tuple in FEED_TYPES:
    type, name = type_tuple

    def notify(self, **kwargs):
        print "notifying %s" % type
        self.create(type, **kwargs)

    notify.__name__ = "notify_%s" % type
    setattr(Feed, notify.__name__, classmethod(notify))

Feed.create("FanMail", to_profile="Gerson", from_profile="Felipe")
Feed.notify_fan_mail(to_profile="Gerson2", from_profile="Felipe2")

想法是为每种Feed类型动态创建一个类方法(例如 notify_fan_mail ).效果几乎很好,唯一的问题是 print 语句始终打印"notify new_event",无论我调用哪种方法(与 notify_new_mail notify_review ,等等.

The idea is to dynamically create one class method (like notify_fan_mail) for each feed type. It works almost great, the only problem is that the print statement always prints "notifying new_event", regardless of the method I call (same for notify_new_mail, notify_review, etc.).

我意识到这是因为它使用的是分配给type的最后一个值.我的问题是:如何动态创建对 type 类型使用正确值的方法?

I realize it's because it's using the last value assigned to type. My question is: how can I dynamically create methods that would use the correct value for type?

此外,如果我在Python文件中有此确切的代码,这是向Feed类添加方法的正确方法,还是还有一种更优雅的方法?

Also, if I have this exact code in a Python file, is that the correct way to add methods to the Feed class, or is there a more elegant way?

推荐答案

使用闭包保留kind的值:

for type_tuple in FEED_TYPES:
    kind, name = type_tuple
    def make_notify(kind):
        def notify(self, **kwargs):
            print "notifying %s" % kind
            self.create(kind, **kwargs)
        return notify
    notify = make_notify(kind)
    notify.__name__ = "notify_%s" % kind
    setattr(cls, notify.__name__, classmethod(notify))

顺便说一句,不要使用type作为变量名,因为它会掩盖同名的内置变量.

By the way, don't use type as a variable name since it shadows the builtin of the same name.

一种修改Feed的更优雅的方法是创建一个类装饰器.这样可以更清楚地看到您有修改Feed原始定义的代码.

A more elegant way to modify Feed is to create a class decorator. This makes it clearer that you have code modifying the original definition of Feed.

FEED_TYPES = [
    ('fan_mail',     'Fan Mail'),
    ('review',       'Review'),
    ('tip',          'Tip'),
    ('fan_user',     'Fan User'),
    ('fan_song',     'Fan Song'),
    ('fan_album',    'Fan Album'),
    ('played_song',  'Played Song'),
    ('played_album', 'Played Album'),
    ('played_radio', 'Played Radio'),
    ('new_event',    'New Event'),
]

def add_feed_types(cls):
    for type_tuple in FEED_TYPES:
        kind, name = type_tuple
        def make_notify(kind):
            def notify(self, **kwargs):
                print "notifying %s" % kind
                self.create(kind, **kwargs)
            return notify
        notify = make_notify(kind)
        notify.__name__ = "notify_%s" % kind
        setattr(cls, notify.__name__, classmethod(notify))
    return cls

@add_feed_types
class Feed:
    @classmethod
    def do_create(cls, **kwargs):
        print kwargs

    @classmethod
    def create(cls, kind, **kwargs):
        kwargs['feed_type'] = kind
        cls.do_create(**kwargs)


Feed.create("FanMail", to_profile="Gerson", from_profile="Felipe")
Feed.notify_fan_mail(to_profile="Gerson2", from_profile="Felipe2")

这篇关于动态地将类方法添加到类中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆