1

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

1
  • At the time External is actually called, shirt_color and shoes_color are not class variables at all; they are simply local variables in the body of the class statement that will be added to the class's dictionary once the metaclass actually creates Parent. Commented Jan 4, 2017 at 22:01

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

7 Comments

Yes but I redefine the class variables that are called in External, do you have an alternative ?
Redefining the class variables won't do anything... why would it? Python doesn't magically remember how each value was constructed and redo the construction when any of its components change
can't use @property decorator if class isn't instantiated like in here
Well, yes. you need to instantiate the class. That's what classes are for, after all. I thought that would go without saying...
I'm not sure if you are familiar with Django, but the Models can be used to instantiate User(email='[email protected]').save() or User.objects.all() that is my purpose with this code, to replicate this
|
0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.