如何在Python中动态添加类方法

2024-10-01 15:41:37 发布

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

我用的是python3。 我知道@classmethod装饰器。另外,我知道类方法可以从实例中调用。在

class HappyClass(object):
    @classmethod
    def say_hello():
        print('hello')
HappyClass.say_hello() # hello
HappyClass().say_hello() # hello

然而,我似乎不能动态地创建类方法并让它们从实例中被调用。假设我想要

^{pr2}$

我使用过cls.__dict__(这会产生异常),以及{}(这只会使thingie从类而不是实例中调用)。在

如果你问我为什么,我想做一个懒惰的类属性。但它不能从实例中调用。在

@classmethod
def search_url(cls):
    if  hasattr(cls, '_search_url'):
        setattr(cls, '_search_url', reverse('%s-search' % cls._meta.model_name))
    return cls._search_url

可能是因为还没从班上叫到物业。。。在

总之,我想添加一个lazy方法,该方法可以从实例中调用。。。这能以一种优雅的方式实现吗?在

有什么想法吗?在

我是如何实现的

抱歉,我的例子很糟糕:\

不管怎样,最后我还是这样做了。。。在

@classmethod
def search_url(cls):
    if not hasattr(cls, '_search_url'):
        setattr(cls, '_search_url', reverse('%s-search' % cls._meta.model_name))
    return cls._search_url

而且setattr确实有效,但是我在测试它时犯了一个错误。。。在


Tags: 实例方法urlhellosearchifdefmeta
3条回答

您可以随时向类添加函数,这种做法称为monkey patching:

class SadClass:
    pass

@classmethod
def say_dynamic(cls):
    print('hello')
SadClass.say_dynamic = say_dynamic

>>> SadClass.say_dynamic()
hello
>>> SadClass().say_dynamic()
hello

注意,您使用的是classmethod修饰符,但是您的函数不接受任何参数,这表明它被设计成一个静态方法。你是不是想用staticmethod代替?在

如果要创建类方法,请不要在__init__函数中创建它们,因为每次创建实例都会重新创建它。但是,以下工作:

class SadClass(object):
    pass

def say_dynamic(cls):
    print("dynamic")

SadClass.say_dynamic = classmethod(say_dynamic)
# or 
setattr(SadClass, 'say_dynamic', classmethod(say_dynamic))

SadClass.say_dynamic() # prints "dynamic!"
SadClass().say_dynamic() # prints "dynamic!"

当然,在__init__方法中,self参数是一个实例,而不是类:要将方法放在类中,可以使用如下方法

^{pr2}$

但它将再次为每个实例创建重置方法,这可能是不必要的。请注意,您的代码很可能失败,因为您在创建任何实例之前调用SadClass.say_dynamic(),因此在注入类方法之前。在

另外,请注意,classmethod获取隐式类参数cls;如果您确实希望在没有任何参数的情况下调用函数,请使用staticmethod修饰符。在

另外,您可以使用实例属性来保存函数:

>>> class Test:
...    pass
... 
>>> t=Test()
>>> t.monkey_patch=lambda s: print(s)
>>> t.monkey_patch('Hello from the monkey patch')
Hello from the monkey patch

相关问题 更多 >

    热门问题