object-oriented – Python data model and inheritance design

I'm implementing a data model in python and would appreciate any comments.

My data structure can be reduced to the following:

        {
& # 39; the source & # 39 ;: {
& # 39; name: none,
& # 39; website & # 39 ;: no
}
& # 39; & # 39 ;: car
        [{
            'manufacturer':None,
            'model':None,
            'year':None,
            'horse_power':None,
            'top_speed':None,
            'unit_top_speed':'km/h',
            'zero_to_100':None,
            'unit_zero_to_100':'seconds'
        }]
    }

For my implementation, I created four classes:

  • relative: A class that contains methods used by all other classes.
  • Car and Source (child of relative): Two intermediate classes modeling the fields car; source.
  • Child (child of Car and Source): The end class for my model.
import warnings
# ------------------------------------------------- ---- -----------------------------
Parental class
# ------------------------------------------------- ---- -----------------------------
Parent class (object):
"" "
* Parental class *

Contains the methods used by all other classes.
"" "
def check_validity (auto, key, subset = none, warn = true):
"" "
Check if the key is a self.data field.
"" "
if subset is None:
if key in self.data.keys ():
returns True
other:
if to warn:
warnings.warn (Not allowed:  n  "{} " is not a given instance field. "(key) format, UserWarning)
returns False
other:
if key in self.data[subset].clés ():
returns True
other:
if to warn:
warnings.warn (Not allowed:  n  "{} " is not a given instance field. "(key) format, UserWarning)
returns False
# ------------------------------------------------- ---- -----------------------------
Number of subclasses
# ------------------------------------------------- ---- -----------------------------
car class (parent):
__template = {
"Manufacturer": none,
& # 39; pattern & # 39 ;: no,
& # 39; year & # 39 ;: no
& # 39; horse_power & # 39 ;: none,
& # 39; top_speed & # 39 ;: none,
& # 39; unit_top_speed: km / h,
& # 39; zero_to_100 & # 39 ;: none,
& # 39; unit_zero_to_100 & # 39; seconds & # 39; seconds & # 39;
}
def __init __ (self, ** kwargs):
self.data = Car .__ template.copy ()
for (k, v) in zip (kwargs.keys (), kwargs.values ​​()):
if self.check_validity (k):
self.data[k] = v
Source class (parent):
__template = {
& # 39; name: none,
& # 39; website & # 39 ;: no
}
def __init __ (self, ** kwargs):
self.data = Source .__ template.copy ()
for (k, v) in zip (kwargs.keys (), kwargs.values ​​()):
if self.check_validity (k):
self.data[k] = v
def set_website (self, website):
if not isinstance (website, str):
raise Exception ('The argument must be a string. & # 39;)
if self .__ class__ is & # 39; Source & # 39 ;:
if not self.check_validity (key = "website", warn = true):
return
self.data['website'] = website
return
other:
otherwise self.check_validity (key = "Web site", subset = "source", warned = false):
return
self.data['source']['website']    = website
return
# ------------------------------------------------- ---- -----------------------------
# Child class
# ------------------------------------------------- ---- -----------------------------
Child class (Car, Source):
__template = {
& # 39; the source & # 39 ;: {
& # 39; name: none,
& # 39; website & # 39 ;: no
}
& # 39; & # 39 ;: car
        [{
            'manufacturer':None,
            'model':None,
            'year':None,
            'horse_power':None,
            'top_speed':None,
            'unit_top_speed':'km/h',
            'zero_to_100':None,
            'unit_zero_to_100':'seconds'
        }]
    }
def __init __ (self, ** kwargs):
self.data = Child .__ template.copy ()
for (k, v) in zip (kwargs.keys (), kwargs.values ​​()):
if self.check_validity (k):
self.data[k] = v
def add_car (auto, car):
if not isinstance (car, car):
raise Exception ('The argument must be of class Car. & # 39;)
self.data['car'].to expand([car.data])
def set_car (auto, car):
if not isinstance (car, car):
raise Exception ('The argument must be of class Car. & # 39;)
self.data['car'] = ([car.data])
def set_source (self, source):
if not isinstance (source, source):
raise Exception ("The argument must be from the Source class.")
self.data['source'] = source.data
  • the __init__ all methods use ** kwargs and a loop to lazily move fields and values ​​when creating an instance, eg.

    • Car (model = "M4", year = 2015) or
    • Car (model = M4, top_speed = 250).
  • The goal of check_validity if double:

    1. It checks when defining an instance that all fields are valid, for example. if we write Car (name = "M4", top_speed = 250), then argument first name is omitted (a warning is issued) because it is not a field of Car model .__.

    2. It is also used to treat inheritance: the class Source has a set_website method. By inheritance, this method is transmitted to Child. However, a trivial set_website method that only overwriting would throw an error when used for Child case like Child model .__ no field website, or even worse than an error, it would create a whole new field. However, I would like to be able to use Child.set_website to crush Child model .__['source']['website']. In this example, I could have simply crushed the method. But as I am confronted with this problem many times, I would prefer not to have to crush. Right here, check_validity is used as a security measure to ensure that the use of the set method logic.

Finally, to tackle the problem dealt with in 2, which I did by defining set_website received the name of the class self .__ class__. What if the class is Source the method crushes the field website, if it is not the case, the method is first associated with the field source and inside that area he crushes website.


Being novice with this kind of tasks, I would appreciate any feedback, especially regarding