Python重写内部Meta类属性

2 投票
1 回答
1309 浏览
提问于 2025-04-20 17:43

免责声明:这和django没有关系。我之所以标记为Django,是因为Django的对象结构很相似,可能有一些知识是可以互相借鉴的。

我正在使用cement这个命令行框架,想要修改使用说明。其实这更多是关于Python继承的问题,而不是cement的问题。下面是我现在的代码示例:

class AbstractBaseController(controller.CementBaseController):
    class Meta:
        label = 'base'
        usage = 'foo ' + label + ' [options. .]'

class BarController(AbstractBaseController):
    class Meta:
        label = 'bar'

接下来,我来解释一下这里发生了什么。我有多个控制器(不仅仅是bar控制器),我希望它们都能从AbstractBaseController.Meta中继承使用说明属性。不过,我希望使用说明能用新的标签,而不是抽象标签。我的主要目标是让每个控制器都能使用这个说明,而不需要在每个控制器里复制粘贴一遍。现在,使用说明继承的是'foo base [options...]',因为在替换之前没有更新标签。

我尝试了以下方法:

class AbstractBaseController(controller.CementBaseController):
    class Meta:
        label = 'base'
        usage = 'foo {cmd} [options. .]'

class BarController(AbstractBaseController):
    class Meta:
        label = 'bar'
        usage = AbstractBaseController.Meta.usage.replace('{cmd}', label)

这个方法是有效的。但是,我仍然面临复制粘贴的问题,因为我必须把这个使用命令复制到每个控制器里。

我还尝试了这个:

class AbstractBaseController(controller.CementBaseController):
    class Meta:
        label = 'base'
        usage = 'foo {cmd} [options. .]'
        def __init__(self):
            self.usage = 'foo ' + self.label + ' [options]'

class BarController(AbstractBaseController):
    class Meta(AbstractBaseController.Meta):
        label = 'bar'

但这个似乎没有任何效果。即使使用__init__,我仍然得到usage = 'foo {cmd}',而不是usage = 'foo base'

有没有办法让每个控制器的使用说明都能独特地使用各自的标签,同时代码只放在一个地方?(也就是抽象控制器)

1 个回答

0

为什么不使用一个方法呢?

class A : 
    class SubA:
        label = 'base'
        def __init__(self) :
            self.usage = 'foo '+self.label+' [options]'
class B() :
    class SubB(A.SubA) :
        label = 'bar'

a = A().SubA()
b = B().SubB()
print(a.usage) # "foo base [options]"
print(b.usage) # "foo bar [options]"

撰写回答