Python for Youngsters

Part 1: Variables, Functions, and Classes

Gregory Terzian
Python for Youngsters
9 min readMar 23, 2023

--

Introduction to the First Part

All code examples below can be copied and pasted into something called a Python interactive shell.

On my mac, starting a Python shell takes the following:

1. Open the terminal application, found within Applications, under Utilities.
2. type python.

Follow this, or search online about how to start a Python shell on your computer, and let’s get started.

1.1 Variables

In programming, variables are used to name things.

"something"

Here is a piece of data; textual data — known in Python as a string — containing a sequence of letters that we recognize as the English word “something”. Using a variable, we can give this string a name.

a = "something"

We have given the string “something” the name a, or, as programmers like to say: we assigned the string “something” to the variable a.

Naming things is useful, because, as we will see below, it allows us to reuse those things elsewhere in our program.

b = "else"

Now we have two pieces of text, two strings: a, the string “something”, and b, the string “else”. We can now combine these two string into a single one.

a + b

Using our two variables, we have combined ”something” with “else” into a new string: the nonsensical “somethingelse”.

Unhappy with the nonsense of “somethingelse”, we want to correct our program so that it will combine the two words into the text “something else” — adding an empty space between the two. We do this using another string, one containing a single character of space.

empty_space = " "
a + empty_space + b

This does the job, but we can remove some clutter: the string of empty space does not requires naming; we can use the value without assigning it to a variable.

a + " " + b

This makes the program shorter, and more expressive — the program becomes easier to read. We could further improve our program: choosing for each of our variables names that describe what they represent.

first_word = "something"
last_word = "else"
first_word + " " + last_word

If a variable is unnecessary for the empty space, why use variables for the first and last word? The word “variable” actually means: something that can change. Using variables for the two words is useful if we are writing a program that can combine different words together.

first_word = "nothing"
first_word + " " + last_word

In our second word combination, we changed the string assigned to the variable first_word, but we left unchanged the string assigned to last_word; the result was a different combination: “nothing else”.

Programmers have a word for using a different value for a variable that has been previously assigned: reassignment. The name first_word was first used to refer to the string “something”, and later the variable was reassigned to refer to another string: “nothing”. Reassignment should be done with care: it makes it easy to lose track of what a variable stands for.

Let’s look again at the entire program together for clarity.

first_word = "something"
last_word = "else"
first_word + " "+ last_word

first_word = "nothing"
first_word + " " + last_word

While the program is readable — the variables clearly describe what they represent — we’ve had to repeat the logic that combines words: the program has become repetitive. We will remove this repetition in the next chapter, by introducing the use of functions.

1.2 Functions

A function is a reusable piece of code: you can use it to to avoid repeating yourself. A function can include parameters — arguments passed to the function from the outside world — as well as return a result. Let’s define a function that combines two words, adding an empty space between the two, and returns the combination.

def combine_words(first, last):
combined_words = first + " " + last
return combined_words

Here we have defined a function called combine_words, a verb-like name that clearly tells what the function does. The function has two parameters: first, and last. These are used as variables within the code inside the function: the function’s body. Note how the body is indented by four spaces, that is how Python makes it clear that the body is a separate group of code.

Next we recognize the familiar line of code: combining two words, an empty space between them. The result of that operation is assigned to a variable, which is then returned at the end of the function. The return statement signals the end of the function, and anything next to it becomes available as the result of calling the function. Let’s use this function to remove the repetition encountered in the previous chapter.

def combine_words(first, last):
combined_words = first + " " + last
return combined_words

first_word = "something"
last_word = "else"
result = combine_words(first_word, last_word)
print(result)

first_word = "nothing"
result = combine_words(first_word, last_word)
print(result)

We’ve started using another function: the print function that comes with the language. Its use is to print value out to the console, and here we use it to print the result of the word combination(re-assigning the result variable). This has become necessary because the Python interactive shell only automatically prints out the last value in a set of statements.

Instead of repeating the code that combines words, we now repeatedly call the combine_words function. This an improvement because the logic of combining words is now found in only one place: in the function’s body. If you wanted to change this code — for example adding a period at the end, and perhaps removing the unnecessary variable(see below) — you would have to change only the code inside the function’s body.

def combine_words(first, last):
return first + " " + last + "."

first_word = "something"
last_word = "else"
combine_words(first_word, last_word)

You may wonder why the parameters of the function have different names from the variables passed as arguments to it when called: first and last against first_word and last_word. The answer is that the code outside the function, and the code inside the function, are two separate worlds.

Programmers have a name for these separate worlds: scopes. Within the scope of the function’s body, first and last are the names of whatever is passed as the first and second argument when the function is called. Outside of the function, we decided to name the string “something” using the variable first_word, but once we pass our variable as the first argument to the function, the string “something” goes inside the scope of the function’s body, and is renamed as whatever has been chosen as the name of the first parameter within that scope.

We don’t even need to name that which is passed as an argument to the function, as the below example shows.

def combine_words(first, last):
return first + " " + last + "."

combine_words("something", "else")

We have seen how a function allows us to reuse logic across our program: a change in the function’s body will change the logic of every function call. An example above was adding a period after the last word. We could define several functions, each one for different type of word combining operations.

def combine_two_words_with_space_and_period(first, last):
return first + " " + last + "."

def combine_two_words_with_space_and_exclamation_mark(first, last):
return first + " " + last + "!"

def combine_two_words_with_space(first, last):
return first + " " + last

print(combine_two_words_with_space_and_period("something", "else"))
print(combine_two_words_with_space_and_exclamation_mark("something", "else"))
print(combine_two_words_with_space("something", "else"))

Our program starts to feel repetitive again; what we need is a way to combine words, with a different final punctuation. We we will see how to achieve that in the next chapter, introducing another concept: classes.

1.3 Classes

A class is, like the function, a reusable piece of code. But, unlike the function, the class comes with a kind of memory; it acts as a grouping of functions that can remember things from one call to the next.

class WordCombiner:
def __init__(self, punctuation):
self.punctuation = punctuation

def combine_words(self, first, last):
return first + " " + last + self.punctuation

Here we define a class named WordCombiner, adding two function-like pieces of code — known as methods — to its definition. A class can be called as a function to create unique objects, each with their own memory: these are know as instances of the class.

simple_combiner = WordCombiner("")

Calling the class as we would a function, we create a new instance, a new combiner of words. Python automatically calls the __init__ method of the class, passing the new instance as the self parameter, and whatever the calling code passes as the sole argument will be supplied as the punctuation parameter: allowing us to configure our new instance with some initial data.

In the body of the __init__ method, we store the punctuation under the name punctuation— similar to how variables are used, except that the variable is stored inside self— we could call this an instance variable, although the Python community calls it a data attribute. Since we pass an empty string as argument, this particular combiner of words will not add any punctuation after the last word.

print(simple_combiner.combine_words("first", "last"))
print(simple_combiner.combine_words("another", "try"))

We can also create other combiners, for different use cases. Each instance carries its own memory: the instance’s state.

period_combiner = WordCombiner(".")
period_combiner.combine_words("first", "last")

We have removed the repetition encountered in the last chapter: the word combining logic is found in only one place, the combine_words method, and we can configure the final punctuation mark when creating an instance. You may realize by now that we could have achieve a similar trick while sticking to functions.

def combine_two_words_with_space_and_punctuation(first, last, punctuation):
return first + " " + last + punctuation

combine_two_words_with_space_and_punctuation("first", "last", ".")

When using a function to remove the repetition, the punctuation will have to be supplied as a the third argument to each function call; the function does not remember anything. The approach that makes the most sense will depend on the needs of your program and the sensibilities of the people you work with.

There are more things you can do with classes, things that would be harder or impossible to do with functions. For example, we could define a class that allows us to supply any number of words, one at a time, and finally combine them together at some later stage.

class WordCombiner:
def __init__(self, spacing, final_punctuation):
self.final_punctuation = final_punctuation
self.spacing = spacing
self.words = []

def add_word(self, word):
self.words.append(word)

def combine_words(self):
combined_words = self.spacing.join(self.words)
return combined_words + self.final_punctuation

combiner = WordCombiner(", ", ".")
combiner.add_word("one")
combiner.add_word("two")
combiner.add_word("three")
combiner.combine_words()

In this new version of our combiner of words, instead of always using the same spacing, the spacing has been made configurable via a data attribute named spacing. We have also added a method to add words to a list; when combining words, we join the spacing with the list of words stored inside our instance. We will discuss the list, and other basic data structures, in the next chapter.

For now, focus on the call to self.spacing.join(self.words) — a method call on an instance of the string class. Remember that self.spacing is a string. We didn’t discuss what “a string” is, but, like our combiner of words, it is also a class, one which happens to receives special treatment from Python: known as built-in types, we can create instances of it without having to call the class directly.

a = "one"
b = str("one")
print(a, b)

We see that both variables above are the same: the second was created using the str class directly; the first one used a more convenient syntax to create instances: string literals.

A string instance has a join method, which can join together a list of strings, using itself as the spacing.

"-> ".join(["one", "two", "three"])

As a programmer, you must know the classes you are using in your code: the methods they provide allow you to do many things without writing code yourself. Classes, like functions, are a way to share code: the capabilities classes make available are known as an interface. Some classes are provided to you by the Python language itself, others are provided to you by programmers in your team, yet others are provided to you by programmers who made them available for free as open-source code. When writing your own classes, you must therefore think about how they will be used by people, including yourself, and design their interface accordingly — the essence of good programming.

In the next part, we will look at the list used above, and other related built-in classes: dictionaries and sets. We will also look at an operation common to all three: processing items one after the other, known as iteration.

--

--

Gregory Terzian
Python for Youngsters

I write in .js, .py, .rs, .tla, and English. Always for people to read