Skip to content

Instantly share code, notes, and snippets.

@monokrome
Created April 5, 2011 04:31
Show Gist options
  • Save monokrome/903038 to your computer and use it in GitHub Desktop.
Save monokrome/903038 to your computer and use it in GitHub Desktop.
A basic idea of how you can implement factories in Python, and what they are used for.
#!/usr/bin/env python
# Here, we are going to implement a Robot. This robot has a lot of attributes - and
# we are going to want to make these accessible through a public interface.
# CHANGE LIST:
# - Added an object that we are using in order to map strings to indexes
# in our data source. This is useful for making things a bit more user
# friendly in some cases. Usually with more complicated data sources.
#
# - Added __getitem__ method, which will allow us to access arbitrary data
# without needed any new code added if the data source's data changes.
#
# - Modified the robot to get properties through a factory to reduce the
# amount of code duplication as the number of attributes becomes larger
arbitrary_data_source = {
'weight': 20.5,
'height': 14.3,
'arm_count': 2,
'leg_count': 4
}
def robot_getter_factory(index):
""" Given 'index', this returns a function that can be used to get that
index from the data attribute of the context passed to it.
"""
def getter(context):
return context.data[index]
return getter
class Robot(object):
""" This is a robot. He is neat. """
data = arbitrary_data_source
data_aliases = {
'arms': 'arm_count',
'legs': 'leg_count',
}
# Use the getter factory to create our getters, so that we don't need to
# repeat ourselves with the same code over and over again.
get_weight = robot_getter_factory('weight')
get_height = robot_getter_factory('height')
get_arm_count = robot_getter_factory('arm_count')
get_leg_count = robot_getter_factory('leg_count')
def __getitem__(self, index):
""" Allows our object to be accessed with [] operators - like a you
would access a dict.
"""
# If the provided index is an alias, get the value of the map that
# resolves to it's real identifier in the data source.
if index in self.data_aliases:
index = self.data_aliases[index]
getter_method = robot_getter_factory(index)
# We need to pass 'self' explicitly here, since our function isn't
# being hosted as an object method - but as a normal function instead.
return getter_method(self)
if __name__ == '__main__':
my_robot = Robot()
def robot_status_output(description, value):
result = 'My robot ' + description.format(value)
return result
robot_status_map = {
'weighs {0} pounds.': my_robot['weight'],
'is {0} feet tall.': my_robot['height'],
'has {0} legs.': my_robot['legs'],
'has {0} arms.': my_robot['arms'],
}
# I should probably have used a generator expression here...
for description, value in robot_status_map.iteritems():
print robot_status_output(description, value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment