André Almeida
André Almeida

Reputation: 53

Define class variable with instance of another class

I'm have the following class set:

class External(object):

    def __init__(self, first, second):
        self.first = first
        self.second = second

    def foo():
        print('something')

class Parent(object):

    shirt_color = ''
    shoes_color = ''
    external_class = External(shirt_color, shoes_color)

class SouthParent(Parent):

    shirt_color = 'white'
    shoes_color = 'blue'

Because SouthParent is a children of Parent and the class variables shirt_color and shoes_color are redefined in the SouthParent class, the expected args that External() would receive should be ('white', 'blue') but the instead it receives ('','')

This is defined this way, to be used in the terminal like SouthParent.external_class.foo() like Django Model ( User.objects.all() )

Upvotes: 1

Views: 2071

Answers (2)

André Almeida
André Almeida

Reputation: 53

Possible Solution: (with help of @kindall)

Use Python metaclass

class External(object):
    def __init__(self, first, second):
        self.first = first
        self.second = second

    def foo():
        print('something')

class ParentMeta(type):
    def __new__(cls, name, bases, attrs):

        if attrs['shirt_color'] and attrs['shoes_color']:
            attrs['external_class'] = External(attrs['odoo_model'],attrs['cache_name'])

        return super(ParentMeta, cls).__new__(cls, name, bases, attrs)

class Parent(metaclass=ParentMeta):

    shirt_color = ''
    shoes_color = ''         

class SouthParent(Parent):

    shirt_color = 'white'
    shoes_color = 'blue'


SouthParent.external_class.foo()
# something

Upvotes: 0

kindall
kindall

Reputation: 184201

You never define external_class on SouthParent, so accessing that attribute uses the external_class from Parent, where it was defined as External('', '').

If you want to have it construct external_class based on the class attributes, you can use a property:

class Parent(object):

    shirt_color = ''
    shoes_color = ''

    @property
    def external_class(self):
        return External(self.shirt_color, self.shoes_color)

If it should be the same External instance each time, do it this way:

class Parent(object):

    shirt_color = ''
    shoes_color = ''

    _external_class = None

    @property
    def external_class(self):
        if self._external_class is None:
            self._external_class = External(self.shirt_color, self.shoes_color)
        return self._external_class

Upvotes: 1

Related Questions