Skip to content

Reading 5: Objects and Methods

A graphic representation of data abstracted from banks
of every computer in the human system.
Unthinkable complexity.
Lines of light ranged in the nonspace of the mind,
clusters and constellations of data.
Like city lights, receding.
- William Gibson, Neuromancer

Overview

We've covered many of the essential aspects of Python programming, but we still have a way to go! In this reading we'll talk about what an "object" is, what "methods" do and how they are related to functions, and how Python is an "object-oriented language". We will use strings as a simple example of an object, but we will see many more kinds of objects later on.

Info

In fact, in Python all data are represented as objects. Even functions are objects.

Topics

  • Terminal input using the input function

  • Objects and methods

Terminal input

This is not really about objects and methods, but we have to put it somewhere, so we're putting it here 😄.

We'd like to be able to write interactive programs, where you (the user) and the program have a "dialogue". You do something, the program responds, you respond to the program, and so forth. There are many ways to do this, but the most basic way is to allow the program to read a line of input typed at the terminal. When the program wants a response from you, it asks you for a line of input. You type it in and hit the return key, then the program does something with that line of input, and so on. In Python, we do this using the input function:

>>> input()
*This is what you type.*
'This is what you type.'

Note

We've put asterisks around the text that you would type into the terminal for the input() function call. You wouldn't actually type the asterisks.

The line under the input() call is what you type literally at the keyboard (try it!). When you're done, hit the return key and Python prints the string it received.

This isn't how you actually use input, of course. You almost always store the line read into a variable:

>>> answer = input()
*This is my answer.*
>>> answer
'This is my answer.'

Now you can use the value of answer to do something in your program. One other thing that would be nice is if input could print a prompt, which is a string that indicates what it is expecting of you. To use a prompt, add a string argument to input:

>>> answer = input('Please answer "yes" or "no": ')
Please answer "yes" or "no": *yes*
>>> answer
'yes'

The only thing that the user entered in this example was the word yes, which becomes the value of the answer variable.

Question

  1. Why are the words "yes" and "no" in the prompt string written with double quotes?

  2. Why is there a blank space at the end of the prompt string?

Type this example into Python yourself, and play around with it to get familiar with how the input function works.

Using input to input integers and other non-strings

One thing to be careful about is that input always returns a string, even if you intended it to return e.g. an integer. For instance, look at this code:

i = input('Enter an integer: ')
j = input('Enter another integer: ')
print('The sum of the two integers is {}'.format(i + j))

Here's a sample run:

Enter an integer: *42*
Enter another integer: *101*
The sum of the two integers is 42101

What went wrong?

Remember, computer languages are dumb and they don't know what you want them to do unless you spell it out exactly. Here, the input function always returns a string, so the variables i and j contain the strings '42' and '101', respectively. When you "add" two strings, you actually concatenate them, so you get the result '42101'. To avoid this, you have to tell Python to convert the result of the input call to an integer using the int conversion function. Here's the right way to do this:

i = int(input('Enter an integer: '))
j = int(input('Enter another integer: '))
print('The sum of the two integers is {}'.format(i + j))

Now look at what happens when we run it:

Enter an integer: *42*
Enter another integer: *101*
The sum of the two integers is 143

This time it works, because of the calls to the int function which converts the string output from input to integers. Again, please play around with this in the interpreter so you understand exactly how it works.

You can convert strings to more than just integers. You can also convert strings to floating-point numbers with the float function:

>>> pi = float('3.1415926')
>>> pi
3.1415926
>>> 4.0 * pi
12.5663704

Exceptions

You might wonder what happens if you try to convert a string to a float (or an integer) which is not the string representation of a valid float (or integer). For example:

>>> pi = float('foobar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: 'foobar'

In this case, Python handles the error by raising an exception and printing a traceback. We will talk a lot more about exceptions and traceback in future readings.

OK, that's enough about input. On to objects!

Objects and methods

You've probably heard the term "object-oriented" as in "Python (or Java, or C++) is an object-oriented programming language". What does that mean?

The exact meaning of "object-oriented" differs between languages, but for Python, it means that all data values are represented as objects. OK, great, so what is an object?

An object is some kind of Python data along with some associated functions that act on the data. (You can think of the data and the functions as begin "bound together" to create an object.) The functions that act on the object are called methods to distinguish them from regular functions. Unlike a function, a method "belongs" to a particular object and has access to the object's internal components.1

Let's look at the syntax of method calls.

Method call syntax ("dot syntax")

We know that function calls have a very specific syntax: the name of the function, followed by a list of arguments in parentheses. Multiple arguments to a function are separated by commas. So function calls looks like this:

func1()        # no arguments
func2(x)       # one argument
func3(x, y, z) # three arguments

and so on. Method calls are almost exactly the same, except that instead of the name of the function, we have the name of the object, a dot (.) and the name of the method. Here are some hypothetical method calls on a hypothetical object called obj:

obj.method1()
obj.method2(x)
obj.method3(x, y, z)

Method calls are like function calls on an object. If you like, you can think of the object as an extra argument to the method that happens to be placed in a weird location (before the dot).

I call the obj.method kind of syntax for method calls the "dot syntax". As we'll see in later readings, this syntax is used for more than just method calls, though the other uses are similar.

Strings are objects

We've actually been working with Python objects already. Since all Python values are objects, even things like integers are objects (but we don't usually use methods on integers). Strings are also objects, and there are a number of useful methods defined for strings. For instance:

>>> 'spam'.upper()
'SPAM'
>>> s = 'spam'
>>> s.upper()
'SPAM'

The upper method on strings converts a string to its uppercase version. (Note that it doesn't change the string, because strings are immutable; it simply creates a new string with the same characters but uppercased).

Notice that you can call a method on a literal value (like 'spam') or on a variable that stands for that value (like s). Most of the time, we use methods on variables, but in this reading we'll often use methods on literal strings for convenience.

Since methods are like functions, they have an argument list. In this case, the argument list is empty, so we have to put the open/close parentheses () after the name of the method. It's pretty common to have methods that take no arguments; what that means is that the method only needs the name of the object to do what it's doing. In this case, all the upper method needs to know about is the string object itself.

You might think that it's dumb that you have to include an empty pair of open/close parentheses to call a method with no arguments. But if you leave them off, the method never gets called:

>>> 'spam'.upper
<built-in method upper of str object at 0x109d3ee30>

Python is basically saying here "yup, that's a method all right". If you want it to do something, you need the parentheses.2

Here are some other methods on strings:

>>> 'SPAM'.lower()
'spam'
>>> 'spam'.islower()
True
>>> '   string with spaces on each end    '.strip()
'string with spaces on each end'
>>> 'Caltech'.endswith('tech')
True

Info

Python uses the special names True and False to stand for boolean (true/false) values.

Notice in particular the call to the endswith method. This is the first method call we've seen that has an argument in its argument list.

A full list of Python's string methods can be found here. You're not expected to memorize them! Some of the more useful ones include:

  • capitalize
  • startswith and endswith
  • find
  • format (we've seen this already)
  • index
  • join
  • lower and upper
  • strip

Exercise

Pick three methods from the above list and look up their definitions. Don't memorize them; just remember enough so that when you come across a situation where they might be useful, you'll know where to look.

Methods vs. functions

Let's take a closer look at the endswith method:

>>> 'Caltech'.endswith('tech')
True

You might wonder why this wasn't written as a regular function, e.g. something like this:

>>> endswith('Caltech', 'tech') # Doesn't work!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'endswith' is not defined

Python is telling you that there is no endswith function.

In fact, endswith could have been written that way. Or you could define it that way if you really wanted to:

>>> def endswith(s, suffix):
...     return s.endswith(suffix)
...
>>> endswith('Caltech', 'tech')
True

There's no reason to do this, though. One benefit of using methods instead of functions is that you can use the same method name on different objects and have it mean different things for each object. Usually, though, it's better if the meaning is similar (even if it's not identical), because otherwise it's likely to be confusing. Not having to define new names for similar (but not identical) functionality means that code reads better and is more intuitive.

Defining methods

We will not go into the syntax for defining methods at this time. In fact, it's almost identical to function definition syntax. For now, and for most of this course, we will use pre-written methods. Python's extensive code libraries (called modules) and many built-in data structures mean that there are a lot of pre-written methods we can use right away.

The len function

As we mentioned above, there are many function-like things that can be written either as methods or as functions, at least in principle. Python is not always totally consistent in this regard.3 Some things are written as functions, and others as methods, and sometimes you find the same functionality is provided by both a function and a method. Usually, though, a particular behavior is implemented as one or the other.

As if this wasn't confusing enough, consider the very useful built-in len function. (Notice that I said function, not method.) len takes a single argument and returns its "length", whatever "length" means for that kind of data. We can use len on a lot of different kinds of Python objects. For instance, strings have a length:

>>> len('foobar')
6

For a string, its len is the number of characters in the string.

On the other hand, integers and boolean values don't have a len:

>>> len(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
>>> len(True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'bool' has no len()

Lists (which are another data type that we'll meet shortly) also have a length:

>>> len([1, 2, 3])
3

(Here, [1, 2, 3] is Python's syntax for a list of three integers: 1, 2, and 3.) So len works on both strings and lists, but it should be clear that finding the length of a string is a different kind of operation than finding the length of a list. You might think, therefore, that Python should have made len a method on strings and lists, not a function. Why didn't it?

Well, actually, it did but it pretends that it didn't. When you say len(x) in Python, it internally calls a method called __len__ on the object. Observe:

>>> len('foobar')
6
>>> 'foobar'.__len__()
6
>>> len([1, 2, 3])
3
>>> [1, 2, 3].__len__()
3

The only reason len is a function is that it's used so often that the Python designer (Guido van Rossum) figured that it would be more pleasant to write it like a function than like a method. You can agree with this or not, but that's how it is.4

What's more interesting is that this is a good example of a method (__len__) which has the same name for two different kinds of objects (strings and lists) but which does different things in each case. Both things are conceptually "lengths" but the details are different. This is common with methods: each object can use the same method names as other objects, but the meaning of these methods is specific to the object.

Special methods

One last thing: the __len__ method uses a naming convention that we'll see again. Names of methods that are used internally by Python for some important purpose are, by convention, written with two leading and two trailing underscores. There are a bunch of "special methods" like this that do a number of things, and we'll meet some more of them very soon. Be aware, though, that this is only a convention. You could write your own methods with names like this, and Python would still accept it. However, please don't do that! If you redefined a method like __len__, your program will probably fail, and it might be very hard for you to figure out why.


  1. That is, assuming the object has any internals. Some very simple objects, like integers, don't have any internal components. 

  2. Some object-oriented languages, like Ruby, don't require you to use parentheses for methods with no arguments. You can waste an incredible amount of time arguing over whether this is a good or a bad thing. 

  3. Some languages, like Java or Ruby, try hard to be "pure" object-oriented languages. Python is more pragmatic; Python programmers use whatever seems best for the application at hand. 

  4. Every programming language has some features in it that some people don't like. Most have features that almost everyone doesn't like. Python is very good, but it isn't perfect. Features in a programming languages that most programmers dislike are commonly referred to as warts. Compared to most languages, Python has very few warts.