Skip to content Skip to sidebar Skip to footer

How To Get Attributes Of Parent Class Object Only

I have 2 classes: class Parent(object): def __init__(self, id, name): self.id = id self.name = name self.__parent_vars = ['id', 'name'] # make a copy

Solution 1:

I am afraid you cannot easily. In Python, classes only carry methods and static attributes. Non static attributes are commonly stored in the __dict__ attribute of the objects. That means that except in special cases, you cannot easily know which attributes where assigned in a parent class method, in a child class method or even outside any method.

I can only imagine a meta_class that would instrument the __init__ method to store which attributes were changed during its call:

import collections
import functools
import inspect

classMeta_attr(type):
    init_func = {}
    attrs = collections.defaultdict(set)

    def__new__(cls, name, bases, namespace, **kwds):
        c = type.__new__(cls, name, bases, namespace, **kwds)
        cls.init_func[c] = c.__init__
        @functools.wraps(c.__init__)definit(self, *args, **kwargs):
            before = set(self.__dict__.keys())
            cls.init_func[c](self, *args, **kwargs)
            after = set(self.__dict__.keys())
            cls.attrs[c].update(after.difference(before))
        init.__signature__ = inspect.signature(c.__init__)
        c.__init__ = init
        return c

classParent(object, metaclass=Meta_attr):
    def__init__(self, id, name):
        self.id = id
        self.name = name

    defprint_values(self):
        res = {}
        for el in Meta_attr.attrs[Parent]:
            res[el] = vars(self)[el]
        return res


classChild(Parent):
    def__init__(self, id, name, last_name, age):
        Parent.__init__(self, id, name)
        self.last_name = last_name
        self.age = age

It gives:

>>> c = Child(1,"a","b", 20)
>>> c.print_values()
{'id': 1, 'name': 'a'}

BEWARE: if an attribute is set outside of the __init__ method, it will not be registered by this meta class...

Solution 2:

I found one more solution. It looks simplier, so I used it. It based on using Marshmallow Schemas. Also It is more usiful in my project because I already used marshmallow Schemas. The idea: I create 2 classes and 2 different Schemas. And can serialize bigger class (Child) using just Parent schema:

Code

Define 2 classes:

classParent(object):
    def__init__(self):
        self.id = 'ID'
        self.name = 'some_name'classChild(Parent):
    def__init__(self):
        Parent.__init__(self)
        self.last_name = 'last_name'
        self.age = 15from marshmallow import Schema, fields, EXCLUDE

Define 2 Schemas:

class ParentSchema(Schema):
    ba = Parent()
    id = fields.Str(missing=ba.id)
    name = fields.Str(missing=ba.name)

class ChildSchema(Schema):
    ba = Child()
    id = fields.Str(missing=ba.id)
    name = fields.Str(missing=ba.name)

    last_name = fields.Str(missing=ba.last_name)
    age = fields.Int(missing=ba.age)

use it to get only Parent attributes for Child object:

user_data = {'id':'IDIDID', 'name':'add_name', 'last_name':'FAMILIYA'}
res = ParentSchema().load(user_data, unknown=EXCLUDE)

# output:
res
{'name': 'add_name', 'id': 'IDIDID'}

Post a Comment for "How To Get Attributes Of Parent Class Object Only"