Skip to content

Instantly share code, notes, and snippets.

@revuel
Created September 20, 2020 11:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save revuel/f8e384adcd70054ddca21eb7beb021d4 to your computer and use it in GitHub Desktop.
Save revuel/f8e384adcd70054ddca21eb7beb021d4 to your computer and use it in GitHub Desktop.
Example of using slotting a POPO class overriding __setattr__ to do validations
""" Just playing around with slots (BASIC EXAMPLE Plain Old Python Object) """
import re
date_pattern = re.compile(r'(\d{4})[/.-](\d{2})[/.-](\d{2})$')
class Person(object):
""" Person sample class with slots """
__slots__ = ('name', 'dob')
def __init__(self):
print(f'Initializing instance of {self}')
@property
def __dict__(self):
""" Dictionary representation for a slotted class (that has no dict at all) """
# Above works just for POPOs
return {s: getattr(self, s, None) for s in self.__slots__}
def __repr__(self):
""" String representation of a slotted class using hijacked dict """
return f'{self.__class__.__name__}({self.__dict__})'
def __setattr__(self, key, value):
print(f'Setting attribute "{key}" of {self} instance with {value} value')
if key == 'dob' and not date_pattern.match(value):
raise ValueError(f'Invalid date format "{value}" for {key} attribute')
else:
# Above is the trick to override __setattr__ in a slotted class
super(Person, self).__setattr__(key, value)
if __name__ == '__main__':
print(f'Running...')
p1 = Person()
p2 = Person()
try:
p1.name = 'Michael'
p1.dob = '1988/03/22'
p2.name = 'Rachel'
# Above will crash since it does not match the pattern yyyy/mm/dd
p2.dob = 'this-is-not-a-valid-date-format'
except Exception as ex:
print(f'{ex} was raised')
finally:
print(f'Person one is {p1}, person two is {p2}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment