Programming in PythonClasses
Many Python functions use the usual function Syntax refers to the textual form of a given construct in a programming language. Examples: Indexing: Named functions: Anonymous functions: Lists: Tuples: Dictionaries: Dot syntax: myList[0], myDict["green"]
myFunction(x)
lambda x,y: x**y
[1, 2, 3]
(1, 2, 3)
{"a": 1, "b": 2}
module.function, object.attribute, object.method()
len("hello")
. However, many other functions are called using a different syntax where an object comes first:
"hello".capitalize()
These functions are called methods. For example, capitalize
is a string method. To understand how methods work in the language, it's helpful to see what they look like at the point of definition.
Suppose you want to write a program which keeps track of the albums you own. Each album is associated with several data, like the name of the album, the year it came out, the number of tracks, etc. You could store all these data by assigning them to different variables, but that becomes untidy very quickly. For example, you will frequently want to pass an album to a function, and you don't want that function to require a long list of parameters just because the album has a lot of data associated with it.
What you want is to be able to treat each album as its own Python object, with all its associated data stored inside. In other words, you want an Album
type. You can do that with the class
keyword (this block won't return anything):
class Album(object):
def __init__(self, name, artist, year, length):
self.name = name
self.artist = artist
self.year = year
self.length = length
def numYearsAgo(self, currentYear):
"Return the number of years since album was released"
return currentYear - self.year
A function defined in the block indented below class Album(object):
is called a method of the class Album
. The \_\_init\_\_
method has a special role: Python calls it whenever Album
is called as a function to create an instance of the class Album
.
A = Album("Abbey Road", "The Beatles", 1969, "47:23")
A
The first parameter, customarily called Syntax refers to the textual form of a given construct in a programming language. Examples: Indexing: Named functions: Anonymous functions: Lists: Tuples: Dictionaries: Dot syntax: self
, refers to the object being created. The four lines in the init method above assign values to attributes which may be accessed later using the dot myList[0], myDict["green"]
myFunction(x)
lambda x,y: x**y
[1, 2, 3]
(1, 2, 3)
{"a": 1, "b": 2}
module.function, object.attribute, object.method()
A.name
or A.artist
.
Dot syntax is also used to access other methods like numYearsAgo
.
A.numYearsAgo(2019)
The object appearing before the dot is implicitly supplied as the first argument to the method. Therefore, A.numYearsAgo(2019)
at call time corresponds to numYearsAgo(A, 2019)
at the point of definition. In fact, you can use the latter syntax if you want, because methods are also accessible using dot syntax on the class name: Album.numYearsAgo(A, 2019)
.
Exercise
Confirm that "hello".capitalize()
does give the same value as str.capitalize("hello")
.
Exercise
In the expression "".join("hello")
, the method join
has
Solution. There are two arguments: the first is the empty string, and the second is "hello"
.
Exercise
Implement a class called Fraction
which represents a ratio of two positive integers. You should reduce the fraction in your \_\_init\_\_
method. Your Fraction
type should include a method called \_\_add\_\_
which adds two fractions and an \_\_eq\_\_
which checks whether two fractions are equal. (These methods will be automatically used by the addition and equality operators.)
from math import gcd
# add code here
def test_Fraction():
assert Fraction(1,2) + Fraction(1,3) == Fraction(5,6)
assert Fraction(2,4) + Fraction(4,8) == Fraction(3,3)
return "Test passed!"
test_Fraction()
Solution. We divide by the gcd in the init method, and we define the other two methods according to the rules of arithmetic:
from math import gcd
class Fraction(object):
def __init__(self, num, denom):
d = gcd(num, denom)
self.num = num//d
self.denom = denom//d
def __add__(self, other):
return Fraction(self.num * other.denom + self.denom * other.num,
self.denom * other.denom)
def __eq__(self, other):
return self.num == other.num and self.denom == other.denom
def test_Fraction():
assert Fraction(1,2) + Fraction(1,3) == Fraction(5,6)
assert Fraction(2,4) + Fraction(4,8) == Fraction(3,3)
return "Test passed!"
test_Fraction()