1



I'm struggling to solve with this problem.

I'd like to have the name variable to be like a pointer to the value of self.model.name. If the value of _class.model.name is changed the _class.name should change accordingly.

Can't find a way to basically map dynamically the Class attributes with any Model attributes without inheriting.

class Model(object):

    name = 'foo'
    parent = 'foo_p'

class Class(object):

    model_class = Model

    def __init__(self):

        self.model = self.model_class() 

        setattr(self, 'name', self.model.name)

_class = Class()
print _class.model.name # foo

_class.model.name = 'foo_1'        
print _class.name # this should be foo_1

Thanks!

2 Answers2

1

Use a property to create a single dynamically computed attributes:

class Class(object):
    _model_class = Model

    @property
    def name(self):
        return Class._model_class.name

This causes all instances of Class to run the name method whenever the attribute name is looked up. This allows the value to be dynamically computed on each lookup.

_class = Class()
print(_class.name)  # 'foo'
Model.name = 'bar'
print(_class.name)  # 'bar'

If you want to dynamically fetch many or all attributes from somewhere else, consider using __getattr__:

class Class(object):
    _model_class = Model

    def __getattr__(self, name):
        # name is a *string* containing the name of the attribute to fetch
        return getattr(Class._model_class, name)

The __getattr__ is only triggered for attributes that are not on the class/instance. This makes it rather straightforward to use with manually defined attributes. Note that you can use arbitrary code to restrict what is fetched - e.g. raise AttributeError if name is not in some whitelist.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119
  • How can I create dynamically properties based on the Model attributes? – Adriano Muraca Oct 19 '18 at 16:23
  • @AdrianoMuraca The example code already shows a dynamic property using the ``Model`` attributes. Please clarify what you need. – MisterMiyagi Oct 20 '18 at 10:43
  • Thank you for your time @MisterMiyagi! :) this is what I meant for dynamically, don't know if it makes sense. Inside the __init__ function of the Class, I was thinking to add something like `for attribute in any_attribute_found_in_Model: set property in this class` In this way I wouldn't need to write manually the property any time a new attribute is added to the Model class. – Adriano Muraca Oct 22 '18 at 09:40
  • @AdrianoMuraca I have added a different approach that is suitable for generically fetching attributes based on rules. – MisterMiyagi Oct 22 '18 at 11:55
  • 1
    It was exactly what I was looking for. Thanks again. – Adriano Muraca Oct 22 '18 at 13:33
1

Along with MisterMiyagi's answer - but in case you want to still want to keep the concerns separated (even though it really doesn't seem like you do)

class Class(object):
    model_class = Model

    def __init__(self):
        self.model = self.model_class() 
        setattr(self, 'name', self.model.name)

    # This is what we'll be changing
    @property
    def model_name(self):
        return self.model.name

    # This method will get called whenever we change the model_name
    @model_name.setter
    def model_name(self, new_name):
        self.model.name = new_name
        self.name = new_name

_class = Class()
_class.model_name # foo

_class.model_name = "bar" # both _class.model.name == bar and _class.name == bar now
Wiggy A.
  • 496
  • 3
  • 16