Gary Fixler
Gary Fixler

Reputation: 6028

Python - appending to class-level lists in derived class definitions

class A (object):
    keywords = ('one', 'two', 'three')

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

Is there any way to change A.keywords to <thing B derives from>.keywords, sort of like super(), but pre-__init__/self? I don't like repeating class names in definitions.

Usage:

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

Upvotes: 2

Views: 602

Answers (4)

Konstantin P.
Konstantin P.

Reputation: 1

I found a workaround-style solution working for me without additional classes and defs.

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

and when subclassing

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

Hope this helps.

Upvotes: 0

luke14free
luke14free

Reputation: 2539

Yes. Use the __bases__ attr to find the base class(es) whenever you've already init'ed your class. Otherwise you need to change approach as B is not aware of its parents.

class A (object):
    keywords = ('one', 'two', 'three')

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

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798606

Actually, you can. Write a descriptor that checks the class's bases for an attribute with the same name and add the passed attributes to its value.

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'))

Upvotes: 5

WooParadog
WooParadog

Reputation: 649

Use metaclass :

#!/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()

Upvotes: 1

Related Questions