如何在Python中引用函数体之外的类方法?

2024-05-16 00:41:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在Observer中进行一次回调注册。我不想在init或其他函数中注册。我不知道是否有与init等价的类级别

    class Observer:

        @classmethod
        def on_new_user_registration(new_user):
            #body of handler...

        # first I try

        NewUserRegistered().subscribe \
          (Observer.on_new_user_registration) #gives NameError for Observer

        #so I try

        NewUserRegistered().subscribe(on_new_user_registration) #says not callable

        #neither does this work

        NewUserRegistered().subscribe(__metaclass__.on_new_user_registration)


class BaseEvent(object):
    _subscriptions = {}

    def __init__(self, event_info = None):
        self.info = event_info

    def fire(self):
        for callback in self._subscriptions[event_type]:
            callback(event_info)

    def subscribe(self, callback):
        if not callable(callback):
            raise Exception(str(callback) + 'is not callable')
        existing = self._subscriptions.get(self.__class__, None)
        if not existing:
            existing = set()
            self._subscriptions[self.__class__] = existing
        existing.add(callback)

    class NewUserRegistered(BaseEvent):
        pass

Tags: selfeventnewondefsubscriptionscallbacknot
3条回答

我已经接受了这样一个事实:当涉及到类定义中的函数式编程时,python并不是很直观。见this question。第一个方法的问题是,在类被构建之前,Observer不作为命名空间存在。第二种方法的问题是,您所创建的类方法在名称空间创建之后才真正执行它应该做的事情。(我不知道为什么要尝试第三种方法。)在这两种情况下,这两种情况都不会发生,直到填充了Observer的类定义。在

这听起来像是一个可悲的约束,但其实没那么糟糕。只需在类定义之后注册。一旦您意识到在模块主体中但在类主体之外的类上执行某些初始化例程并不是一种坏的风格,python就会变得更加友好。尝试: 班级观察员:

# Define the other classes first

class Observer:
    @classmethod
    def on_new_user_registration(new_user):
        #body of handler...
NewUserRegistered().subscribe(Observer.on_new_user_registration)

由于模块在python中的工作方式,您可以保证在导入Observer时只执行一次注册(除非进程分叉和其他一些不相关的边界情况)。在

哦。很抱歉。 我所要做的就是将订阅转移到类定义之外

class Observer:

        @classmethod
        def on_new_user_registration(new_user):
            #body of handler...

#after end of class

NewUserRegistered().subscribe(Observer.on_new_user_registration)

我猜这是Java太多的副作用,人们不会马上想到这一点。在

我建议减少类的数量——记住Python不是Java。每次使用@classmethod或{}时,都应该停下来考虑一下,因为这些关键字在Python中非常罕见。在

这样做很有效:

class BaseEvent(object):
    def __init__(self, event_info=None):
        self._subscriptions = set()
        self.info = event_info

    def fire(self, data):
        for callback in self._subscriptions:
            callback(self.info, data)

    def subscribe(self, callback):
        if not callable(callback):
            raise ValueError("%r is not callable" % callback)
        self._subscriptions.add(callback)
        return callback

new_user = BaseEvent()

@new_user.subscribe
def on_new_user_registration(info, username):
    print "new user: %s" % username

new_user.fire("Martin")

如果你想要一个观察者类,那么你可以这样做:

班级观察员:

^{pr2}$

但是请注意,静态方法不能访问协议实例,因此这可能不是很有用。您不能订阅绑定到这样的对象实例的方法,因为在执行类定义时对象将不存在。在

但你当然可以这样做:

class Observer:
    def on_new_user_registration(self, info, username):
        print "new user: %s" % username

o = Observer()
new_user.subscribe(o.on_new_user_registration)

其中我们使用绑定o.on_new_user_registration作为参数来订阅。在

相关问题 更多 >