Skip to content

Instantly share code, notes, and snippets.

@soedar
Last active December 24, 2015 09:09
Show Gist options
  • Save soedar/6775790 to your computer and use it in GitHub Desktop.
Save soedar/6775790 to your computer and use it in GitHub Desktop.
Data Abstraction
## Data Abstraction
# Variable Naming
# The key idea behind data abstraction is that we want to give meaning to data types. We already have
# seen how the naming your variables more meaninfully would help us give meaning to primitive data.
# For instance,
x = 24 # Not exactly clear what x refers to, and what does 24 mean
# Consider:
room_temperature = 24 # Now, we can probably infer that 24 is degree celsius, just by naming our
# variables meaningfully.
# However, we definitely can do better than that. We have simply inferred that the temperature is
# represented in celsius. We can of course rename it to room_temperature_c, however that is not an
# elegant solution to model the problem.
#########
# Data Abstraction
#########
# Clearly, one variable is not enough to represent the temperature of room. We need a way to represent
# the temperature with both the value of the temperature, as well as the unit of the temperature. From
# what we have learned so far in data abstraction, we can make use of a tuple to represent this
# information:
temperature = (24, 'C') # The 2nd parameter determines the type of temperature.
# The thing to note about in this case is that the although technically, the temperature variable
# holds a tuple, but that is not exactly accurate. The more accurate description is that the temperature
# variable now *holds the representation of a temperature*, which in this case happens to be a tuple.
# With this representation, we can define the following:
#Constructor
def make_temperature_c(deg):
return (deg, 'C')
# Accessors. Accessors take in a temperature type, and return the part of the temperature that
# we are interested in.
def temperature_value(temperature):
# Since we know the temperature is represented by the tuple (value, units), we
# return the first element of the tuple.
return temperature[0]
def temperature_unit(temperature)
return temperature[1]
#####################
# Using temperature
#####################
# With this, we can create the following function that makes use of the accessors:
# Fan takes in a temperature, and reduces it by 0.5 deg C
def fan(temperature):
new_temp = temperature_value(temperature) - 0.5
return make_temperature_c(new_temp)
# Note that by making use of the constructors and accessors, we are able to treat the temperature NOT
# as a tuple, but as a REPRESENTATION of the temperature, and that this representation will be
# independent of what is the underlying implementation of the temperature type.
########################
# Breaking Abstraction
########################
# In your missions, I have commented that some of you have broken abstraction. What I meant by that
# is, that instead of writing the above code, you can techincally write the following and it would work
# as expected (in this case)
# Breaking the abstraction
def fan(temperature):
return (temperature[0]-0.5, temperature[1])
# By breaking the abstraction, I meant that your functions now 'know' that temperature is represented
# as a tuple, with the first element as value, and the 2nd element as unit. Contrast with the first
# example of fan, when the function know NOTHING about how temperature is implemented, as how it is
# implemented has been has been taken care of by the constructors and accessors
############
# Rationale
############
# Why do we need the abstraction? Imagine one day, you decide that perhaps the best way to represent
# the data is to put the unit first, as a character. So you decide to re-write your constructors as
# follow:
def make_temperature_c(deg):
return ('C', deg)
def temperature_value(temperature):
return temperature[1]
def temperature_unit(temperature):
return temperature[0]
# Or if I decide to go crazy, and implement it like this:
def make_temperature(deg):
return deg + "_C"
def temperature_value(temperature):
# temperature is a string separated by _
return temperature.split('_')[0]
def temperature_unit(temperature):
return temperature.split('_')[1]
# Do you notice that although I have changed the representation of the of what a temperature is, the
# fan code in the first case will NOT break, because we are using the accessors to access the parts of
# the temperature 'type', and not making any assumption of what the underlying implementation of the
# data structure?
##############
# Bonus Question
##############
# 1) In the most common case of using a tuple to represent a temperature, how can we differentiate a
# tuple that represent a temperature, vs any other tuples?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment