Created
April 5, 2011 04:31
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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