Data Types

Learning Objectives

By the end of this chapter, you will be able to:

  • Explain the different numerical data types
  • Use operators on numerical data types
  • Explain strings and implement string operations, such as indexing, slicing, and string formatting
  • Describe escape sequences
  • Explain lists and perform simple operations on them
  • Use Boolean expressions and Boolean operators

This lesson introduces the data types available to us. We look at integers, strings, lists, and Booleans.

Introduction

In the previous chapter, we learned about variables and looked at a few of the values/types of data that can be assigned to them. Specifically, we dealt with data of the string and integer types. In this chapter, we will look at the other data types that Python supports. Data types classify data, to tell the interpreter how the program intends to utilize that data. Data types define the different operations that can be performed on the data, how the data is stored, and the meaning of the data.

Numerical Data

Let's begin with numerical data types.

Types of Numbers

Integers

Integers, as we saw in the previous chapter, are numerical data types that are comprised of whole numbers. Whole numbers can be either negative or positive. In the following example, we will see how Python represents integers, and then, we can check their types:

>>> integer = 49

>>> negative_integer = -35

>>> print(type(integer), integer)

<class 'int'> 49

>>> print(type(negative_integer), negative_integer)

<class 'int'> -35

>>>

Additionally, Python integers have unlimited precision. This means that there are no limits to how large they can be (save for the amount of available memory):

>>> large_integer = 34567898327463893216847532149022563647754227885439016662145553364327889985421

>>> print(large_integer)

34567898327463893216847532149022563647754227885439016662145553364327889985421

>>>

Floating Point Numbers

Another numerical type supported by Python is floating point numbers. The type for this kind of value is float. As we saw in the previous chapter, these are represented in the following way:

>>> n = 3.3333

>>> print(n)

3.3333

>>> import math

>>> print(type(math.pi), math.pi)

<class 'float'>, 3.141592653589793

>>> print(type(math.e), math.e)

<class 'float'>, 2.718281828459045

>>>

Here, we import math, which is a built-in Python library that provides access to different mathematical functions and constants. We print out the type and the values of the constants Pi (math.pi) and Euler's number (math.e). The displayed values are approximated.

Furthermore, you can convert an integer to a floating point value by using the float function:

>>> float(23)

23.0

>>>

Binary, Hexadecimal, and Octal Numbers

Binary, hexadecimal, and octal numbers are alternative number systems, as opposed to the common decimal number system that we're accustomed to. Binary numbers are numbers expressed in the base 2 system, which uses only 0s and 1s to represent numbers.

To write binary numbers in Python, write the number and prefix it with 0b. Typing a binary number on the interactive shell outputs its decimal equivalent:

>>> 0b111

7

>>> 0b10

2

>>> 0b1000

8

>>>

Hexadecimal numbers are numbers that are expressed in the base 16 system. The symbols 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f are used to represent hexadecimal numbers. Hexadecimal numbers should be prefixed with 0x. Typing a hexadecimal number in the interpreter outputs its decimal equivalent:

>>> 0xf

15

>>> 0x9ac

2476

>>> 0xaf

175

>>>

Finally, we have octal numbers, which are numbers written in the base 8 numbering system. This system uses the digits from 0 to 7 to represent numbers. In Python, they should be prefixed with 0o. Typing an octal number in the interpreter outputs its decimal equivalent:

>>> 0o20

16

>>> 0o200

128

>>> 0o113

75

>>>

To convert any decimal (base 10) number to binary, hexadecimal, or octal numbers, you can use the built-in bin, hex, and oct Python functions, respectively, as shown here:

>>> bin(7)

'0b111'

>>> hex(700)

'0x2bc'

>>> oct(70)

'0o106'

>>>

Exercise 11: Converting Between Different Types of Number Systems

In this exercise, we'll practice converting between different types of number systems. We will create a script that takes the user's input and converts it into a binary number.

The steps are as follows:

  1. Create a new file named binary_converter.py.
  2. On the first line, define the number variable that takes a user input:

    number = input("Convert to binary: ")

  3. Convert the input to an integer:

    # convert number to integer

    integer = int(number)

  4. Then, convert it to a binary number:

    # convert integer to binary

    binary = bin(integer)

  5. Finally, print out the value:

    print(binary)

  6. We can then run the script with the python binary_converter.py command and pass in a value to be converted. It should look something like this:
Figure 2.1: Output of running the binary_converter.py script
Figure 2.1: Output of running the binary_converter.py script

Besides these types, Python also has support for complex numbers, which comes in handy for scientific calculations that require them, such as Fourier transforms, among others. Python offers several different numeric types and provides a straightforward, intuitive process for converting between them.

Operators

In this section, we will discuss the different operators that Python makes available to us.

Arithmetic Operators

Arithmetic operators are mathematical functions that take numerical values and perform calculations on them.

Numerical data types are only as valuable as the operations that you can carry out on them. All of the Python numeric types support the following operations:

Figure 2.2: Arithmetic Operators
Figure 2.2: Arithmetic Operators

We will be demonstrating by using decimal numbers, but these operators can work on operands of any numeric type. As you've already seen, you can add numbers, as follows:

>>> 5 + 8 + 7

20

>>>

You can also carry out subtraction:

>>> 20 - 5

15

>>>

And, you can also perform multiplication:

>>> 4 * 3

12

>>>

Finally, you can perform division:

>>> 12 / 3

4.0

>>>

Note

The division of two numbers, regardless of their value types in Python, will always yield a floating point number.

Floor division is different from classic division, in that it always yields a whole integer. It is a division of two numbers, but the value yielded has any fractional parts discarded. Floor division is also referred to as integer division:

>>> 13 // 2 # classic division would yield 6.5

6

>>>

The modulo operation finds the remainder after the division of one number by another:

>>> 5 % 2

1

>>> 20 % 3

2

>>>

Finally, we have the exponentiation operation, which raises a number to a specified power:

>>> 5 ** 3

125

>>> 10 ** 4

10000

>>>

The difference between this method of exponentiation and using the pow function is that the pow function allows you to pass in a third argument, a divisor, which can be used to find the remainder after dividing the result (the exponentiated value) and the divisor.

Assignment Operators

Aside from the = simple assignment operator, Python has other assignment operators. These are shorthand variations of simple operators, in that they not only do an arithmetic operation but also reassign the variable. The following table lists all of the assignment operators:

Figure 2.3: Assignment Operators
Figure 2.3: Assignment Operators

The following is an example of these operators in action. x is initially assigned to 10. We add 1 and then reassign x to the result of that operation, 11:

>>> x = 10

>>> x += 1

>>> print(x)

11

>>>

The preceding code is equivalent to the following:

>>> x = 10

>>> x = x + 1

>>> print(x)

11

>>>

The same principle is applicable for all of the operators that are listed in the preceding table.

You can perform all arithmetic operations in Python. All operators can be applied to all numeric types. Python also provides assignment operators as a shorthand way of performing an operation and assignment in one statement.

Order of Operations

The order of operations is the collection of rules about which procedures should be evaluated first when evaluating an expression.

In Python, the order in which operators are evaluated is just as it is mathematically: PEMDAS.

Parentheses have the highest precedence. Expressions inside parenthesis are evaluated first:

>>> (9 + 2) * 2

22

>>>

Next, the exponentiation operator is given the second highest precedence:

>>> 2 ** 3 + 2

10

>>>

Multiplication and division (including floor division and the modulo operation) have the same precedence. Addition and subtraction come next:

>>> 8 * 3 + 1

25

>>> 24 / 6 - 2

2

>>> 7 + 5 - 3

9

In cases where two operators have the same precedence (for example, addition and subtraction), statements are evaluated left to right:

>>> 7 - 5 + 4

6

>>> 10 / 5 * 3

6.0

The exception to the preceding rule is with exponents, which are evaluated from the right-most value. In the following example, the evaluation is equivalent to 2^(3^2):

>>> 2**3**2

512

Let's go over what we have learned in this section before moving ahead:

  • Python supports different numeric types: integers, floating point numbers, and binary, hexadecimal, and octal numbers, to name but a few.
  • Python also supports complex numbers.
  • Multiple operators can be applied to these different types of numbers.
  • Assignment operators carry out the operation and reassign the variable to the result.
  • Arithmetic operators in Python follow the standard order of operations in mathematics: PEMDAS.

Activity 7: Order of Operations

In this activity, we will try to get conversant with the order of arithmetic operators in Python. Rewrite the following equation as a Python expression and get the result of the equation:

Figure 2.4: Activity Equation
Figure 2.4: Activity Equation

Python follows the mathematical rules that you're accustomed to. A lot of what you'd expect to work mathematically can be intuitively tried out in Python, and will often work.

Note

Solution for this activity can be found at page 279.

Activity 8: Using Different Arithmetic Operators

Write a script that takes user input as days and converts the days into years, weeks, and days, and then prints them out. We can ignore leap years. The aim of this activity is to use different arithmetic operators to split days into years, weeks, and days.

The steps are as follows:

  1. Create a file named convert_days.py.
  2. On the first line, declare the user input. It's an integer, so cast the string.
  3. Then calculate the number of years in that set of days.
  4. Next, convert the remaining days that weren't converted to years into weeks.
  5. Then, get any remaining days that weren't converted to weeks.
  6. Finally, print everything out.
  7. We can then save and run the script.
  8. The output should look something like this:
Figure 2.5: Output of running the convert_days.py script
Figure 2.5: Output of running the convert_days.py script

Note

Solution for this activity can be found at page 279.

Strings

In this section, we will look at strings in detail.

String Operations and Methods

As we mentioned in the previous chapter, strings are a sequence of characters. The characters in a string can be enclosed in either single (') or double (") quotes. This does not make a difference. A string enclosed in single quotes is completely identical to one enclosed in double quotes:

>>> "a string"

'a string'

>>> 'foobar'

'foobar'

>>>

A double-quoted string can contain single quotes:

>>> "Susan's"

"Susan's"

>>>

A single-quoted string can also contain double quotes:

>>> '"Help!", he exclaimed.'

'"Help!", he exclaimed.'

>>>

You can also build a multiline string by enclosing the characters in triple quotes (''' or """):

>>> s = """A multiline

string"""

>>> print(s)

A multiline

string

>>> s2 = '''Also a

multiline string

'''

>>> print(s2)

Also a

multiline string

>>>

Also, as you saw in the first chapter, you can use the * operator to repeat strings:

>>> print('Alibaba and the', 'thieves ' * 40)

Alibaba and the thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves thieves

>>>

And, you can use the + operator to concatenate strings:

>>> "I " + "love " + "Python"

'I love Python'

>>>

Note

Concatenation will join the two strings just as they are, and will not add spaces; thus, we add a space at the end for each string that forms a word in the preceding example.

Python strings are immutable. This means that once they are assigned to a variable, their value cannot be changed. Consider the following:

>>> string = "flip flop"

>>> string * 8 # a spider wearing slippers

'flip flop flip flop flip flop flip flop flip flop flip flop flip flop flip flop '

Once we print the original value, we will see that the string's original value remains unchanged:

>>> print(string)

flip flop

The same is applicable for all string operations; they do not change any part of
the string:

>>> hello = "Hello "

>>> world = "World"

>>> hello + world

'Hello World'

>>> hello

'Hello '

To change the preceding string, we'd have to reassign the variable to the new string:

>>> hello = hello + world

>>> hello

'Hello World'

Indexing

Python strings can be indexed. Like most languages, the first character in the sequence in the string is at the index 0.

Consider the string Python is fun. The following is a table showing the index of each character in the string. Characters in the string are indexed in two ways - left to right, which starts at 0, and right to left, which starts at -1:

Figure 2.6: String indices
Figure 2.6: String indices

To get a character from a string, you can use the standard [] syntax:

>>> s = "Python is fun"

>>> s[0]

'P'

>>> print(s[7], s[8])

i s

>>> s[-1]

'n'

>>> s[-13]

'P'

If we try to get a character from an index that doesn't exist, Python will raise an IndexError. Here, we are trying to get a character in an index that's larger than the size of the string itself:

>>> s = "foobar"

>>> s[100]

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

IndexError: string index out of range

>>>

Slicing

Additionally, you can access characters within a range of indices in a string and get a slice/substring of that string. Slicing syntax is in the following format: string[start_index : end_index].

Note that the returned substring doesn't include the character at the end index, but instead, every character up to it:

>>> string = "championships"

>>> string[0:5]

'champ'

>>> string[5:9]

'ions'

>>> string[-5:-1]

'ship'

Python allows you to omit the start or end index when slicing a string:

>>> string = "foobar"

>>> string[3:]

'bar'

>>> string[:3]

'foo'

Here, we can see that when we pass just the start index while slicing, Python automatically slices the string up to the last index. If we pass only the end index, it slices every character, from the start of the string up to that end index.

Activity 9: String Slicing

Given the following statements, predict what the output will be:

  1. Execute the following statement:

    >>> "Living in a silent film"[5]

  2. Execute the following statement:

    >>> "[8, 9, 10]"[4]

  3. Execute the following statement:

    >>> "Don't try to frighten us with your sorcerer's ways"[13:19]

  4. Execute the following statement:

    >>> "Testing 1, 2, 3"[7:]

  5. Execute the following statement:

    >>> "A man, a plan, a canal: Panama."[:-1]

    Note

    Solution for this activity can be found at page 280.

Length

The length of a string is determined by the number of characters there are inside of it. In Python, you can get the length of a string by using the built-in len() function, which takes a string as its parameter and returns an integer. In the following example, we can see that the length of the string is 44 characters:

>>> question = "Who was the first Beatle to leave the group?"

>>> len(question)

44

>>>

An empty string would have a length of 0:

>>> empty = ""

>>> len(empty)

0

>>>

String Formatting

String formatting is important when you want to build new strings that are using existing values. Python provides several ways to format text strings. The most popular of these are string interpolation, the str.format() method, and % formatting.

String Interpolation

In Python 3.6, support for string interpolation was added. String interpolation is the process of evaluating a string that has placeholders. These placeholders can hold expressions that yield a value, which is then placed inside the string. Special kinds of strings, known as f-strings (formatted strings), are used during string interpolation. These strings are prefixed with an f to denote how they're meant to be interpreted:

>>> pie = 3.14

>>> f"I ate some {pie} and it was yummy!"

'I ate some 3.14 and it was yummy!'

>>>

Note

If you omit the f prefix, the string will be interpreted literally, as-is.

To insert the variable, we need to place curly braces that contain the expression we want to put inside the string. This can be any valid Python expression:

>>> number = 7

>>> f"{number+1} is just a number."

'8 is just a number.'

>>>

Python string interpolation provides powerful, declarative, and more intuitive formatting of your strings, compared to the other methods that Python offers. This should be the de facto way to format strings when using Python 3.6+.

Note

To read more on string interpolation, visit https://www.python.org/dev/peps/pep-0498/.

The str.format() Method

The format() method can be found on every string instance. It allows you to insert different values in positions within the string. This method works similarly to interpolation, save for the fact that you can't put expressions into the placeholders, and you have to pass in the values for insertion in the method call. The syntax for this is as follows:

>>> fruit = "bananas"

>>> "I love {}".format(fruit)

'I love bananas'

>>>

In the preceding string, we put curly braces in the positions where we want to put our values. When we call the format method, it takes that first argument (our variable, fruit), and replaces the curly braces with its value. You can also pass multiple values in.

The values can be any kind of object:

>>> age = 40

>>> years = 10

>>> string = "In {} years, I'll be {}"

>>> string.format(years, age)

"In 10 years I'll be 40"

>>>

If the Python version you're using doesn't support string interpolation, this should be the method that you use.

% Formatting

An old, deprecated way of formatting strings, which you might end up seeing in old code, is the C language style % formatting. In this method, you use the % operator to pass in values. Inside the string, you use the % character, followed by a format specifier, to declare how the value should be inserted; for example, %s for string, or %d for integers:

>>> number = 3

>>> pets = "cats"

>>> "They have %d %s" % (number, pets)

'They have 3 cats'

This method is inflexible and is harder to use correctly, and thus, it should generally be avoided.

String Methods

Aside from the format method, string instances have a couple of useful methods that can be used to transform and inspect strings. We will demonstrate a few of the common ones. You can read through the Python documentation for more information on string methods.

str.capitalize()

The str.capitalize() method returns a copy of the string with the first letter capitalized and the rest in lowercase:

>>> "HELLO".capitalize()

'Hello'

>>> "hello".capitalize()

'Hello'

str.lower()

The str.lower() method returns a copy of the string with all characters converted to lowercase:

>>> "WORLD".lower()

'world'

>>> "wOrLd".lower()

'world'

str.upper()

The str.upper() method returns a copy of the string with all characters converted to uppercase:

>>> "abcd".upper()

'ABCD'

>>> "EfGhi".upper()

'EFGHI'

>>>

str.startswith()

The str.startswith() method checks whether a string starts with the specified prefix. The prefix can contain one or more characters, and is case-sensitive. The method returns a Boolean, True or False:

>>> "Python".startswith("Py")

True

>>>

str.endswith()

The str.endswith() method is just like the startswith method, but it checks that the string ends with the specified suffix:

>>> "Python".endswith("on")

True

>>>

str.strip()

The str.strip() method returns a copy of the string with the leading and trailing characters removed. The method also takes an argument that is a string, specifying the set of characters to be removed. This method is also case-sensitive. If no arguments are passed to it, it removes all of the trailing and leading whitespaces.

This can be useful when sanitizing data:

>>> "Championship".strip("ship")

'Champion'

>>> "repair".strip("r")

'epai'

>>> " John Doe ".strip()

'John Doe'

>>>

str.replace()

The str.replace() method takes two substrings as arguments (old and new), then returns a copy of the string with all of the occurrences of the old substring replaced with the new one. Note that the method is case-sensitive:

>>> "Cashewnuts".replace("Cashew", "Coco")

'Coconuts'

>>> "Emacs".replace("Emacs", "Vim")

"Vim"

>>>

Note

There are a lot more string methods available for use. You can read through the Python documentation for more information on string methods at https://docs.python.org/3/library/stdtypes.html#str.

You don't have to remember all of the string methods off the top of your head, as you can always refer to the documentation to see what methods strings support. To do this in the interpreter, run the following command:

>>> help(str)

You should see the following output, which you can browse through:

Figure 2.7: Output of help(str)
Figure 2.7: Output of help(str)

Activity 10: Working with Strings

Write a script that converts the last n letters of a given string to uppercase. The script should take the string to convert and an integer, specifying the last n letters to convert as input from the user. You can assume that n will be a positive number.

The steps are as follows:

  1. Create a file named convert_to_uppercase.py.
  2. On the first line, request the string to convert from the user.
  3. On the next line, request for the number of last letters to convert.
  4. Next, get the first part of the string.
  5. Then, get the last part of the string, that is, the one we'll be converting.
  6. Then, concatenate the first and last part back together, with the last substring transformed.
  7. Finally, run the script with the python convert_to_uppercase.py command.

The output should look something like this:

Figure 2.8: Output of running the convert_to_uppercase.py script
Figure 2.8: Output of running the convert_to_uppercase.py script

Note

Solution for this activity can be found at page 280.

Reviewing what we have learned about strings, we should remember that the characters in a string are indexed, and you can access characters in each index. Python string indices start at 0. You can also access characters within a range of indices by slicing the string. Of the different string formatting methods that Python allows for, you should use string interpolation when using Python versions 3.6+, and the str.format() method otherwise.

Escape Sequences

An escape sequence is a sequence of characters that does not represent its literal meaning when inside of a string. An escape character tells the interpreter/compiler to interpret the next character(s) in a special way and ignore its usual meaning, thus creating an escape sequence.

In Python, the escape character is the backslash (). For example, adding inside a string will tell the interpreter to interpret a new line inside the string, instead of the literal letter n:

>>> print("Hello World")

Hello

World

>>>

You can escape quotes inside a string, so that they are not interpreted as closing quotes:

>>> 'Weekend at Bernie's'

File "<stdin>", line 1

'Weekend at Bernie's'

^

SyntaxError: invalid syntax

>>> 'Weekend at Bernie's'

"Weekend at Bernie's"

>>>

Here is the full list of valid escape sequences in Python:

Figure 2.9: Escape sequences
Figure 2.9: Escape sequences

Exercise 12: Using Escape Sequences

In this exercise, we will write a Python script that breaks down all the words of a sentence and prints each word on its own line, and will ring a bell when it's done. The goal of this exercise is to get familiar with escape sequences:

  1. Create a file named split_to_lines.py.
  2. On the first line, request the sentences to split from the user:

    sentence = input("Sentence: ")

  3. Next, replace all of the spaces in the sentence with newline characters:

    sentence = sentence.replace(" ", " ")

  4. Finally, print out the sentence and ring the terminal bell when you're done. Each word should appear on a new line:

    print(sentence, "a")

  5. You can run the script by using the python split_to_lines.py command. The output should look like this:
Figure 2.10: Output of running the split_to_lines.py script
Figure 2.10: Output of running the split_to_lines.py script

Escape sequences in strings tell the program to perform a function or command, such as inserting a new line, ignore quotes occurring in strings, prompting the terminal to emit an audible signal, and several other functions.

Let's review what we have learned about strings:

  • Strings are a sequence of characters.
  • Strings can be enclosed in either single quotes (') or double quotes (").
  • Multiline strings can be enclosed in either triple single quotes (''') or triple double quotes (""").
  • Strings are immutable
  • Characters in a string are indexed, and you can access each character by index.
  • The first element in a string is at the index 0.
  • Substrings in a string can be accessed by slicing.
  • Formatting strings allows you to insert values into a string.
  • Strings come with several handy built-in methods for transforming or inspecting the string.
  • Escape sequences in strings tell the program to perform a function or command.

Activity 11: Manipulating Strings

Write a script that counts and displays the number of occurrences of a specified word in a given excerpt. The script should request two input values from the user, that is, the excerpt and the word to search for. You can assume that the word will not occur as a substring in other words.

The steps are as follows:

  1. Create a file named count_occurrences.py.
  2. Take in the user input for the sentence and the query.
  3. Next, sanitize and format the input by removing the whitespace and converting it to lowercase.
  4. Count the occurrences of the substring.
  5. Print the results.
  6. Run the script by using the python count_occurrences.py command.

The output should look like this:

Figure 2.11: Output of running the count_occurrences.py script
Figure 2.11: Output of running the count_occurrences.py script

Note

Solution for this activity can be found at page 281.

Lists

This is part one of two regarding lists, which we will be going through in this book. This part will act as an introduction, and will not cover the various methods that list objects have, such as extend(), remove(), pop(), and several others. We will go through the second section on lists in a later chapter.

List Operations

In Python, arrays (or the closest abstraction of them) are known as lists. Lists are an aggregate data type, meaning that they are composed of other data types. Lists are similar to strings, in that the values inside them are indexed, and they have a length property and a count of the objects inside of them. In Python, lists are heterogeneous, in that they can hold values of different types. In contrast to how arrays are in most languages, Python lists are also mutable, meaning that you can change the values inside of them, adding and removing items on the go.

Lists can be likened to a wardrobe. Wardrobes can hold multiple items of clothing, clothes of different kinds, and even shoes. Wardrobes provide a convenient storage space for the easy retrieval of your clothes, and make it so that you don't have to look for them all around the house. If we didn't have a list, we'd have to keep track of dozens of separate variables. Like wardrobes, lists provide a convenient collection of related objects.

Lists are made with is comma-separated elements enclosed in square brackets; for example:

>>> digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

>>> digits

[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

>>> letters = ["a", "b", "c", "d"]

>>> letters

['a', 'b', 'c', 'd']

>>> mixed_list = [1, 3.14159, "Spring", "Summer", [1, 2, 3, 4]]

>>> mixed_list

[1, 3.14159, 'Spring', 'Summer', [1, 2, 3, 4]]

>>>

As you can see here, lists can also contain other lists within them. You can also get the number of elements in a list by using the len() function:

>>> len(["a", "b", "c", "d"])

4

>>>

Indexing

Like strings, lists can also be indexed. The first element in a list starts at the index 0:

>>> fruits = ["apples", "bananas", "strawberries", "mangoes", "pears"]

>>> fruits[3]

'mangoes'

Negative indices can be used, as well:

>>> fruits[-1]

'pears'

>>>

Slicing

Lists can also be sliced. The slicing operation always returns a new list that's been derived from the old list. The syntax remains as list[start_index : end_index ]. As with string slicing, the element at the end index isn't included in the result:

>>> my_list = [10, 20, 30, 40, 50, 60, 70]

>>> my_list[4:5]

[50]

>>> my_list[5:]

[60, 70]

>>>

Omitting the end index and providing only the start index will slice everything from the start to the end of the list, while omitting the start index and giving only the end index will slice everything from the start index to the end index:

>>> my_list = [10, 20, 30, 40, 50, 60, 70]

>>> my_list[5:]

[60, 70]

>>> my_list[:4]

[10, 20, 30, 40]

>>>

Concatenation

Additionally, you can add two lists together by using the + operator. The elements of all of the lists being concatenated are brought together inside one list:

>>> [1, 2, 3] + [4, 5, 6]

[1, 2, 3, 4, 5, 6]

>>> ["a", "b", "c"] + [1, 2.0, 3]

['a', 'b', 'c', 1, 2.0, 3]

>>>

Changing Values in a List

Since lists are mutable, you can change the value in a list by assigning whatever is at that index:

>>> names = ["Eva", "Keziah", "John", "Diana"]

>>> names[2] = "Jean"

>>> names

['Eva', Keziah, 'Jean', 'Diana']

>>>

Note that it's possible to add any type of value to a list, regardless of what types of values it contains. For example, you can add an integer to a list of strings or a string to a list of integers, and so on.

You can also use the list.append() method to insert a value at the end of a list:

>>> planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]

>>> planets.append("Planet X")

>>> planets

['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Planet X']

Finally, you can assign slices of a list. This replaces the target slice with whatever you assign, regardless of the initial size of the list:

>>> alphanumeric_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

>>> alphanumeric_list[4:7]

[5, 6, 7]

>>> alphanumeric_list[4:7] = ["a", "b", "c"]

>>> alphanumeric_list

[1, 2, 3, 4, 'a', 'b', 'c', 8, 9, 0]

An important thing to note is that when you assign a list, it points it to an object in the memory. If you assign another variable to the variable that references that list, the new variable also references that same list object in the memory. Any changes made using either reference will always change the same list object in the memory.

Exercise 13: List References

In this exercise, we will see how list references work:

  1. Create a new list, as follows:

    >>> list_1 = [1, 2, 3]

  2. Then, assign a new variable, list_2, to list_1:

    >>> list_2 = list_1

  3. Any changes that we make to list_2 will be applied to list_1. Append 4 to list_2 and check the contents of list_1:

    >>> list_2.append(4)

    >>> list_1

    [1, 2, 3, 4]

  4. Any changes that we make to list_1 will be applied to list_2. Insert the value a at index 0 of list_1, and check the contents of list_2:

    >>> list_1[0] = "a"

    >>> list_2

    ['a', 2, 3, 4]

    >>>

This is because both variables reference the same object.

Note

We will be covering lists in further depth in Chapter 5, Lists and Tuples.

We've seen that lists are collections of values. Python lists are mutable. There are multiple operations that you can carry out on lists, such as accessing elements by index, slicing elements, getting the count of elements inside a list, concatenation, and changing values, either by index, appending, or replacing slices of the list.

Activity 12: Working with Lists

Write a program that fetches the first n elements of a list.

The steps are as follows:

  1. Create a script named get_first_n_elements.py.
  2. On the first line, create the array.
  3. Next, print the array out and fetch the user input for the number of elements to fetch from the array.
  4. Finally, print out the slice of the array from the first element to the nth element.
  5. Then, run the script by using the python get_first_n_elements.py command.

The output should look like this:

Figure 2.12: Output of running the get_first_n_elements.py script
Figure 2.12: Output of running the get_first_n_elements.py script

Note

Solution for this activity can be found at page 282.

Booleans

Boolean data types are values that can only be one of two values, True or False. For example, the proposition 100 is more than 5 is True, and thus, it would have a True Boolean value. On the other hand, the proposition The sky is green is False, and thus, it would have a False Boolean value.

Booleans are largely associated with control statements, as they change the flow of the program, depending on the truthfulness of the specified quantities.

In Python, True and False are used to represent the two Boolean constants:

>>> True

True

>>> False

False

>>> print(type(True), type(False))

<class 'bool'> <class 'bool'>

We can see that the type of each expression is bool (short for Boolean). Like all other types, Booleans have operators that you can apply.

Comparison Operators

Comparison operators compare the values of objects or the objects, identities themselves. The objects don't need to be of the same type. There are eight comparison operators in Python:

Figure 2.13: Comparison operators
Figure 2.13: Comparison operators

The following are some example uses:

>>> 10 < 1

False

>>> len("open") <= 4

True

>>> 10 > 1

True

>>> len(["banana"]) >= 0

True

>>> "Foobar" == "Foobar"

True

>>> "Foobar" != "Foobar"

False

>>>

Now, consider the following code:

>>> l = [1, 2, 3]

>>> l2 = l

>>> l is l2

True

>>> l is not None

True

>>>

Here, we create a list, l, and then assign the variable l2 to that same list. This creates a reference for the list. Thus, the statement l is l2 is True, since both variables reference the same object in the memory.

The statement l is not None evaluates to True, as well, since l points to something in the memory, and therefore, it isn't null. None is the Python equivalent of null.

Logical Operators

We use logic in everyday life. Consider the following statements:

  • I'll have juice OR water if there isn't any juice.
  • The knife has to be sharpened AND polished for the chef to use it.
  • I am NOT tired; therefore, I will stay awake.

Each of these statements has a condition. The condition for having water is if there isn't any juice available. The chef will only use the knife if two conditions are met, that is, that it is sharpened and that it is polished. The condition for staying awake is only if the condition of being tired has not been met.

In the same way, we have logical operators that combine Boolean expressions in Python: not, and, and or, as described in the following table:

Figure 2.14: Logical operators
Figure 2.14: Logical operators

and is a short-circuit operator, in that it only evaluates the second argument if the first one is True. or is also a short-circuit operator, in that it will only evaluate the second argument if the first one is False.

The following is an example of and:

>>> fruits = ["banana", "mangoes", "apples"]

>>> wants_fruits = True

>>> len(fruits) > 0 and wants_fruits

True

>>>

The following code shows or in action:

>>> value_1 = 5

>>> value_2 = 0

>>> value_1 > 0 or value_2 > 0

True

>>>

Finally, the following is an example of not:

>>> not True

False

>>> not False

True

>>>

Membership Operators

The operators in and not in test for membership. All sequences (for example, lists and strings), support this operator. For lists, these operators go through each element to see whether the element being searched for is within the list. For strings, the operators check whether the substring can be found within the string. The return values for these operators are True or False.

Let's see how they work:

>>> numbers = [1, 2, 3, 4, 5]

>>> 3 in numbers

True

>>> 100 in numbers

False

>>> sentence = "I like beef, mutton and pork"

>>> "chicken" not in sentence

True

>>> "beef" not in sentence

False

>>>

Boolean data types are values that can be either True or False. You can compare the values of two objects by using comparison operators, and you can combine or alter Boolean expressions by using logical operators. Membership operators are used to assert whether an element can be found in a sequence or container type object.

Activity 13: Using Boolean Operators

Insert the appropriate Boolean operators in the following condition statements, so that the code in the block executes. This will help us practice using Boolean operators:

  1. Consider the following code block:

    n = 124

    if n % 2 ? 0:

    print("Even")

  2. Consider the following code block:

    age = 25

    if age ? 18:

    print("Here is your legal pass.")

  3. Consider the following code block:

    letter = "b"

    if letter ? ["a", "e", "i", "o", "u"]:

    print(f"'{letter}' is not a vowel.")

    Note

    Solution for this activity can be found at page 282.

Summary

In this chapter, we took an in-depth look at the basic data types that Python supports. We started with numerical data types and their related operators. We then covered strings and looked at string indexing, slicing, and formatting. Then, we moved on and took a brief look at lists (also known as arrays) and Booleans, as well as Boolean operators.

In the next chapter, we will begin our journey into learning how to control the flow of our programs by using control statements and loops.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.97.40