Skip to content

Instantly share code, notes, and snippets.

@gerryjenkinslb
Last active July 27, 2018 22:15
Show Gist options
  • Save gerryjenkinslb/1b40527b94e961825039cf2cfcf05e58 to your computer and use it in GitHub Desktop.
Save gerryjenkinslb/1b40527b94e961825039cf2cfcf05e58 to your computer and use it in GitHub Desktop.
Showing dynamic Class/Object possibilites using object.__dict__ in Python 3.6+
import math
# basic point class
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def distance(self, other_point):
return math.hypot(self.x - other_point.x, self.y - other_point.y)
def run():
p1 = Point(1, 2)
p2 = Point(2, 3)
print(f'distance: {p1.distance(p2):.5f}')
if __name__ == '__main__':
run()
import math
# added __repr__ printing self.__dict__
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def distance(self, other_point):
return math.hypot(self.x - other_point.x, self.y - other_point.y)
def __repr__(self): return str(self.__dict__) # new
def run():
p1 = Point(1, 2)
p2 = Point(2, 3)
print(f'p1:{p1} p2:{p2}') # new
print(f'distance: {p1.distance(p2):.5f}')
if __name__ == '__main__':
run()
import math
class Point(object):
defaults = {'x': 0, 'y': 0} # new
def __init__(self):
self.__dict__.update(Point.defaults) # new body
def distance(self, other_point):
return math.hypot(self.x - other_point.x, self.y - other_point.y)
def __repr__(self): return str(self.__dict__)
def run(): # modified
p1 = Point()
print(f'p1:{p1}')
if __name__ == '__main__':
run()
import math
# created template and class method to update it
class Point(object):
defaults = {'x': 0, 'y': 0} # new
@classmethod
def set_defaults(cls, **kwargs): # new method
Point.defaults.update(kwargs)
def __init__(self):
self.__dict__.update(Point.defaults) # new body
def distance(self, other_point):
return math.hypot(self.x - other_point.x, self.y - other_point.y)
def __repr__(self): return str(self.__dict__)
def run(): # modified
p1 = Point()
print(f'p1:{p1}')
Point.set_defaults(x=99)
p2 = Point()
print(f'p2:{p2}')
# surprise
Point.set_defaults(z=0)
p3 = Point()
print(f'p3:{p3}')
p3.z = 42
print(f'p3:{p3}')
if __name__ == '__main__':
run()
import math
# add dynamic object attributes
class Point(object):
defaults = {'x': 0, 'y': 0}
@classmethod
def set_defaults(cls, **kwargs):
Point.defaults.update(kwargs)
def __init__(self, *args, **kwargs):
self.__dict__.update(Point.defaults)
keys = list(Point.defaults.keys())
for i, v in enumerate(args): # copy args to __dict__ in order
self.__dict__[keys[i]] = v
self.modify_attributes(**kwargs)
def modify_attributes(self, **kwargs):
self.__dict__.update(kwargs) # new
def distance(self, other_point):
return math.hypot(self.x - other_point.x, self.y - other_point.y)
def __repr__(self): return str(self.__dict__)
def run(): # modified
p1 = Point(1, 2, z=99, label='p1')
print(p1)
p1.modify_attributes(z=88, color='green')
print(p1)
if __name__ == '__main__':
run()
Lessons in dynamic attributes for a class using self.__dict__
From python.org documents:
object.__dict__ :
A dictionary or other mapping object
used to store an object’s (writable) attributes.
Learn to object.__dict__ for:
1. Setting defaults for the classes/object attributes
Kind of like a dynamic template for your objects
2. Defining a flexible constructor can be called with attributes or
allowed to be set to defaults
3. Adding new attributes to class to affect future object instances
4. Adding attributes to specific object dynamically after creation
*** this code relies on python version 3.6+ or 3.7+
*** This is just one way to do these things,
I don't claim they are the most pythonic way.
*** you should already know these concepts:
@classmethod, *args, **kwargs, and dict update, enumerate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment