【问题标题】:Python - appending to class-level lists in derived class definitionsPython - 附加到派生类定义中的类级列表
【发布时间】:2012-04-12 07:25:49
【问题描述】:
class A (object):
    keywords = ('one', 'two', 'three')

class B (A):
    keywords = A.keywords + ('four', 'five', 'six')

有什么方法可以将A.keywords 更改为<thing B derives from>.keywords,有点像super(),但之前是__init__/self?我不喜欢在定义中重复类名。

用法:

>>> A.keywords
('one', 'two', 'three')
>>> B.keywords
('one', 'two', 'three', 'four', 'five', 'six')

【问题讨论】:

    标签: python class-variables


    【解决方案1】:

    其实可以的。编写一个descriptor,检查类的基类中是否存在同名属性,并将传递的属性添加到其值中。

    class parentplus(object):
        def __init__(self, name, current):
            self.name = name
            self.value = current
    
        def __get__(self, instance, owner):
            # Find the attribute in self.name in instance's bases
            # Implementation left as an exercise for the reader
    
    class A(object):
        keywords = ('one', 'two', 'three')
    
    class B(A):
        keywords = parentplus('keywords', ('four', 'five', 'six'))
    

    【讨论】:

    • 有趣。我还没有想过转向更外部的解决方案。
    【解决方案2】:

    使用元类:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    class Meta(type):
        def __new__(cls, name, bases, attrs):
            new_cls = super(Meta,cls).__new__(cls, name, bases, attrs)
            if hasattr(new_cls, 'keywords'):
                new_cls.keywords += ('1','2')
            return new_cls
    
    class B(object):
        keywords = ('0',)
        __metaclass__= Meta
    
    def main():
        print B().keywords
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 虽然这是我看到的唯一不按名称调用任何类的方法,但它似乎与问题不成比例。
    • 是的,agf。这是很好的信息,但我正在寻找一个微小的解决方案,比如 super().keywords + 关键字。谢谢。
    【解决方案3】:

    是的。只要你已经初始化了你的类,就使用 __bases__ attr 来查找基类。否则你需要改变方法,因为 B 不知道它的父母。

    class A (object):
        keywords = ('one', 'two', 'three')
    
    class B (A):
        def __init__(self):
            keywords = self.__bases__[0].keywords + ('four', 'five', 'six')
    

    【讨论】:

    • 问题的关键是如何在类定义时做到这一点。
    • @GaryFixler afg 是正确的,使用 Ignatio 方法,我的根本无法在基础级别工作。
    • 明白。是的,我在课堂上需要这个,实例前。
    【解决方案4】:

    我发现了一种对我有用的解决方法,无需额外的类和定义。

    class BaseModelAdmin(admin.ModelAdmin):
        _readonly_fields = readonly_fields = ('created_by', 'date_add', 'date_upd', 'deleted')
    

    当子类化时

    class PayerInline(BaseTabularInline):
        exclude = BaseTabularInline._exclude + ('details',)
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2013-04-19
      • 2018-02-04
      • 1970-01-01
      • 2010-10-29
      • 2013-09-26
      • 1970-01-01
      • 2012-05-29
      • 1970-01-01
      • 2021-12-10
      相关资源
      最近更新 更多