# 11. Strings & Objects

• Strings are a little different when compared to the other types we have seen (int, float, bool)

• Classically speaking, a string is a collection of individual characters

• In fact, we can index the string to access individual characters from it

1some_string = "Hello, world!"
2print(some_string[0])   # prints out 'H'
3print(some_string[4])   # prints out 'o'


Note

In Python, and many other programming languages, the index for the beginning is actually 0, not 1. There are some historical and engineering reasons for this, and there are plenty of programming languages that start at 1 too. This can feel tedious for new programmers, but it will become natural to you.

Activity

1. Write a single line command to print the first 4 characters of some string.

2. How about the 2nd to 7th characters?

3. Get the last three characters? Hint: what does a negative index do?

4. Get the length of a string.

5. What does print(a[0:4]) do?

## 11.1. For loops

• We can find the length of a given string with len(some_string)

• And we know we can index individual characters from a string

• Let’s write a function vertical_print_while that prints a string vertically (one character per line)

 1def vertical_print_while(a_string: str):
2    """
3    Print out a string vertically. In other words, print out a single character on each line.
4
5    :param a_string: Some string to print out
6    :type a_string String
7    """
8    character_index = 0
9    while character_index < len(a_string):
10        print(a_string[character_index])
11        character_index += 1


Activity

Write the vertical_print_while function yourself. Try not to just copy/paste the provided solution. Call the function on a few different strings to see if it behaves the way you expect.

• The while loop worked perfectly fine

• But there is another type of loop called a for loop that may feel a little nicer to use in this scenario

• These for loops are great for when we have a collection of things and we want to do something for each of those things

1def vertical_print_for(a_string: str):
2    """
3    Print out a string vertically. In other words, print out a single character on each line.
4
5    :param a_string: Some string to print out
6    :type a_string String
7    """
8    for char in a_string:
9        print(char)

• The while loop will continue to run while the condition is True

• The for loop will run for each thing

• In this example, the for loop will run for each character in the string

• If we were to call vertical_print_for("Hello")

• The first time through the loop char would have the value "H"

• The second time char would have the value "e"

• The third time char would be "l"

• Fourth time char is "l" again

• The fifth time char is "o"

• The loop ends as there are no more characters in the string

• Both the while and for loops are perfectly fine for this situation

• But you may find the for loop has a little nicer syntax

Note

In the vertical_print_for example, the use of the variable name char in the for loop is arbitrary. It is just a variable name and is not required to be char because the things in the string are characters. I chose char since it is an appropriate name for the variable. For example, the following code would work:

1for terrible_variable_name in a_string:
2    print(terrible_variable_name)


## 11.2. Immutability

• Although we can access individual characters at a specified index

• some_string[an_index]

• We cannot change the value at a specified index

• some_string[an_index] = "X"

• If you try this, you will get TypeError: 'str' object does not support item assignment

• This is because strings are not mutable

• They’re immutable

• Fancy way of saying, once they exist you cannot change them

• However, there is nothing stopping us from making a new string based on the old

1a_string = "Hello, world!"
2b_string = a_string[:5] + "!" + a_string[6:]


## 11.4. String Trivia

• ' or " will work for the quotes needed for strings

1a = "This is a string"
2b = 'this is also a string'

• We can concatenate strings with +

1a = "CSCI" + " " + "161"
2print(a)    # results in "CSCI 161"

• We can make a string repeat with *

1a = "CSCI" * 3
2print(a)    # results in "CSCICSCICSCI"

• We can convert an int to a str

1print(type(1))      # <class 'int'>
2print(type(str(1))) # <class 'str'>

• The string "" is a string, but it’s empty

1a = ""
2print(len(a))   # results in 0
3print(type(a))  # results in <class 'str'>

• We have some special characters that we have no keys for on the keyboard, like a newline or an indent tab

• '\n'

• '\t'

• There are many

1a = 'hello\nWorld\tFUN\\!'
2print(a)
3# hello
4# World   FUN\!

• ASCII Table
• Every character is a number

1wut = ord('a')  # get the num of "a"
2print(wut)      # results in 97
3
4wut = chr(65)   # convert num to char
5print(wut)      # results in "A"


## 11.5. f-Strings

• There are a number of ways to format strings in Python, but we will focus on f-Strings due to their simplicity and popularity

1name = "John Doe"
2course_code = "CSCI 161"
3to_print = f"My name is {name} and I love {course_code}."
4print(to_print)    # My name is John Doe and I love CSCI 161.

• In the previous example, all the variables were of type string, but they don’t have to be

• We can even format the output of a floating point number to a specified decimal place

1some_integer = 123
2some_float = 456.789
3to_print = f"The following is an integer {some_integer}, and this is a float to 2 decimal places {some_float:.2f}."
4print(to_print)    # The following is an integer 123, and this is a float to 2 decimal places 456.79.

• You can even specify align output nicely with f-Strings

• For example, if you wanted to format some output of something like a bill and you wrote the following, it wouldn’t look too nice

1# Ugly
2print(10.95)
3print(1.10)
4print(123.45)
5
6# Output
7# 10.95
8# 1.1
9# 123.45

• Notice how the decimal place does not align well

• If instead we used f-Strings like this, it would look much better

1# Pretty
2print(f"{10.95:8.2f}")
3print(f"{1.10:8.2f}")
4print(f"{123.45:8.2f}")
5
6# Output
7#   10.95
8#    1.10
9#  123.45

• Literal values were included in the above example, but this would also work with variables

Warning

This only scratches the surface of what you can do with f-Strings. Further, much of the same functionality can be done without f-Strings, but f-Strings are very popular and simple.

If you are wondering “how am I supposed to remember all this?”, don’t worry — you’re not supposed to. All that you really need to remember is that f-Strings are a thing and if you need to use them in the future, just do a quick search on Google.

## 11.6. Objects

Warning

Much of the following is going to be kept at a very high level and not quite accurate for Python. That said, the underlying ideas being presented below are important. Additionally, more details on Objects are presented later in the course.

• We have seen a few types so far

• Most of these are what we call primitive types

• Integers

• Floats

• Booleans

• But we have also seen Strings and how they are a little different

• Strings are objects and work a little different

### 11.6.1. Methods

• We’ve seen built in functions

• print('this is a function')

• We’ve written our own functions

• character_is_in('a','bleh')

• However, there is also something called a method that is very similar to a function, but acts on a specific instance of an object

Activity

In Colab:
1. Assign a string to some variable and print it out

2. After running the code, type the name of the variable

3. Press . (period)

4. Wait (or press space, or tab, or ctrl-space

You should see a menu pop up that looks like the following:

• The menu that popped up contains methods that can be run on a string

• Other objects that we will see later in the course will have methods associated with them too

Activity

1. Assign some string to a variable called a_string

2. Add the line of code a_string.upper() and then print out a_string

3. Try some of the other methods and see what they do

### 11.6.2. Method vs. Function

• Why do we have to do it with a method

• a_string.upper()

• Instead of a function like this?

• upper(a_string)

• In reality, there is nothing stopping us from writing the function upper(a_string)

• But with the string, the sequence of characters that make up the string are stored in the object

• The method a_string.upper() is about the data within the object

• The functionality that manages the data in that object will belong to that object