#!/usr/bin/env python from dataclasses import * #dataclass, make_dataclass def validate_positive(name, value): '''eine einfache Validierungsfunktion''' if value < 0: raise ValueError( f'The value for {name!r} must be positive, {value!r} is not.') class YearBetweenValidator: '''komplexerer Validator, beachte die magische Methode __call__''' def __init__(self, mini, maxi): self.mini, self.maxi = mini, maxi def __call__(self, name, value): if value > self.mini and value < self.maxi: return True raise ValueError(f'The value for {name!r} must be between {self.mini!r} and {self.maxi!r}, {value!r} is not.') class BaseDesc: '''ein Deskriptor''' def __init__(self, type, validators=[]): self.type = type self.validators = validators def __set_name__(self, owner, name): self.name = name def __get__(self, obj, objtype=None): return getattr(self, self.name) def __set__(self, obj, value): if not isinstance(value, self.type): raise TypeError(f'The value for {self.name!r} must be a {self.type!r}, {value!r} is not.') for validate in self.validators: validate(self.name, value) setattr(self, self.name, value) class BaseData: class meta: '''docstrings are cool, too...''' s = '''This is just a metaclass whose attributes are not in BaseData...''' def getFields(self): return list(self.__dataclass_fields__.keys()) def printme(self): rv = list() fields = self.getFields() for field in fields: rv.append('{}={}'.format(field, getattr(self, field, None))) print(' '.join(rv)) return(rv) def makePerson(): rv = make_dataclass( 'Person', bases=(BaseData,), fields=[ ('vorname', str, field(default=BaseDesc(str))), ('nachname', str, field(default=BaseDesc(str))), ] ) return rv def makeStudent(): rv = make_dataclass( 'Student', bases=(BaseData,), fields=[ ('vorname', str, field(default=BaseDesc(str))), ('nachname', str, field(default=BaseDesc(str))), ('matriculation', int, field(default=BaseDesc(int, [validate_positive]))), ] ) return rv def makeGraduate(): rv = make_dataclass( 'Graduate', bases=(BaseData,), fields=[ ('vorname', str, field(default=BaseDesc(str))), ('nachname', str, field(default=BaseDesc(str))), ('matriculation', int, field(default=BaseDesc(int, [validate_positive]))), ('graduation', int, field(default=BaseDesc(int, [validate_positive, YearBetweenValidator(1990, 2020)]))), ] ) return rv if __name__ == '__main__': Person = makePerson() Student = makeStudent() Graduate = makeGraduate() try: print(Person('Sheeva', 'Plug')) except Exception as e: print(str(e)) try: print(Student('Sheeva', 'Plug', 1991)) except Exception as e: print(str(e)) try: print(Graduate('Sheeva', 'Plug', 1991, 1995)) except Exception as e: print(str(e)) try: print(Graduate('Sheeva', 'Plug', 1991, '1995')) except Exception as e: print(str(e)) try: print(Graduate('Sheeva', 'Plug', 1991, -1995)) except Exception as e: print(str(e)) try: print(Graduate('Sheeva', 'Plug', 1989, 1989)) except Exception as e: print(str(e)) print('-------------------------------------------------------------') try: print(Graduate('Sheeva', 'Plug', 1991, 1995).getFields()) except Exception as e: print(str(e)) print('-------------------------------------------------------------') try: makeGraduate()('Sheeva', 'Plug', 1991, '1995').printme() except Exception as e: print(str(e)) print('-------------------------------------------------------------') try: g = makeGraduate()('Sheeva', 'Plug', 1991, 1995) g.printme() print(g.meta.s) print(g.meta.__doc__) print(vars(g)) print({i: getattr(g, i) for i in dir(g)}) except Exception as e: print(str(e))