Skip to main content

Introduction to Computer Programming with Python: Chapter 2. Essential Building Blocks of Computer Programs

Introduction to Computer Programming with Python
Chapter 2. Essential Building Blocks of Computer Programs
  • Show the following:

    Annotations
    Resources
  • Adjust appearance:

    Font
    Font style
    Color Scheme
    Light
    Dark
    Annotation contrast
    Low
    High
    Margins
  • Search within:
    • Notifications
    • Privacy
  • Project HomeIntroduction to Computer Programming with Python
  • Learn more about Manifold

Notes

table of contents
  1. Cover
  2. Title Page
  3. Copyright Page
  4. Contents
  5. Chapter 1 Introduction
    1. Learning Objectives
    2. 1.1 A Brief History of Computers
    3. 1.2 Fundamentals of Computing and Modern Computers
      1. Number Systems and the Foundation of Computing
      2. Computability and Computational Complexity
      3. The Construction of Modern Computers
        1. Analog Computers
        2. Digital Computers
        3. Mechanic-Based Components
        4. Vacuum Tube–Based Components
        5. Transistors
        6. Integrated Circuits and Very Large-Scale Integrated Circuits
    4. 1.3 Programming and Programming Languages
    5. 1.4 Python Programming Language
      1. The Development and Implementation of Python
      2. Advantages of Python
      3. Resources for Python and Python Education
    6. 1.5 Getting Ready to Learn Programming in Python
      1. Installing and Setting Up the Python Programming Environment
        1. Installing Python
        2. Setting Up a Virtual Environment for a Python Project
        3. Installing Jupyter Notebook
        4. Installing Visual Studio Code
      2. Additional Tools Supporting Software Development in Python
        1. Buildbot
        2. Trac
        3. Roundup
    7. 1.6 Getting a Taste of Programming with Python
      1. Program Interactively with Python Interactive Shell
      2. Program with VS Code IDE
      3. Use Jupyter Notebook Within VS Code to Program Interactively
      4. Write Documentation in Markdown
        1. Headings
        2. Paragraphs
        3. New Lines
        4. Italic, Bold, and Strikethrough Texts
        5. Horizontal Rules
        6. Keyboard Keys
        7. Unordered Lists
        8. Ordered Lists
        9. Definition Lists
        10. Links
        11. Links to Internal Sections
        12. Images
        13. Blockquotes
        14. Tables
        15. Inline Program / Script Code
        16. Code Block
        17. Mathematical Formulas and Expressions
        18. To-Do List
        19. Escape Sequence for Special Characters
      5. Programming Interactively with Jupyter Notebook Within VS Code
      6. Run Python Programs Outside IDE
      7. Make the Python Program File Executable
      8. Errors in Programs
    8. 1.7 Essentials of Problem Solving and Software Development
      1. Design Algorithms to Solve Problems
      2. Phases of Software System Development
        1. Phase 1. Understand the Project
        2. Phase 2. Analyze the Requirements to Identify Computer-Solvable Problems and Tasks
        3. Phase 3. Design the System
        4. Phase 4. Implement the System
        5. Phase 5. Test the System
        6. Phase 6. Maintain the System
    9. 1.8 Manage Your Working Files for Software Development Projects
      1. Set Up Git on Your Computer and Version-Control Locally
      2. Set Up an Account on GitHub and Version-Control with Remote Repositories
    10. Chapter Summary
    11. Exercises
    12. Projects
  6. Chapter 2 Essential Building Blocks of Computer Programs
    1. Learning Objectives
    2. 2.1 Primary Constructs of Computer Programs in Python
      1. Vocabulary of the Programming Language
        1. Rules of Naming Identifiers
        2. Python Naming Conventions
        3. Names with Leading and/or Trailing Underscores
        4. Rules of Scope Resolution for Identifiers
      2. Simple Data Types
        1. Signed Integers (int)
        2. Float (float)
        3. Boolean (bool)
        4. Complex (complex)
      3. Compound Data Types
        1. String (str)
        2. List
        3. Tuple
        4. Set
        5. Dictionary
        6. Object
      4. Variables and Constants
        1. Variables
        2. Built-In Constants
      5. Operators
        1. Arithmetic Operators
        2. Comparison Operators
        3. Logical Operators
        4. Bitwise Operators
        5. Assignment Operators
        6. Identity Operators
        7. Sequence Operators
        8. Membership Operator
      6. Built-In Functions
      7. Expressions
    3. 2.2 Higher-Level Constructs of Python Programs
      1. Structure of Python Programs
      2. Documentation and Comments
      3. Simple Statements
        1. Expression Statement
        2. Assignment Statement
        3. print Statement
        4. input Statement
        5. assert Statement
        6. pass Statement
        7. del Statement
        8. return Statement
        9. open Statement
        10. yield Statement
        11. raise Statement
        12. break Statement
        13. continue Statement
        14. import Statement
        15. global Statement
        16. nonlocal Statement
        17. help Statement
      4. Compound Statements
        1. Code Blocks
        2. Rules of Indentation
        3. Rules of Spacing
        4. if Statement
        5. if-else Statement
        6. if-elif Statement
        7. if-elif-else Statement
        8. while Statement
        9. for Statement
        10. def Statement
        11. class Statement
        12. try-except Statement
        13. with Statement
    4. Chapter Summary
    5. Exercises
    6. Projects
  7. Chapter 3 Flow Control of Statements
    1. Learning Objectives
    2. 3.1 Selective with the if Statement
    3. 3.2 Single-branch selective with if Statement
    4. 3.3 Multiple-Branch Selective with if-elif-… and if-elif-…-else Statements
    5. 3.4 Iterate with for Statement
      1. Using break and continue Statements and an else Clause Within Loops
      2. Common Coding Mistakes with the for Loop
    6. 3.5 Iterate with the while Statement
      1. Common Coding Mistakes with a while Loop
    7. 3.6 Iterate with for Versus while
    8. Chapter Summary
    9. Exercises
    10. Projects
  8. Chapter 4 Handle Errors and Exceptions in Programs
    1. Learning Objectives
    2. 4.1 Errors in Your Programs
      1. Exception
      2. ArithmeticError
      3. OverflowError
      4. ZeroDivisionError
      5. FloatingPointError
      6. AssertionError
      7. AttributeError
      8. BufferError
      9. EOFError
      10. GeneratorExit
      11. ImportError
      12. IndexError
      13. KeyError
      14. KeyboardInterrupt
      15. MemoryError
      16. ModuleNotFoundError
      17. NameError
      18. NotImplementedError
      19. OSError
      20. BlockingIOError
      21. ChildProcessError
      22. ConnectionError
      23. BrokenPipeError
      24. ConnectionAbortedError
      25. ConnectionRefusedError
      26. ConnectionResetError
      27. FileExistsError
      28. FileNotFoundError
      29. IsADirectoryError
      30. NotADirectoryError
      31. PermissionError
      32. ProcessLookupError
      33. TimeoutError
      34. RecursionError
      35. ReferenceError
      36. RuntimeError
      37. StopIteration
      38. StopAsyncIteration
      39. SyntaxError
      40. IndentationError
      41. TabError
      42. SystemError
      43. SystemExit
      44. TypeError
      45. UnboundLocalError
      46. UnicodeError
      47. UnicodeEncodeError
      48. UnicodeDecodeError
      49. UnicodeTranslateError
      50. ValueError
    3. 4.2 Handling Runtime Errors and Exceptions
    4. Chapter Summary
    5. Exercises
  9. Chapter 5 Use Sequences, Sets, Dictionaries, and Text Files
    1. Learning Objectives
    2. 5.1 Strings
      1. Methods of Built-In Class str
      2. Built-In Functions and Operators for Strings
      3. Constructing and Formatting Strings
      4. Regular Expressions
    3. 5.2 Lists
    4. 5.3 Tuples
    5. 5.4 Sets
    6. 5.5 Dictionaries
    7. 5.6 List, Set, and Dictionary Comprehension
      1. List Comprehension
      2. Set Comprehension
      3. Dictionary Comprehension
    8. 5.7 Text Files
      1. Opening and Closing a File
      2. Write or Append to a File
      3. Reading from a File
      4. Update Existing Content of a Text File
      5. Deleting Portion of a Text File
    9. Chapter Summary
    10. Exercises
    11. Projects
  10. Chapter 6 Define and Use Functions
    1. Learning Objectives
    2. 6.1 Defining and Using Functions in Python
    3. 6.2 Parameters and Arguments in Functions
    4. 6.3 Recursive Functions
    5. 6.4 Anonymous Functions: lambda Expressions
    6. 6.5 Special Functions: Mapping, Filtering, and Reducing
      1. Mapping
      2. Filtering
      3. Reducing
    7. 6.6 Generators: Turning a Function into a Generator of Iterables
    8. 6.7 Closures: Turning a Function into a Closure
    9. 6.8 Decorators: Using Function as a Decorator in Python
    10. 6.9 Properties of Functions
    11. Chapter Summary
    12. Exercises
    13. Projects
  11. Chapter 7 Object-Oriented Programming with Python
    1. Learning Objectives
    2. 7.1 Introduction to Object-Oriented Programming (OOP)
      1. Abstraction
      2. Information Hiding or Data Encapsulation
      3. Inheritance
    3. 7.2 Defining and Using Classes in Python
      1. Inheritance: Subclass and Superclass
      2. Public, Private, and Protected Members of a Class
      3. Class Methods
      4. Static Methods
      5. Class Attributes
    4. 7.3 Advanced Topics in OOP with Python
      1. Dunder Methods in Class Definition
      2. Using Class as Decorator
      3. Built-In Property() Function and Property Decorator
      4. Creating a New Class Dynamically and Modify a Defined Class or Instance
      5. Keeping Objects in Permanent Storage
    5. Chapter Summary
    6. Exercises
    7. Project
  12. Chapter 8 Modules and Packages
    1. Learning Objectives
    2. 8.1 Creating Modules and Packages
    3. 8.2 Using Modules and Packages
    4. 8.3 Install and Learn About Modules Developed by Others
    5. 8.4 Module for Generating Random Numbers
      1. Functions for Bookkeeping
      2. Functions for Generating Random Integers
      3. Functions for Randomly Generating Float Numbers
      4. Functions for Randomly Selected Item(s) from Sequences
    6. 8.5 Module for Mathematical Operations
    7. 8.6 Modules for Time, Date, and Calendar
      1. The Datetime Module
      2. The Time Module
      3. The Calendar Module
    8. 8.7 Modules for Data Representation and Exchange
    9. 8.8 Modules for Interfacing Operating Systems and Python Interpreter
      1. OS Module for Interacting with the Operating System
      2. The path Submodule from os for Manipulating File Paths
      3. The sys Module for Interaction Between the Python and Python Interpreter or Python Virtual Machine (PVM)
    10. 8.9 Module for Logging Events During Program Runtime
    11. 8.10 Modules for Playing and Manipulating Audio and Video Files
      1. winsound
      2. PyGame
    12. 8.11 Modules for Creating and Manipulating Graphics and Images
      1. Create Graphics with Tkinter
      2. Manipulate Images with Pillow
    13. 8.12 Modules for Data Analytics
    14. Chapter Summary
    15. Exercises
    16. Projects
  13. Chapter 9 Develop GUI-Based Applications
    1. Learning Objectives
    2. 9.1 Terminal-Based Applications Versus GUI-Based Applications
    3. 9.2 Designing and Developing GUI-Based Applications in Python
      1. Tkinter Module
      2. tkinter.ttk—Tk-Themed Widgets
    4. Chapter Summary
    5. Exercises
    6. Projects

Chapter 2 Essential Building Blocks of Computer Programs

This chapter introduces the fundamental elements and building blocks of computer programs in the Python language. These fundamental building blocks include the words, keywords, and reserved words that can be used in Python programs. You will also learn the primary data types and data models, the operators, and some built-in functions that can be applied to the data and data models in Python, as well as some important statements or sentences that can be used to instruct computers.

Learning Objectives

After completing this chapter, you should be able to

  • • make and use names correctly to identify various items in your Python programs.
  • • use different types of data and data models correctly.
  • • use the proper operators for different types of data and data models.
  • • correctly compose expressions using variables, data, operators, and the built-in functions of Python.
  • • write an assignment statement to assign values to variables.
  • • write augmented assignment statements.
  • • write input statements correctly to get input from users.
  • • write correct statements using print.

2.1 Primary Constructs of Computer Programs in Python

Computer programs tell computers how to complete specific tasks. These specific tasks may be as small as what you would do on a calculator or as big as mission control for space exploration. Believe it or not, computer programs for all these different tasks are composed of the same types of statements on the same types of primary data. The difference is in how the data are structured and how the statements are organized. In computing, the study of the first “how” is the subject of data structures, whereas the study of the second “how” is the subject of algorithms. In computing, there are dedicated courses providing in-depth coverage on data structures and algorithms. While studying introductory computer programming, keep in mind the importance of data and algorithms in solving problems and try to identify the data involved and describe the algorithms needed to solve a problem using the methods introduced in 1.7.

Vocabulary of the Programming Language

Vocabulary is the foundation of any language. In computer languages, identifiers are an important part of the vocabulary used to write computer programs. As in all programming languages, identifiers in Python are used to identify variables, functions and methods, classes, objects, and modules. They are called identifiers because, for computers, the only purpose of these names is to identify specific locations of computer memory that hold or can be used to hold specific data or code blocks.

Figure 2-1 illustrates how a variable named “grade” is identified as the memory location that holds the integer 98. Please note that we use 98 in the diagram for illustration purposes, although, in fact, both data and program codes are stored as sequences of binary (0s and 1s).

“Grade” is in a small rectangle connected by a line to a larger shape that contains “98” in a rectangle within it.

Figure 2-1: The variable “grade” and its memory location

Although an identifier in computer programs does not need to be meaningful to humans, it must be unique in a given context, which is often called namespace. In Python, a namespace is a mapping from names to objects and is implemented as a Python dictionary.

In a program, different identifiers may be used to refer to the same memory location and hold the same data or program code, as shown in Figure 2-2. This is accomplished through the following Python code:

In [ ]:

x = 'John'

y = x

Out [ ]:

John

To check what x and y hold, we use the print statement as follows:

In [ ]:

print('x holds ', x, ', y holds', y)

Out [ ]:

x holds John, y holds John

“X” and “Y” are in separate squares. John is in the center of a larger shape. Two arrows point to John: a blue one from “X” & an orange one from “Y.”

Figure 2-2: X and Y point to the same memory location

If we change one identifier to refer to something else, the value referred to by the other identifier will remain the same, as shown in Figure 2-3. This is done with the following code:

In [ ]:

x = 'Smith'

print('x holds ', x, ', y holds ', y)

Out [ ]:

x holds Smith, y holds John

“X” and “Y” are in separate squares. A blue arrow points from “X” to Smith; an orange arrow points from “Y” to John. Both names are in a larger shape.

Figure 2-3: Now X and Y point to different memory locations

Please note that in the examples above and other examples in the remainder of the textbook, the box behind In [ ] represents a code cell in Jupyter Notebook, whereas everything behind Out [ ] is the output from the code contained in the code cell when you press Shift+Enter or click the play button.

Rules of Naming Identifiers

In addition to uniqueness, identifiers used in Python programs must be named according to the following rules:

  1. 1. An identifier can be a combination of letters (a–z, or A–Z), numbers (0–9), and underscores (_).
  2. 2. It must begin with a letter (a–z or A–Z) or underscore (_).
  3. 3. In Python, identifiers are case-sensitive, so x and X are different identifiers.
  4. 4. Identifiers can be of any length.
  5. 5. User-defined identifiers cannot be the same as words reserved by the Python language.

According to these rules, the following are legitimate user-defined identifiers in Python:

AB, zf, cd, hz, d_2, c5E, falling, to_be

Whereas the following are not:

1d, d/, f-, g.d

In Python, identifiers shown in Table 2-1 are reserved and hence called reserved words or keywords, with predefined special meaning in the language, which means that you must not use them to name your variables, functions/methods, classes, or modules.

Table 2-1: Reserved words in the Python programming language

Reserved word

Special meaning

Reserved word

Special meaning

and

logical and

if

conditional statement

as

used together with import and with to create new alia

import

to import modules

assert

to make an assertion for handling possible errors

in

membership test

break

to get out of some code blocks such as during iteration

is

identity test

class

to define class

lambda

to create a lambda function

continue

to omit the rest of the code block and continue the loop

not

logic negation

def

to define functions

or

logical or

del

to delete an object

pass

to pass the code block

elif

used together with if to create a conditional statement

print

to output

else

used together with if to create a conditional statement

raise

to raise an exception intentionally

except

used together with try to handle errors

return

to return values from a function in function definition

exec

to execute some dynamically generated code in a string or object

try

used for exception handling

finally

used together with try and except to handle errors

while

to make loop/iteration statements

for

to create a loop

with

to introduce context for a code block

from

used together with import

yield

used in place of return, to turn a function into a generator

global

to access a global variable from inside of a function

In addition to the reserved words in Table 2-1, you should also avoid using names that have been used by Python for built-in types and built-in functions, classes, and modules. These names are collectively called built-in names. It is grammatically fine to use built-in names as user-defined identifiers, but using them may cause confusion.

Furthermore, Python also uses the underscore _ as an identifier for a very special variable to hold the result of the last evaluation when Python is running in interactive mode, as shown in the following example:

>>> sum ([1,2,3,4,5,6])

21

>>> sum (list(range(1000)))

499500

>>> _

499500

>>> |

This use of _ as a special variable can also be seen in Jupyter Notebook, as shown in the following example:

In [ ]:

pow(9, 3)

Out [ ]:

729

In [ ]:

_

Out [ ]:

729

When Python is not running in interactive mode, _ has no predefined meaning, however. Even within Jupyter Notebook, the value of _ is often unpredictable unless explicitly assigned.

Syntactically, the special variable _ can be used in the same way as others, especially when the value is to be thrown away and not used, as shown below:

In [ ]:

p, n = 1, 10   # assign 1 to variable p, and assign 10 to variable n

for _ in range(n):   # note that _ is not used elsewhere

  p *= 2

print(f'2^{n} = {p}')   # format the output with f-string

Out [ ]:

2^10 = 1024

Python Naming Conventions

Although identifiers used in Python programs don’t have to be meaningful to humans, you should always try to use more meaningful identifiers in your programs because it is not only easy for you to tell what the identifiers are used for but also easier for other programmers to understand your programs when you work in a team or want to share your code with others.

For the same reason, you should also follow common practices and widely accepted coding conventions when programming. In terms of composing identifiers these conventions include:

  1. 1. Lower case identifiers are usually used for variables and function names.
  2. 2. Capitalized identifiers are used for class names.
  3. 3. Upper case identifiers are used for constants, such as PI = 3.1415926, E = 2.7182, and so on.
  4. 4. When an identifier has multiple words, the underscore _ is used to separate the words. So we use your_name instead of yourname, use to_be instead of tobe. Some programmers prefer not to use an underscore, but to capitalize each word, except for the first word, when an identifier is used as a variable or the name of a function or method.

Along with the programming technologies, these practices and conventions have developed over the years and may further evolve in the future. A good Python programmer should follow the developments and trends of the Python programming community.

Names with Leading and/or Trailing Underscores

As mentioned above, identifiers for variables, function/method names, and class names may begin and/or end with a single underscore, double underscores, or even triple underscores, and those names may have special meanings.

When a name has both leading and trailing double underscores, such as __init__, it is called a dunder (double-underscore) name. Some dunder names have been given special meanings in Python Virtual Machine (PVM) or a Python interpreter. They are either reserved as special variables holding special data or as special function/method names.

The following are some special dunder names used as special values or special variables holding special data.

__main__

Used as a special value. When a Python program/script file runs as the main program other than a module, the special variable __name__ will be assigned special value __main__.

__name__

Used as a special variable in a Python program to hold special value indicating how the program file is called or used. If the program file is used as the main program, __name__ will hold __main__. If it is used as a module, __name__ will hold the name of the module.

__package__

Used as a special variable to hold the package’s name if a module imported is a package. Otherwise, __package__ will hold an empty string.

__spec__

Used as a special variable to hold the module specification used when the module is imported. If the Python program file is not used as a module, it will hold the special value None.

__path__

Used as a special variable to hold the path to the module in a package. If the module is not within a package, __path__ is not defined.

__file__

Used as a special variable to hold the name of a Python program file.

__cached__

A special variable often used together with the special variable __file__, referring to a precompiled bytecode. If the precompiled bytecode is not from a program file, __file__ is not defined.

__loader__

Used as a special variable to hold the object that loads or imports the module so that you would know who is using the module.

__doc__

Used as a special variable to hold the documentation of a module or Python program if it is used as the main program, documentation of a class, or function or method of a class.


Dunder names used for special functions and methods will be discussed in Chapter 6 and Chapter 7.

Rules of Scope Resolution for Identifiers

Big programs for complicated applications often use hundreds or even thousands of identifiers to name variables, functions, classes, and other objects. When so many names are used, it is unavoidable that some names will be used more than once. How can we ensure in a program that each name can be mapped to an object without confusion and ambiguity? The answer is to follow the LEGB rule, in which L, E, G, and B refer to different scopes from small to big: L is for local, referring to the inside of a function or class; E is for enclosed, referring to the inside of a function enclosing another function; G is for global, referring to the space outside of all classes and function in a Python program file; and B is for built-in, referring to all the names defined within Python’s built-in module. The relationships of LEGB scopes are illustrated in Figure 2-4.

Four concentric rectangles represent the scopes of the rule. The center rectangle (local) is white, followed by gray, orange, and blue rectangles.

Figure 2-4: LEGB rules for scope resolution for names

The illustration above should be viewed in reference to a name used within a function or class. To resolve the name or to link it to a specific object, apply the following LEGB rules:

  1. 1. Look at the names defined locally (L) within the function/method or class. If not defined, proceed to the next rule.
  2. 2. Check whether the name has been defined in the enclosure (E) function (note that enclosures are not often used, so this is just for discussion right now). If not, proceed to the next rule.
  3. 3. Check whether it has been defined globally (G).
  4. 4. Check whether it is a built-in (B) name of Python.

The following sample shows how matching local and global names are resolved:

In [ ]:

g_name = 'John'   # global name g_name

l_name = 'Smith'   # global name l_name

def display_names():   # define a function

  l_name = input('What is your name:')   # get input

  print(f'Local name is {l_name}')   # l_name is defined again

  print(f'Global name is {g_name}')   # g_name is global

display_names()

Out [ ]:

What is your name: Kevin

local name is Kevin

Global name is John

You may have noted in the example above that variable l_name is defined both locally in definition of the function display_names() and globally. When it is used within the function, its local definition is used; variable g_name, on the other hand, is only defined globally, and when it is used within the function, it is resolved to its global definition.

In addition to the LEGB rules, please keep in mind the following:

  1. 1. A local name defined in a function will not be seen anywhere outside the function.
  2. 2. A local name defined in a class can be seen outside the class or its objects if the name is not a private member of the class, with an explicit reference to the name with dot notation. For example, a name X defined in class C can be accessed using C.X, or O.X if O is an object of C.
  3. 3. A name Nx globally defined in a Python script file named M1.py can be seen inside another Python script file by either importing the name explicitly from M or by importing M1 as a whole and using dot notation M1.Nx to access Nx.

Simple Data Types

Computers solve problems and accomplish various tasks by processing information. This information is represented in the form of data. It is important to know what data we can use or process and what operations we can apply to different types of data. In Python, there are simple data types and compound data types. The latter are also called models of data.

Simple data types include numbers, strings, and Boolean values. Numbers are used to represent numerical information, strings are used to represent literal information, and Boolean values are used to represent the result of tests, either True or False.

In Python, numbers can be signed integers, float numbers, and complex numbers. They all can be values of variables, as we shall see in the next section.

Although a string can be used conveniently as simple data, it has all the properties and supported operations of a compound data type. As such, it will be discussed in full detail later in this section.

Signed Integers (int)

Signed integers in Python are …−2, −1, 0, 1, 2…, as examples. In Python 3, signed integers can be of arbitrary size, at least theoretically, as long as computer memory is not exhausted. In implementation, however, the biggest integer is defined by sys.maxsize, a variable named maxsize in a module called sys, which specifies the maximum number of bytes that can be used to represent an integer number. The notation of sys.maxsize here means maxsize, defined in module sys.

Operations on integer numbers include the following:

  • addition (x + y)
  • subtraction (x − y)
  • multiplication (x * y)
  • division (x / y)
  • negation (−x)
  • exponentiation (x ** y)
  • modular (x % y)
  • integer division (x // y)

You should be able to use the above operations, which you should already be familiar with, as well as the following bitwise operations you may never have heard about:

  • bitwise or (x | y)
  • >>> 1 | 4
  • 5
  • bitwise exclusive or, often called XOR (x ^ y)
  • >>> 1 ^ 2
  • 3
  • bitwise and (x & y)
  • >>> 1 & 5
  • 1
  • shifted left (x << n)
  • >>> 2 << 3
  • 16
  • shifted right (x >> n)
  • >>> 256 >> 5
  • 8
  • invert (~x)
  • >>> ~128
  • -129

The following are a few more samples from the Python interactive shell that show how these operators are used:

>>> 12 + 23

35

>>> 35 - 12

23

>>> -123

-123

>>> 123 * 567

69741

>>> 69741/123   # the result is a real or float-point number

567.0

>>> 69741//123   # get the quotient of two integers

567

>>> 69741%12   # operation % will get the remainder

9

The next few examples are about bitwise operations. The first two operations on the first line show the binary form of the two numbers. In Python, you can have two or multiple statements on a single line, but you are not encouraged to do so.

>>> bin(123); bin(567)   # how to have two or more statements on one line

'0b1111011'

'0b1000110111'

>>> bin(123 | 567)   # it will be 0001111011 | 1000110111

'0b1001111111'

>>> bin(123 ^ 567)   # it will be 0001111011 ^ 1000110111

'0b1001001100'

>>> bin(123 & 567)   # it will be 0001111011 & 1000110111

'0b110011'

>>> bin(123 << 5)   # it will be 1111011 << 5

'0b111101100000'

>>> bin(123 >> 5)   # it will be 1111011 >> 5

'0b11'

>>> bin(~123)

'-0b1111100'

There are also many built-in functions available for operations on integers. All the built-in functions of Python will be discussed in detail below.

In addition, the following methods are also available to use for operations on integer objects.

n.bit_length()

This returns the number of necessary bits representing the integer in binary, excluding the sign and leading zeros.

>>> n = -29

>>> print(f'Binary string of {n} is {bin(n)}')

binary string of -29 is -0b11101

>>> print(f'# of significant bits of {bin(n)} is {n.bit_length()}')

# of significant bits of -0b11101 is 5

n.to_bytes(length, byteorder, *, signed=False)

This returns an array of bytes representing an integer, where length is the length of bytes used to represent the number. byteorder can take Big-Endian or Little-Endian byte order, depending on whether higher-order bytes (also called most significant) bytes come first or lower-order bytes come first, and an optional signed argument is used to tell whether 2’s complement should be used to represent the integer.

>>> n = 256

>>> n.to_bytes(2, byteorder = 'big') # big means higher bytes first

b'\x01\x00'

Recall that modern computers use 2’s complements to represent negative numbers. So if the integer n is negative while signed remains False, an OverflowError will be raised, as shown below:

>>> n = -23567

>>> n.to_bytes(3, 'big')

OverflowError Traceback (most recent call last)

<ipython-input-4-66989275e22d> in <module>

1 n = -23567

----> 2 n.to_bytes(3, 'big')

OverflowError: can't convert negative int to unsigned

So a correct call of the method would be

>>> n = -23567

>>> n.to_bytes(3, 'big', signed = True)

b'\xff\xa3\xf1'

int.from_bytes(bytes, byteorder, *, signed = False)

This classmethod returns the integer represented by the given array of bytes.

>>> n = 256

>>> bin(n)

'0b100000000'

>>> # convert '0b100000000' in Big Endian to int

>>> int.from_bytes(n.to_bytes(2, byteorder = 'big'), 'big')

256

>>> # convert '0b100000000' in Little Endian to int

>>> n.from_bytes(n.to_bytes(2, byteorder = 'big'), 'little')

1

Note that when two bytes are used to represent integer 256, 0b100000000 will be expanded to 00000001 00000000. In Big Endian, it represents 256, but in Little Endian, 00000001 becomes the less significant byte, while 00000000 becomes the most significant byte, and the corresponding number for 256 becomes 00000000 00000001.

For more advanced operations on integers, there are some special modules such as the standard math module, math; the free open-source mathematics software system SAGE; (https://www.sagemath.org/); SymPy (https://www.sympy.org/en/index.html); and, for operations in number theory, eulerlib (https://pypi.org/project/eulerlib/).

Float (float)

Float numbers are numbers with decimals, in the form of 12.5 in decimal notation or 1.25e1 in scientific notation, for example. Operations on float numbers include addition (+), subtraction (−), multiplication (*), division (/), and exponentiation (**), as shown below:

In [ ]:

x = 12.5 * 32.7 / 23.9 - 53.6 + 28.9 ** 2.7

print(f"x = {x}")   # prefix f tells to format the string

Out [ ]:

x = 8762.31728619258

In the example above, the equal sign (=) is an assignment operator in Python (and almost all other programming languages as well). We will explain all operators fully later in this section.

Python can handle very big integers and floating-point numbers. When a number is too big, it becomes difficult to count and check for accuracy. To solve that problem, Python allows using the underscore to separate the numbers, in the similar way that accounting and finance use a comma. The following is an example:

>>> 123_456_789_987.56+234_456_678_789

357913468776.56

Using an underscore to separate the digits has made it much easier to tell how big the number is.

r.as_integer_ratio()

This returns a pair of integers whose ratio is exactly equal to the original float r and with a positive denominator. It will raise OverflowError on infinities and a ValueError on NaNs.

>>> r.as_integer_ratio()

(7093169413108531, 562949953421312)

r.is_integer()

This returns True if r is finite with integral value, and False otherwise.

>>> r.is_integer()

False

r.hex()

This returns a representation of a floating-point number as a hexadecimal string. For finite floating-point numbers, this representation will always include a leading 0x and a trailing p and exponent.

>>> r.hex()

'0x1.9333333333333p+3'

float.fromhex(s)

This returns the float represented by a hexadecimal string s. The string s may have leading and trailing whitespace.

>>> float.fromhex('0x1.9333333333333p+3')

12.6

Boolean (bool)

Boolean data have only two values: True and False. They are used to represent the result of a test or an evaluation of logical expressions, as we will see. Technically, Python does not need a special Boolean data type, since it treats 0 and None as Boolean False, and treats everything else as Boolean True, as shown below:

In [ ]:

b = None   # assign None to variable b. None in Python represents 'no value'

print(f"b = {b}")   # print out what b holds

if not b:   # if (not b) is True then print

  print("Print this out when b is None!")

Out [ ]:

b = None

Print this out when b is None!

However, having a Boolean data type with two Boolean values of True and False does clearly remind Python programmers, especially beginners, that there are special types of data and expressions called Boolean data and Boolean expressions.

Complex (complex)

If you have never heard about complex numbers, quickly search the internet for complex numbers and read some articles or watch some videos.

Briefly, a complex number is a representation of a point on a plane with X and Y axes that take the form of x + yj, in which x and y are float numbers that represent and define the location of a point on the plane. Examples of complex numbers are 1 + 1j, 3 − 6j, 2.5 − 8.9j, and so on.

The same operations on float numbers can also be applied to complex numbers, as shown below:

In [ ]:

x = 3.5 + 6.7j   # assign a complex number to x

y = 12.3 - 23.9j   # assign another complex number to y

z = x + y   # assign the sum of x and y to z

print(x, '+', y, '=', z)   # print out the value of the variable

print(x, '-', y, '=', x - y)   # the difference between x and y

print(x, '*', y, '=', x * y)   # the product of x and y

print(x, '/', y, '=', x / y)   # the result of x divided by y

Out [ ]:

(3.5 + 6.7j) + (12.3 - 23.9j) = (15.8 - 17.2j) (3.5 + 6.7j) - (12.3 - 23.9j) = (-8.8 + 30.599999999999998j) (3.5 + 6.7j) * (12.3 - 23.9j) = (203.18 - 1.2399999999999807j) (3.5 + 6.7j) / (12.3 - 23.9j) = (-0.16204844290657439 + 0.229840830449827j)

Compound Data Types

In previous sections, we saw data in pieces. Sometimes it is more convenient, more effective, and even necessary to use some data together to represent certain kinds of information. Examples are when we refer to the days of the week, months of the year, and so on. Courses in universities are often identified using compound data, a tuple made of a course number and course title or name.

In Python, compound data types provide means of structuring data. They are also referred to as data structures.

Compound data types in Python can be categorized into sequence and nonsequence data types. Items in sequence compound data are ordered and indexed. Sequence compound data types include string, list, and tuple. Items in a nonsequence compound data are not ordered. Nonsequence compound data include set and dictionary.

String (str)

Sequences are a group of data in order, and a string is a good example of a sequence.

Like numbers, strings are very important in all programming languages. It is hard to imagine what a number means without its context. For that reason, in most programming languages, strings are also considered a primary data type in terms of their importance and the role that they play.

In Python, strings are sequences of characters, symbols, and numbers enclosed in a pair of double quotation marks or a pair of single quotation marks. Table 2-2 is a list of ASCII characters that can be used in strings. The following are some examples of strings:

In [ ]:

s1 = "this is my first string in double quotes"

s2 = 'string in single quotes'

print('s1 = ', s1)   # print out s1 = the value of variable s1

print('s2 = ', s2)   # print out s2 = the value of variable s2

Out [ ]:

s1 = this is my first string in double quotes

s2 = string in single quotes

When a string is too long and needs to span more than one line, a pair of triple quotation marks can be used, as shown in the following example:

In [ ]:

long_string = """ASCII stands for American Standard Code for Information Interchange.

Computers can only understand numbers, so an ASCII code is the numerical representation of a character such as "a" or "@" or an action of some sort.

ASCII was developed a long time ago, and now the nonprinting characters are rarely used for their original purpose. Below is the ASCII character table. The first 32 characters are nonprinting characters. ASCII was designed for use with teletypes, so the descriptions in ASCII are somewhat obscure.

If someone says they want your CV in ASCII format, all this means is they want "plain" text with no formatting such as tabs, bold or underscoring—the raw format that any computer can understand.

This is usually so they can easily import the file into their own applications without issues. Notepad.exe creates ASCII text, and MS Word lets you save a file as "text only."

"""

print('long_string =', long_string)

Out [ ]:

long_string = ASCII stands for American Standard Code for Information Interchange. Computers can only understand numbers, so an ASCII code is the numerical representation of a character such as "a" or "@" or an action of some sort. ASCII was developed a long time ago and now the nonprinting characters are rarely used for their original purpose. Below is the ASCII character table. The first 32 characters are nonprinting characters. ASCII was designed for use with teletypes and so the descriptions in ASCII are somewhat obscure. If someone says they want your CV in ASCII format, all this means is they want "plain" text with no formatting such as tabs, bold or underscoring—the raw format that any computer can understand. This is usually so they can easily import the file into their own applications without issues. Notepad.exe creates ASCII text, and MS Word lets you save a file as "text only."

This can be very useful in cases such as when you want to print out instructions for users to use with an application you developed.

Otherwise, you would need to use backslash at the end of each line except the last one to escape the invisible newline ASCII character, as shown below:

In [ ]:

s0 = 'Demo only. This string is not too long \

to be put on one line.'

print(f's0 = {s0}')

Out [ ]:

s0 = Demo only. This string is not too long to be put on one line.

This is OK if the string only spans across two or three lines. It will look clumsy if the string spans across a dozen lines.

In the example above, we use backslash \ to escape or cancel the invisible newline ASCII character. In Python and almost all programming languages, some characters have special meanings, or we may want to assign special meaning to a character. To include such a character in a string, you need to use a backslash to escape from its original meaning. The following are some examples:

In [ ]:

print("This string will be put \n on two lines")

# \n will start a new line

print("This string will add \t a tab - a big space")

# \t will add a tab - big space

Out [ ]:

This string will be put

on two lines

This string will add    a tab - a big space

In the examples above, putting a backslash in front of n assigns the combination \n a special meaning, which is to add a new line to the string; putting a backslash in front of t assigns the combination \t a special meaning, which is to add a tab (a number of whitespaces) to the string. The next example uses backslash to escape the quotation from its original meaning defined in Python.

In [ ]:

print("This is \"President\" quoted")

# \" puts quotation marks in a string

Out [ ]:

This is "President" quoted

Table 2-2: ASCII table showing the codes of characters

Dec

Char

Dec

Char

Dec

Char

Dec

Char

0

NUL (null)

32

SPACE

64

@

96

`

1

SOH (start of heading)

33

!

65

A

97

a

2

STX (start of text)

34

"

66

B

98

b

3

ETX (end of text)

35

#

67

C

99

c

4

EOT (end of transmission)

36

$

68

D

100

d

5

ENQ (enquiry)

37

%

69

E

101

e

6

ACK (acknowledge)

38

&

70

F

102

f

7

BEL (bell)

39

'

71

G

103

g

8

BS (backspace)

40

(

72

v

104

h

9

TAB (horizontal tab)

41

)

73

I

105

i

10

LF (NL line feed, new line)

42

*

74

J

106

j

11

VT (vertical tab)

43

+

75

K

107

k

12

FF (NP form feed, new page)

44

,

76

L

108

l

13

CR (carriage return)

45

-

77

M

109

m

14

SO (shift out)

46

.

78

N

110

n

15

SI (shift in)

47

/

79

O

111

o

16

DLE (data link escape)

48

0

80

P

112

p

17

DC1 (device control 1)

49

1

81

Q

113

q

18

DC2 (device control 2)

50

2

82

R

114

r

19

DC3 (device control 3)

51

3

83

S

115

s

20

DC4 (device control 4)

52

4

84

T

116

t

21

NAK (negative acknowledge)

53

5

85

U

117

u

22

SYN (synchronous idle)

54

6

86

V

118

v

23

ETB (end of trans. block)

55

7

87

W

119

w

24

CAN (cancel)

56

8

88

X

120

x

25

EM (end of medium)

57

9

89

Y

121

y

26

SUB (substitute)

58

:

90

Z

122

z

27

ESC (escape)

59

;

91

[

123

{

28

FS (file separator)

60

<

92

\

124

|

29

GS (group separator)

61

=

93

]

125

}

30

RS (record separator)

62

>

94

^

126

~

31

US (unit separator)

63

?

95

_

127

DEL

These 128 ASCII characters, including both printable and unprintable ones, are defined for communication in English between humans and machines. There is an extended set of ASCII characters defined for communication in other Western languages such as German, French, and others.

To enable communication between human and machines in languages such as Chinese, Unicode was designed. Details about Unicode can be found at https://unicode.org/. For information on how Unicode is used in Python, read the article at https://docs.python.org/3/howto/unicode.html.

In earlier versions of Python, if you want to use a non-ASCII character encoded in Unicode in a string, you need to know the code, assuming it is NNNN, and use escape sequence \uNNNN within the string to represent the non-ASCII character. You can also use built-in function chr(M) to get a one-character string encoded in Unicode, where M is code of the character in the Unicode table. The reverse built-in function order(Unicode character) is used to get the code of the Unicode character in the Unicode table.

In Python 3.0, however, the default encoding of Python programs was changed to UTF-8, which includes Unicode, so you can simply include any Unicode character in a string and PVM will recognize and handle it correctly, as shown in the following example:

In [ ]:

print("秦时明月汉时关 can be directly included in a string")

print(f"though you can still use chr(31206) for {chr(31206)}, chr(27721) for {chr(27721)}")

Out [ ]:

秦时明月汉时关 can be directly included in a string

though you can still use chr(31206) for 秦, chr(27721) for 汉

When representing strings, some prefixes or flags can be put in front of the opening quotation mark. These flags are also called prefixes, used before the opening quote of a string. These prefixes are listed in Table 2-3 with their meaning and some coding samples.

Table 2-3: Prefixes used for string formatting and construction

Flag

What it does

Code sample in Jupyter Notebook

F, f

F/f for formatting. Causes the evaluation of expressions enclosed within {}.

In:

name="John"

s0 = f"Your name is {name}."

print(s0)

Out:

Your name is John.

R, r

R/r for raw string. Nothing in the string is evaluated, not even \".

In:

name = "John"

s0 = r"Your name is\t {name} \""

print(s0)

Out:

Your name is \t {name} \"

U, u

U/u for Unicode, indicating Unicode literals in a string. It has no effect in Python 3 since Python 3’s default coding is UTF-8, which includes Unicode.

In:

print(u"秦时明月汉时关", end=":")

print("秦时明月汉时关")

Out:

秦时明月汉时关:秦时明月汉时关

B, b

B/b for byte. Literals in the string become byte literals, and anything outside of ASCII table must be escaped with backslash.

In:

print(b"2005-05-26-10458.68")

Out:

b"2005-05-26-10458.68"

List

List is a very useful compound data type built into Python. A list of elements, which can be different types of data, is enclosed in square brackets. The following are some examples of lists:

[1, 2, 3, 4, 5]

['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']

In Python, an element in a list can be any type of data or object, to use a more common computer-science term. So an element can be a list too, such as,

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

Assume that

week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

The term week[0] refers to the first element of the list, and week[1] refers to the second element of the list, where 0 and 1 are called index. An index can be negative as well, meaning an item counted from the end of the list. For example, week[-1] will be Sunday, the first item from the end; week[-2] will be Saturday, the second item from the end.

To get a sublist of a list L we use notation L[s: e], where s is the starting point in the list, e is the ending point within the list, and the sublist will include all items from s till e but excluding the item at e. For example, to get all weekdays from the list week, we use week[0,5], as shown below:

In [ ]:

week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

week[0:5]

Out [ ]:

['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']

Negative indexing becomes convenient when a list, or any sequence, is too long to count from the beginning. In the example above, it is much easier to count from the end to find out that the weekdays stop right before Saturday, whose index is −2, as shown below:

In [ ]:

week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

week[0:-2]

Out [ ]:

['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']

Within the notation of L[s:e], s or e or both may be missing. When s is missed, it means the sublist is indexed from the beginning of the list; when e is missed, it means the sublist is indexed from the end of the list. So week[:] will include all the items of the list week, as shown below:

In [ ]:

week[:]

Out [ ]:

['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

Multiple lists can be joined together with operator +. Assume we have the following two lists:

weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']

weekend = ['Saturday', 'Sunday']

We can then combine weekdays and weekend into one list and assign the new list to week using operator +, as shown below:

In [ ]:

weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']

weekend = ['Saturday', 'Sunday']

week = weekdays + weekend

print(week)

Out [ ]:

['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

A copy of a list can be easily made by sublisting all its members, as shown below:

week0 = week[:]

We can create a list from a string using the built-in function list():

In [ ]:

l0 = list("How are you?")

print(l0)

Out [ ]:

['H', 'o', 'w', ' ', 'a', 'r', 'e', ' ', 'y', 'o', 'u', '?']

We can also create a list using the built-in function list() and range():

In [ ]:

l1 = list(range(10))

l2 = list(range(10, 20))

print(l1, l2)

Out [ ]:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

We can use the built-in function len() to find out how many elements are in the list:

In [ ]:

print(len(week))

Out [ ]:

4

Tuple

Tuple is another type of sequence, but members of a tuple are enclosed in parentheses. The following are some sample tuples:

(12, 35)

('Canada', 'Ottawa')

('China', 'Beijing')

You can create a tuple from a list by using the tuple() function. For example,

tpl = tuple(week)

This will create a tuple, as shown below:

('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')

Similarly, you can create a list from a tuple, as shown below:

week = list(tpl)

Members of a tuple can be accessed in the same way as lists because the members are also indexed. For example, tpl[0] refers to Monday.

Moreover, most of the operations used on lists can be applied to tuples, except those that make changes to the member items, because tuples are immutable.

Why are tuples immutable? You may consider it like this: A tuple is used to represent a specific object, such as a point on a line, or even a shape. If any member of the tuple is changed, it will refer to a different object. This is the same for numbers and strings, which are also immutable. If you change any digit of a number, or any character of a string, the number or string will be different.

Set

In Python, a set is a collection of elements or objects enclosed in a pair of curly brackets. Like sets in mathematics, members in a set are unordered and unindexed. The following are two examples of sets:

grades = {'A', 'A+', 'A−', 'B', 'B+', 'B−', 'C', 'C+', 'C−', 'D', 'D+', 'D−'}

My_friends = {'John', 'Jack', 'Jim', 'Jerry', 'Jeromy'}

You can use built-in function set() to build a set from a list or tuple:

week_set = set(('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'))

Built-in functions set(), list(), tuple(), float(), int(), str() are also called constructors or converters, because they are used to construct or convert to one respective type of data from another type.

You can use membership operator in to test if an object is a member of a set. For example,

'John' in My_friends

will give you a True value because John is a member of set My_friends constructed above.

You can use built-in function len() to get the size of a set—that is, how many members are in the set. So len(grades) will be 12.

Dictionary

In Python, a dictionary is a collection of comma-separated key-value pairs enclosed in curly brackets and separated by a colon :. The members of a dictionary are unordered and unindexed. The following is an example:

In [ ]:

weekday = {'Mon':'Monday', 'Tue':'Tuesday', 'Wed':'Wednesday', 'Thu':'Thursday', 'Fri':'Friday'}

print(weekday['Mon'], ' of ', weekday)

Out [ ]:

Monday of {'Mon': 'Monday', 'Tue': 'Tuesday', 'Wed': 'Wednesday', 'Thu': 'Thursday', 'Fri': 'Friday'}

Because the keys are used to retrieve the values, each key must be unique within a dictionary. For example, we use Weekday['Mon'] to retrieve its corresponding value, Monday.

In this case, you can also use integer numbers as keys, as shown below:

In [ ]:

weekday = {1:'Monday', 2:'Tuesday', 3:'Wednesday', 4:'Thursday', 5:'Friday'}

print(weekday[1], ' of ', weekday)

Out [ ]:

Monday of {1: 'Monday', 2: 'Tuesday', 3: 'Wednesday', 4: 'Thursday', 5: 'Friday'}

Object

Although you can code almost any application in Python without object-oriented thinking, you should be aware that Python fully supports object-oriented programming. In fact, Python treats everything as an object, including classes, functions, and modules. For example, numbers are treated as objects in the following statements:

In [ ]:

print((2.35).hex())

print((23).bit_length())

Out [ ]:

0x1.2cccccccccccdp+1

5

There are some special types of objects in Python, as shown in Table 2-4.

Table 2-4: Types of objects in Python

Name

Meaning

Example of usage

type

Because in Python everything is an object, so are classes, whose class is type, which is again an object as well as a special object.

It has no real usage in programming but is rather a philosophical and ideological concept.

None

An object representing “no value.” It is the only object of data type NoneType. For a logical expression, None is the same as 0, null, empty string, and False.

In:

if not None:

  print('there is no value')

Out:

There is no value

file

A file object can be created by calling the file() or open() methods, which allow us to use, access, and manipulate all accessible files.

f = open("resume.xml", "r")

function

In Python, functions are first-class objects and can be passed as arguments in another function call.

sort(method, data_list)

module

A special type of object that all modules belong to.

It is more a philosophical and ideological concept.

class

A type of all classes.

It is more a philosophical and ideological concept.

class Instance

An individual object of a given class.

It is more a philosophical and ideological concept.

method

A method of a given class.

It is more a philosophical and ideological concept.

code

A code object is the internal representation of a piece of runnable Python code.

It is used in internal Python program running.

frame

A table containing all the local variables.

It is used in function calling.

traceback

A special object for exception handling.

It provides an interface to extract, format, and print stack traces of Python programs, especially when an exception is raised.

ellipsis

A single object called ellipsis, a built-in name in Python 3.

It is rarely used except in slicing.

Variables and Constants

Data values, variables, and constants are important constructs of any programming language. We have presented all standard simple or primary data types and compound data types and their values in the previous section. In the following section, we will study variables and constants.

Variables

A variable is a name that identifies a location in computer memory to store data. A variable must conform to the rules of naming discussed earlier in this section, and it also must not be used for other purposes within the same context of the program. For example, you cannot use reserved words or keywords as variables.

An important operation on a variable is to assign a value to it or put a value into the memory location identified by the variable. In Python, this is done by using the assignment operator =.

For example, the following statement assigns COMP 218 to the variable course, assigns Smith to the variable student, and assigns 99 to the variable grade:

In [ ]:

course = 'COMP 218'

student = 'Smith'

grade = 99

print("course is {}, student is {}, grade is {}".format(course, student, grade))

Out [ ]:

course is COMP 218, student is Smith, grade is 99

Unlike other programming languages, in Python, there is no need to declare its type before a variable is introduced and used in your program for the first time. Its type is determined by the value assigned to it. In the above example, the type of grade is integer, because 99 is an integer.

In [ ]:

type(grade)

Out [ ]:

int

You may convert the value of a variable into another type using specific built-in functions, such as int(), float(), str(), etc.

In [ ]:

marks = 90.8   # assign float mark to variable marks

int_mark = int(marks)   # convert into integer mark and assign it to variable int_mark

print(int_mark)

Out [ ]:

90

Coding Practice

Task 1

In a Jupyter Notebook cell, type the following code and run it by hitting Shift+Enter to see what you will get:

pi = 3.1415

r = 6

area = pi * r ** 2

print(F"The type of pi is {type(pi)}, and its value is {pi}")

print("The type of r is ", type(r), ", its value is ", r)

print("The type of area is {:^10}".format(str(type(area))), end='')

print(", and its value is {:^12}.".format(area))

Task 2

In a new cell of Jupyter Notebook, write and run the following statements, which calculate the circumference of a circle with radius r = 10, and print the result:

pi = 3.1415

r = 10

circumference = 2 * pi * r

print("The circumference of a circle with radius {:d} is {:f}".format(r, circumference))

Please note that in Jupyter Notebook, if you need a new cell, simply click the plus sign button under the notebook menu.

Please also note that the type of variable area is the same as the type of variable pi, but not of variable r. We can check what type the result will be when a different arithmetic operator is applied to a pair of numbers of the same or different types, as shown in Tables 2-5a and 2-5b:

Table 2-5a: Semantics of operator +, -, *

+, -, *

integer

float

complex

integer

integer

float

complex

float

float

float

complex

complex

complex

complex

complex

Table 2-5b: Semantics of / (division) operator

/

integer

float

complex

integer

float

float

complex

float

float

float

complex

complex

complex

complex

complex

The following coding example in Jupyter Notebook confirms that the result will be a complex number when an integer is divided by a complex number:

In [ ]:

i = 12

cx = 23 + 35j

icx = i / cx

print(icx, type(icx))

Out [ ]:

(0.1573546180159635-0.2394526795895097j) <class 'complex'>

You may copy and modify the code above to check other combinations in Jupyter Notebook.

Built-In Constants

We have seen some values of various data types. Some values have special meanings in Python. We call them constants. The following table lists all the constants you may see and use when programming with Python.

Table 2-6: Python built-in constants

Constant name

Meaning

Code sample in Python interactive mode

True

Logical true

>>> x = True

>>> if x:

… print(f"x is {x}")

…

x is True

False

Logical false

>>> x = False

>>> if not x:

… print(f"x is {x}")

…

x is False

None

No value assigned

>>> x = None

>>> if not x:

… print(f"{x} is treated as False")

…

None is treated as False

Ellipsis

Same as …, often used in slicing multiple dimensional arrays

>>> Ellipsis == …

True

>>> Ellipsis is …

__debug__

Contains True if Python is started without the -O option

C:\Users\comp218>python -O

Python 3.7.2

>>> __debug__

False

quit

Contains information displayed when Python quits and terminates

>>> quit

Use quit() or Ctrl+Z+Enter to exit

exit

Contains information displayed when Python quits and terminates

>>> exit

Use exit() or Ctrl+Z+Enter to exit

copyright

Contains copyright information

>>> copyright

Copyright (c) 2001–2018 Python Software Foundation.

All Rights Reserved.

Copyright (c) 2000 BeOpen.com.

All Rights Reserved.

Copyright (c) 1995–2001 Corporation for National Research Initiatives.

All Rights Reserved.

Copyright (c) 1991–1995 Stichting Mathematisch Centrum, Amsterdam.

All Rights Reserved.

credits

Contains credit information

>>> credits

Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands for supporting Python development. See www.python.org for more information.

license

Contains licensing information

>>> license

Type license() to see the full license text

__name__

When a Python file is started, some special variables are initialized with specific values, and __name__ is one such variable. This variable will have value __main__ if the Python file is started as the main program; otherwise, it will contain the module name or the function or class name if that is imported from the module.

C:\comp218> python prime.py

.…

>>> __name__

__main__

More information about these constants can be found at https://docs.python.org/3/library/constants.html.

Operators

As we learned in previous sections, data are used to represent information, while variables and constants are used to refer to data stored in computer memory. In the following sections, we will learn about operators and built-in functions that can be used to process and manipulate data.

Arithmetic Operators

Arithmetic operators are used on numbers. These operators are well-known. Table 2-7 provides a list of these operators, their meaning, and code samples you may take and practise in Python interactive mode. Please copy only the expressions or statements behind >>>, which is the Python prompt for your input.

Table 2-7: Arithmetic operators

Operator

Operation

Code samples in Python interactive mode

+

Add two operands

or unary plus

+ operator can be redefined in a class for its objects defining __add__

>>> x = 10

>>> y = 20

>>> x + y

30

>>> +y

20

−

Subtract right operand from the left or unary minus

>>> x, y = 10, 20

>>> x - y

-10

>>> -y

-20

*

Multiply two operands

>>> x, y = 10, 20

>>> y * x

200

/

Divide left operand by the right one (always results into float)

>>> x, y = 10, 20

>>> y / x

2.0

//

Floor division—division that results into integer number by omitting all the decimals

>>> x, y = 32, 7

>>> x, y

(32, 7)

>>> x // y

4

%

Modulus—remainder of the division of left operand by the right

>>> x, y = 32, 7

>>> x, y

(32, 7)

>>> x % y

4

**

Exponent—left operand raised to the power of right

>>> x, y = 32, 7

>>> x, y

(32, 7)

>>> x ** y

34359738368

When two or more of these arithmetic operators are used in an expression, the precedence rules you learned in high school or university math courses apply. In brief, the precedence rules for all the operators are as follows:

  1. 1. Exponent operation (*) has the highest precedence.
  2. 2. Unary negation (−) is the next.
  3. 3. Multiplication (*), division (/), floor division (//), and modulus operation (%) have the same precedence and will be evaluated next unary negation.
  4. 4. Addition (+) and subtraction (−) are next, with the same precedence.
  5. 5. Comparison operators are next, with the same precedence.
  6. 6. The three logical operators (not, and, or) are next, with not having the highest precedence among the three, followed by and, then or.
  7. 7. When operators with equal precedence are present, the expression will be evaluated from left to right, hence left association.
  8. 8. Parentheses can be used to change the order of evaluation.

The following are some examples of how expressions are evaluated.

>>> 12 + 3 * 21

75

In the expression 12 + 3 * 21, because * has higher precedence than +, 3 * 21 is evaluated first to get 63, and then 12 + 63 is evaluated to get 75.

>>> ((23 + 32) // 6 - 5 * 7 / 10) * 2 ** 3

44.0

In this example, because ** has the highest precedence, 2 ** 3 is evaluated first, to get

((23 + 32) // 6 - 5 * 7 / 10) * 8

In this intermediate result, because of parentheses, we will need to evaluate ((23 + 32) // 6 − 5 * 7 / 10) first, and in this subexpression, because of parentheses, 23 + 32 will be evaluated first to get 55//6 − 5 * 7 /10. According to the precedence rules, this subexpression will be evaluated to 9 − 35 / 10, and then 9 − 3.5 = 5.5. Then the expression above will be

5.5 * 8

which is evaluated to be 44.0.

Comparison Operators

Comparison operators are used to compare two objects. It is easy to understand how they work on numbers and even strings. When a comparison is applied to lists or tuples, the comparison will be applied to pairs of items, one from each list or tuple, and the final result is True if there are more Trues; otherwise it will be False, as shown in the example below:

In [ ]:

l1 = ['apple', 'orange', 'peach']

l2 = ['tomato', 'pepper', 'cabbage']

l1 < l2

Out [ ]:

True

Table 2-8 explains all the comparison operators, with samples.

Table 2-8: Python comparison operators

Operator

Operation

Code sample in Python interactive mode

>

Greater than—True if left operand is greater than the right

>>> x, y = 23, 53

>>> x > y

False

>>> l1 = ('apple', 'orange', 'peach')

>>> l2 = ('tomato', 'pepper', 'cabbage')

>>> l2 > l1

True

<

Less than—True if left operand is less than the right

>>> x, y = 23, 53

>>> x, y

(23, 53)

>>> x < y

True

>>> s1 = "Albert"

>>> s2 = "Jeremy"

>>> s1 < s2

True

==

Equal to—True if both operands are equal

>>> x, y = 23, 53

>>> x, y

(23, 53)

>>> x == y

False

!=

Not equal to—True if operands are not equal

>>> x, y = 23, 53

>>> x, y

(23, 53)

>>> x != y

True

>=

Greater than or equal to—True if left operand is greater than or equal to the right

>>> x, y = 23, 53

>>> x, y

(23, 53)

>>> x >= y

True

<=

Less than or equal to—True if left operand is less than or equal to the right

>>> x, y = 23, 53

>>> x, y

(23, 53)

>>> x <= y

True

Logical Operators

Logical operators are used to form logical expressions. Any expression whose value is a Boolean True or False is a logical expression. These will include expressions made of comparison operators discussed above. Table 2-9 summarize the details of these logical variables.

Table 2-9: Python logical operators

Operator

Meaning

Code sample in Python interactive mode

and

A and B

True if both A and B are true

>>> (x, y) = (23, 53)

>>> (m, n) = (12, 9.6)

>>> x, y, m, n

(23, 53, 12, 9.6)

>>> x > y and m > n

False

or

A or B

True if either A or B is true

>>> (x, y) = (23, 53)

>>> (m, n) = (12, 9.6)

>>> x, y, m, n

(23, 53, 12, 9.6)

>>> x > y or m > n

True

not

not A

True if A is false

>>> (x, y) = (23, 53)

>>> x, y

(23, 53)

>>> not x < y

False

Logical expressions are often used in if and while statements, and it is important to ensure that the logical expressions used in your programs are correctly written. Otherwise, catastrophic results may occur in some real applications. Common errors in writing logical expressions include:

  1. 1. Using > instead of <, or using < instead of >
  2. 2. Using >= instead of >, or using > instead >=
  3. 3. Using <= instead of <, or using < instead <=

For example, suppose you are writing a program to control the furnace at home, and you want to heat the home to 25 degrees Celsius. The code for this should be

if t < 25 : heating()

However, if instead you wrote,

if t > 25 : heating()

the consequence would be either the home will not heat at all (if the initial temperature is below 25 when the program starts) or it will overheat (if the initial temperature is greater than 25).

Bitwise Operators

We know that data in computer memory are represented as sequences of bits, which are either 1 or 0. Bitwise operators are used to operate bit sequences bit by bit. These bitwise operations may look strange to you, but you will appreciate these operations when you need them. Table 2-10 provides a summary of bitwise operators. Please note that built-in function bin() converts data into their binary equivalents and returns a string of their binary expressions, with a leading 0b.

Table 2-10: Python bitwise operators

Operator

Meaning

Code sample in Python interactive mode

&

Bitwise and

>>> m, n = 12, 15

>>> bin(m), bin(n)

('0b1100', '0b1111')

>>> bin(m & n)

'0b1100'

|

Bitwise or

>>> bin(m), bin(n)

('0b1100', '0b1111')

>>> bin(m | n)

'0b1111'

~

Bitwise not

>>> ~ m

-13

>>> bin(~ m)

'-0b1101'

^

Bitwise XOR

>>> bin(m), bin(n)

('0b1100', '0b1111')

>>> bin(m ^ n)

'0b11'

>> 

Bitwise right shift

>>> bin(m)

'0b1100'

>>> bin(m>>2)

'0b11'

<< 

Bitwise left shift

>>> bin(m)

'0b1100'

>>> bin(m<<2)

'0b110000'

Assignment Operators

In Python, and all programming languages, the assignment operation is one of the most important operations because assignment operations store data in variables for later use.

In previous sections, we have seen many examples of using the assignment operator =, the equal sign. However, Python provides many augmented assignment operators. Table 2-11 lists all the assignment operators you can use in your Python programs.

Table 2-11: Python assignment operators

Operator

Operation

Code samples in Python interactive mode

x = e

Expression e is evaluated, and the value is assigned to variable x.

Note that in Python and in previous code samples, assignments can be made to more than one variable with one statement.

>>> m, n = 23, 12

>>> m, n

(23, 12)

>>> x = m + n

>>> x

35

x += e

Expression x + e is evaluated, and the value is assigned to variable x.

x = x + e

>>> x, m, n = 35, 23, 12

>>> x, m, n

(35, 23, 12)

>>> x += m + n

>>> x

70

>>> x, m, n

(70, 23, 12)

x = e

Expression x − e is evaluated, and the value is assigned to variable x.

x = x − e

>>> x, m, n = (70, 23, 12)

>>> x, m, n

(70, 23, 12)

>>> x -= m + n

>>> x, m, n

(35, 23, 12)

x *= e

Expression x * e is evaluated, and the value is assigned to variable x.

x = x * e

>>> x, m, n = (35, 23, 12)

>>> x, m, n

(35, 23, 12)

>>> x *= m + n

>>> x, m, n

(1225, 23, 12)

x /= e

Expression x / e is evaluated, and the value is assigned to variable x.

x = x / e

>>> x, m, n = (1225, 23, 12)

>>> x, m, n

(1225, 23, 12)

>>> x /= m + n

>>> x, m, n

(35.0, 23, 12)

x %= e

Expression x % e is evaluated, and the value is assigned to variable x.

x = x % e

>>> x, m, n = (28, 23, 12)

>>> x, m, n

(28, 23, 12)

>>> x %= m + n

>>> x, m, n

(28, 23, 12)

x //= e

Expression x // e is evaluated, and the value is assigned to variable x.

x = x // e

>>> x, m, n = 989, 23, 12

>>> x, m, n

(989, 23, 12)

>>> x //= m + n

>>> x, m, n

(28, 23, 12)

x **= e

Expression x ** e is evaluated, and the value is assigned to variable x.

x = x ** e

>>> x, m, n = 98, 3, 2

>>> x **= m + n

>>> x, m, n

(9039207968, 3, 2)

x &= e

Expression x & e is evaluated, and the value is assigned to variable x.

x = x & e

>>> x, m, n = 9, 3, 2

>>> bin(x), bin(m), bin(n)

('0b1001', '0b11', '0b10')

>>> x &= m * n

>>> bin(x), bin(m), bin(n)

('0b0', '0b11', '0b10')

x |= e

Expression x | e is evaluated, and the value is assigned to variable x.

x = x | e

>>> x, m, n = 9, 3, 2

>>> bin(x), bin(m), bin(n)

('0b1001', '0b11', '0b10')

>>> x |= m * n

>>> bin(x), bin(m), bin(n)

('0b1111', '0b11', '0b10')

x ^= e

Expression x ^ e is evaluated, and the value is assigned to variable x.

x = x ^ e

>>> x, m, n = 9, 3, 2

>>> bin(x), bin(m), bin(n)

('0b1001', '0b11', '0b10')

>>> x ^= m * n

>>> bin(x), bin(m), bin(n)

('0b1111', '0b11', '0b10')

x >>= e

Expression x >> e is evaluated, and the value is assigned to variable x.

x = x >> e

>>> x, m, n = 9, 3, 2

>>> bin(x), bin(m), bin(n)

('0b1001', '0b11', '0b10')

>>> x >>= m * n

>>> bin(x), bin(m), bin(n)

('0b0', '0b11', '0b10')

x <<= e

Expression x << e is evaluated, and the value is assigned to variable x.

x = x << e

>>> x, m, n = 9, 3, 2

>>> bin(x), bin(m), bin(n)

('0b1001', '0b11', '0b10')

>>> x <<= m * n

>>> bin(x), bin(m), bin(n)

('0b1001000000', '0b11', '0b10')

Coding Practice

Type the following code to a scratch file in VS Code or a code cell in Jupyter Notebook and run. Explain why bin(8 << 2) is equal to bin(8 * 4).

print(bin(8))

print(bin(8 << 2), bin(8 * 4))

Identity Operators

Identity operators are used to test if two operands, usually two identifiers, are identical, which in most implementations of Python means that they are referring to the same memory block of the computer. The examples Table 2-12 tell you more about this. Note that in the example, the built-in function id(o) is used to get the id of object o.

Table 2-12: Python identity operators

Operator

Meaning

Example

is

True if the operands are identical (refer to the same object)

Note that 3 and 2 + 1 have the same id, and so does 6 // 2, but not 6 / 2 because 6 / 2 = 3.0, which is different from 3.

>>> x = list(range(3))

>>> y = list(range(3))

>>> x, y

([0, 1, 2], [0, 1, 2])

>>> id(x), id(y)

(10049456, 10049016)

>>> x is y

False

>>> id(3)

258398416

>>> id(2 + 1)

258398416

is not

True if the operands are not identical (do not refer to the same object).

Note that when assigning variable y to variable x, the operation points x to the same memory block y is pointing to (so that the two have the id) and shares the same memory block. However, when a new assignment is made to x or y, the two will have different ids, unless they both hold the same integer or string.

>>> x = list(range(3))

>>> x = y

>>> id(x), id(y)

(10049016, 10049016)

>>> x is y

True

>>> y = list(range(3))

>>> id(x),id(y)

(10090256, 10090336)

>>> x, y

([0, 1, 2], [0, 1, 2])

>>> x is not y

True

Sequence Operators

In 2.1, we learned that sequences include strings, lists, and tuples because elements in strings, lists, and tuples are ordered and indexed. Sets and dictionaries are not sequences because elements in dictionaries and sets are not ordered, or not in sequence.

Sequence operators are made available for operations on strings, lists and tuples, as shown in Table 2-13.

Table 2-13: Python sequence operators

Operator

Operation

Code sample in Python interactive mode

*

Repeat a sequence such as string, list or tuple multiple times

>>> "Python " * 3

'Python Python Python '

>>> [1, 2, 3] * 5

[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

+

Join two sequences

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

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

[n]

Slice out a single member of the sequence

>>> name = 'John'

>>> name[1]

'o'

[n:m]

Slice a sequence start from n to m.

>>> name

'John'

>>> name[1:3]

'oh'

Membership Operator

Membership operators are used to test whether an element is a member of a sequence. There are three membership operators in Python, and two of them are shown in Table 2-14.

Table 2-14: Python membership operators

Operator

Operation

Code sample in Python interactive mode

v in s

True if value v is found in sequence s

>>> l = list(range(10))

>>> l

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

>>> 3 in l

True

>>> 2 + 1 in l

True

>>> 'x' in "Welcome to COMP218"

False

v not in s

Checks whether value/variable is not found in the sequence

>>> l

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

>>> 30 in l

False

>>> 30 not in l

True

The third membership operator is used to access members of objects, modules, or packages. It is the dot (.) operator. The example in Table 2-15 shows how to access a function in module math.

Table 2-15: Dot operator

Operator

Operation

Code sample in Python interactive mode

p.q

q is a member of p where p and q refer to an object (variable, constant, function or method name), package, or module name

>>> import math

>>> type(math)

<class 'module'>

>>> type(math.sqrt)

<class 'builtin_function_or_method'>

>>> math.sqrt(35)

5.916079783099616

Built-In Functions

As with operators, built-in functions are also important in processing and testing data in programs. As the name implies, built-in functions are built into Python Virtual Machine (PVM). A built-in function can be used directly without importing any module or noting what it belongs to.

Built-in functions, and functions or methods in general, can be put into two categories. One is based on the data they return, whereas the other is based on the operations performed, although sometimes the returned data from a built-in function in the second category may still be useful in subsequent executions of the program.

We will first explain built-in functions in the first category, followed by built-in functions in the second category. To best understand these functions, read through these built-in functions and test the sample code in a Python interactive shell or Jupyter Notebook.

abs(x)

This returns the absolute value of x, which can be any number.

>>> abs(-99)

99

>>> abs(-b110010)   # a binary number

50

>>> abs(-0o32560)   # an octal number

13680

>>> abs(0xdef21a)   # a hexadecimal(16) number

13610970

int(s, base = 10)

This converts a number s in a specific base to an integer in base-10. The default base is 10. If the base is explicitly given, s must be a string containing a legitimate literal for the base.

>>> int(19.9)

19

>>> int("22", 8)   # in the quote must be a legitimate literal for base-8

18

>>> int('0x123', base = 16)   # a number in base-16

291

pow(x, p)

This returns the value of x to the power of p.

>>> pow(2.9, 12.8)

829266.980472172

float(s)

This converts s to float. s can be a number, or a string of numbers.

>>> float('18.23')

18.23

>>> float(19)

19.0

max(iterable, *[, default = obj, key = func])

max(arg1, arg2, *args, *[, key = func])

These find and return the biggest element from an iterable such as a list, tuple or string, or from two or more arguments. The default keyword-only argument specifies what will be returned if the iterable is empty. The key keyword-only argument specifies how the maximum is defined if it is out of the ordinary.

>>> max(2, 1, 5, 65, 89)   # variable-length list of arguments

89

>>> max("this")   # the given sequence is a string

't'

>>> max((2, 3, 5, 1, 78))   # numbers in a tuple

78

>>> max([2, 3, 5, 1, 78])   # numbers in a list

78

min(iterable, *[, default = obj, key = func])

min(arg1, arg2, *args, *[, key = func])

These find and return the smallest number from an iterable such as a list, tuple or string, or from two or more arguments. The default keyword-only argument specifies what will be returned if the iterable is empty. The key keyword-only argument specifies how the minimum is defined if it is out of the ordinary.

>>> min(6, 5, 8, 3, 2)

2

>>> min([2, 3, 5, 1, 78])   # numbers in a list

>>> min([], default = 0)   # 0 will be returned because the list is empty

0

round(f)

This rounds number f to the closest integer and returns the integer.

>>> round(3.1415926)

3

ord(c)

This finds and returns the order of a character, as a single char string, in the ASCII table.

>>> ord('c')

99

sum(…)

This calculates and returns the sum of numbers in a list, a tuple, or a range() call.

>>> sum([23, 56, 67, 12, 89])

247

>>> sum((23, 56, 67, 12, 89))

247

>>> sum(range(88))

3828

set(s)

This converts a set from a list or tuple.

>>> set([23, 56, 67, 12, 89])

{23, 56, 67, 12, 89}

dict()

dict(iterable)

dict(a = v,…)

These convert an empty dictionary, construct a dictionary from the iterable of (k, v) tuples, and from key=value pairs, respectively.

>>> dict()

{}

>>> dict([(1,'Turing'), (2,'Bool'), (3,'Babbage'), (4,'Neumann'), (5,'Knuth')])

{1: 'Turing', 2: 'Bool', 3: 'Babbage', 4: 'Neumann', 5: 'Knuth'}

>>> dict(a = 1, b = 2, c = 3)

{'a': 1, 'b': 2, 'c': 3}

bin(n)

This converts a number to its binary equivalence as a string.

>>> bin(98)

'0b1100010'

hex(n)

This converts a number to its hex equivalence as a string.

>>> hex(19)

'0x13'

oct(n)

This converts a number to its oct equivalence as a string.

>>> oct(28)

'0o34'

bool(o)

This converts o to Boolean True or False. In Python, 0, '', and None are equivalent to False, everything else is equivalent to True.

>>> bool(1)

True

>>> bool('school')

True

>>> bool(0)

False

tuple(s)

This constructs a tuple from a list, a string, or range() call.

>>> tuple("this is tuple")

('t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'u', 'p', 'l', 'e')

len(s)

This returns the length of a sequence.

>>> len(my_tuple)

13

>>> len("I like Python so much!")

22

list(s)

This constructs a list from a sequence or range() call.

>>> list(range(5))

[0, 1, 2, 3, 4]

range(start, stop, step)

This returns a sequence of numbers starting from 0 by default, ending right before stop and increasing by one step by default.

>>> list(range(1, 9, 2))

[1, 3, 5, 7]

complex(a, b)

This constructs a complex number from a pair of numbers and returns the complex number.

>>> complex(1, 8)

1 + 8j

hash(s)

This generates a hash for a given string s and returns the hash. One use is for transmitting and saving passwords.

>>> hash("Python is a great language for programming")

6145305589036905122

divmod(a, b)

This returns a tuple of the quotient and the remainder of one integer or float number divided by another integer or float number.

>>> divmod(23, 5)

(4, 3)

str(x)

This converts object x literally to a string and returns the converted string.

>>> str([23, 56, 67, 12, 89])

'[23, 56, 67, 12, 89]'

chr(n)

This returns the character n with its code in the Unicode table. Note that 0 <= n <= 0x10ffff as a legitimate code.

>>> chr(90)

'Z'

>>> chr(99)

'c'

type(o)

type(C, bases, dict)

type(o) returns the data type of object o, whereas type(C, bases, dict) will create a new type/class whose name is C and whose base classes are in bases, which is a tuple, and the dictionary defines the attributes of the new class, with assigned values. This gives programmers a way to dynamically define classes.

>>> type(list(range(9)))

<class 'list'>

In [ ]:

X = type('X', (object), dict(a = 1, b = 3))   # create a new class named X

x = X()   # create an instance of X

print(f'x.a = {x.a}, x.b = {x.b}')

x.a, x.b = 23, 35   # assign values to x's attribute a and b

print(f'x.a = {x.a}, x.b = {x.b}')

Out [ ]:

x.a = 1, x.b = 3

x.a = 23, x.b = 35

all(iterable)

This returns True if all the elements of iterable are true.

>>> all(range(9))

False

>>> all(range(1,9))

True

any(iterable)

This returns True if any of the arguments true.

>>> any(range(9))

True

>>> any([0,0,0,0])

False

dir()

dir(o)

dir() returns a list of names in the current namespace. dir(o) returns a list of the attributes of object o.

>>> dir()

['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

>>> dir(math)

['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

next(it)

This returns the next element of an iterable such as list, string, tuple, and so on.

>>> l=iter(list(range(3,99)))

>>> next(l)

3

>>> next(l)

4

ascii(o)

This returns a string containing a printable ASCII representation of an object.

>>> ascii(math)

"< module 'math' (built-in)>"

>>> ascii(int)

"<class 'int'>"

id(o)

This returns object o’s “identity,” which is a unique integer within a given context, usually the address of the object in memory.

>>> i = 10

>>> id(i)   # return the id of variable i

263313728

>>> i *= 98

>>> id(i)   # id is different, but still the same i

2809440

sorted(s)

This returns a new sorted list of elements in iterable s.

>>> il = [12, 0, 9, 32, 8, 5, 3, 99] # il is a list of integers

>>> sorted(il)   # default is to sort in ascending order

[0, 3, 5, 8, 9, 12, 32, 99]

>>> sorted(il, reverse = 1)   # sorted in descending order

[99, 32, 12, 9, 8, 5, 3, 0]

reversed(s)

This returns a reversed iterator.

>>> il = [0, 3, 5, 8, 9, 12, 32, 99]

>>> list(reversed(il))

[99, 32, 12, 9, 8, 5, 3, 0]

>>> list(reversed(range(9))) # range(9) return a sequence of 0,1,…9

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

enumerate(s, start = 0)

This returns a list of tuples from a sequence in which the elements are counted and each element is paired with its count to form a tuple.

>>> list(enumerate("this is"))   # default value for optional argument start is 0

[(0, 't'), (1, 'h'), (2, '€'), (3, 's'), (4, ' '), (5, '€'), (6, 's')]

>>> list(enumerate("this is", 2))   # now counting start from 2

[(2, 't'), (3, 'h'), (4, '€'), (5, 's'), (6, ' '), (7, '€'), (8, 's')]

>>>

eval(s, globals = None, locals = None, /)

This evaluates the expression in s as a string or a compiled Python code in s and returns the value. Global and local namespaces can be specified for the expression or code object using the keyword arguments.

>>> eval("1 / (1 + (1 / math.e) ** 12)")

0.9999938558253978

exec(s)

This executes the statement in string s and provides a way to dynamically execute the Python code.

>>> exec("print('Hello World!')")

Hello World!

In [ ]:

def cubbie(n):

  return n * n * n

src = "print(cubbie(23))"

exec(src)

Out [ ]:

12167

zip(*iterables)

This returns a list of tuples by taking one element from each of the iterables to make a tuple until reaching the end of the shortest iterable, and then returning the tuple. In Python, *p notation means p takes multiple arguments. In this case, multiple iterables such as lists, tuples, or strings are expected.

>>> grade_n = [50, 70, 80, 90, 100]

>>> grade_c = ['F', 'D', 'C','B', 'A']

>>> list(zip(grade_n, grade_c))

[(50, 'F'), (70, 'D'), (80, 'C'), (90, 'B'), (100, 'A')]

In [ ]:

chars = [chr(i) for i in range(32,97)] # a list of chars

asc_table = zip(range(32,97), chars)

for coding in asc_table:

  print(coding)

Out [ ]:

(32, ' ') (33, '!') (34, '"') (35, '#') (36, '$') (37, '%') (38, '&') (39, "'")(40, '(') (41, ')') (42, '*') (43, '+') (44, ',') (45, '-') (46, '.') (47, '/') (48, '0') (49, '1') (50, '2') (51, '3') (52, '4') (53, '5') (54, '6') (55, '7') (56, '8') (57, '9') (58, ':') (59, ';') (60, '<') (61, '=') (62, '>') (63, '?') (64, '@') (65, 'A') (66, 'B') (67, 'C') (68, 'D') (69, 'E') (70, 'F') (71, 'G') (72, 'H') (73, 'I') (74, 'J') (75, 'K') (76, 'L') (77, 'M') (78, 'N') (79, 'O') (80, 'P') (81, 'Q') (82, 'R') (83, 'S') (84, 'T') (85, 'U') (86, 'V') (87, 'W') (88, 'X') (89, 'Y') (90, 'Z') (91, '[') (92, '\\') (93, ']') (94, '^') (95, '_') (96, '`')

The code sample above prints a portion of ASCII table showing the codes from 32 to 96 and their corresponding characters. It is only to show how zip function is used. There is a much simpler way to print such a table using just one for loop.

map(f, *iterables)

This applies function f to every item of an iterable and returns the resulted iterator.

>>> import math

>>> list(map(math.sqrt, range(17))

[0.0, 1.0, 1.4142135623730951, 1.7320508075688772, 2.0, 2.23606797749979, 2.449489742783178]

>>> list(map(sum, ([1, 2, 3], [4, 5, 6], [7, 8, 9, 10])))

[6, 15, 34]

getattr(o, attr)

This returns the value of object o’s attribute attr, the same as o.attr.

>>> getattr(math, 'sqrt')

<built-in function sqrt>

>>> getattr(math, 'e')

2.718281828459045

hasattr(o, attr)

This tests if object o has attribute attr and returns True if it does.

>>> hasattr(math, 'e')

True

>>> hasattr(math, 'sqrt')

True

>>> hasattr(math, 'power')

False

setattr(o, a, v)

This sets or adds an attribute a to object o and assigns value v to the attribute.

>>> class Student:   # defining a class named Student. By convention, class names should be capitalized

…pass   # this defines a class without any attribute

…

>>> s1 = Student()   # create an instance of Student

>>> setattr(s1, 'name', 'John')   # add an attribute called name, and assign 'John' to it

>>> s1.name

'John'

>>> hasattr(s1, 'name')

True

delattr(o, a)

This deletes attribute a from object o.

>>> delattr(s1, 'name') # delete attribute name from object s1

>>> hasattr(s1, 'name') # check if s1 has attribute name

False

isinstance(o, c)

This returns True if o is an instance of class c or a subclass of c.

>>> class Student:

…pass

…

>>> s1 = Student()

>>> isinstance(s1, Student)

True

issubclass(c, C)

This returns True if class c is a subclass of C.

>>> class Graduate(student):

…pass

…

>>> issubclass(Graduate, Student)

True

repr(o)

This returns a string representation of object o.

>>> repr(Graduate)

"<class "__main__.graduate'>'

filter(f, iterator)

This returns an iterator containing only the elements of the iterable for which the function returns true.

>>> def even(n):

…return not n%2 # return True if n can be divided by 2

…

>>> list(filter(even, range(9)))   # odd numbers will be taken out

[0, 2, 4, 6, 8]

callable(o)

This returns True if o is a callable object such as a defined function.

>>> callable(even)   # it will return True since even is defined

True

locals()

This updates and returns a dictionary of local names/symbols.

>>> locals()

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'math': <module 'math' (built-in)>, 'l': <list_iterator object at 0x00370230>, 'student': <class '__main__.student'>, 's1': <__main__.student object at 0x00CE3DB0>, 'graduate': <class '__main__.graduate'>, 'even': <function even at 0x0029F7C8>}

vars()

vars(o)

vars() returns the same as locals(), whereas vars(o) returns the _dict_ attribute of object o.

>>> setattr(s1, 'name', 'John')

>>> vars(s1)

{'name': 'John'}

globals()

This updates and returns a dictionary of global names/symbols in the current scope.

>>> globals()

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'math': <module 'math' (built-in)>, 'student': <class '__main__.student'>, 's1': <__main__.student object at 0x00CE3DB0>, 'graduate': <class '__main__.graduate'>, 'even': <function even at 0x0029F7C8>}

bytearray([source[, encoding[, errors]]])

This returns a bytearray object which is an array of the given bytes.

>>> s = "Hello Python lover!"

>>> barry = bytearray(s, 'utf-8')

>>> print(barry)

bytearray(b'Hello Python lover!')

bytes([source[, encoding[, errors]]])

>>> bs = bytes(s, 'utf-8')

>>> print(bs)

b'Hello Python lover!'

breakpoint(*args, **kws)

This function break the program and takes it into debug mode, calls sys.breakpointhook(), and passes a list of arguments (args) and a list of keyword arguments (**kws) to the system function.

@classmethod

The at sign @ is called a decorator in Python. This particular decorator is used to declare a method as class method, which receives the class as its first argument.

# define a class Person

class Person:

# define a class attribute

    species = "human"

# define an instance method

    def __init__(self, name, age):

        self.name = name

        self.age = age

# define a class method using the @classmethod decorator

    @classmethod

    def from_birth_year(cls, name, birth_year):

# calculate the age from the birth year

        age = 2023 - birth_year

# return a new instance of Person with the given name and age

        return cls(name, age)

# create an instance of Person using the class method

p1 = Person.from_birth_year("Alice", 1995)

# print the instance attributes

print(p1.name) # output: Alice

print(p1.age) # output: 28

print(p1.species) # output: human

The code above was taken from a code cell in Jupyter Notebook. The output is as follows when you hit the Ctrl+Enter key to run the code:

Alice

28

Human

compile(source, filename, mode, flags = 0, dont_inherit = False, optimize = −1)

This is used to compile the source into a code that can be executed using eval() or exec().

format(value[, format_spec])

This is used to convert a value to a “formatted” representation, as controlled by format_spec.

>>> print("Modern computers have over {h:3d} years of history".format(h = 80))

Modern computers have over 80 years of history

frozenset([iterable])

This returns a new frozenset object, with the option to display it with elements taken from an iterable. frozenset is also a built-in class.

>>> l = list(range(10))

>>> print(frozenset(l))

frozenset({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) # {…} is a set

help([object])

This invokes the built-in help system on the object.

>>> help(frozenset)

Using help on class frozenset in module builtins displays the following:

class frozenset(object)

 |  frozenset() -> empty frozenset object

 |  frozenset(iterable) -> frozenset object

 |

 |  Build an immutable unordered collection of unique elements.

 |….

input([prompt])

This is used to read a line from input, convert it to a string with trailing newline characters stripped, and return the string. The optional prompt argument will be displayed without a trailing newline character so that the cursor will just wait at the end of the prompt for input.

>>> s = input("please give me an integer:")

please give me an integer:

iter(object[, sentinel])

This returns an iterator object. If the second argument doesn’t exist, the first argument must be a collection object.

>>> for c in range(6): print(next(l))

…

P

y

t

h

o

n

memoryview(obj)

This returns a “memory view” object of obj. Note that obj must be a bytes-like object.

>>> mv = memoryview(b"Hello Python Lover")

>>> print(mv)

<memory at 0x000001B932AD4A00>

object

This returns a new featureless object, a base for all classes.

>>> O = object

>>> print(O)

<class 'object'>

open(file, mode = 'r', buffering = −1, encoding = None, errors = None, newline = None, closefd = True, opener = None)

This opens the file in the desired mode and returns a corresponding file object. The default mode is read.

>>> f = open('scoresheet.txt', 'w')

The example opens a file named scoresheet.txt for writing and assigns the handle to f.

print(*objects, sep = ' ', end = '\n', file = sys.stdout, flush = False)

This prints objects to the text stream file, separated by separator and followed by end. sep, end, file, and flush, if present, must be given as keyword arguments.

>>> print("Hello Python Lover!")

Hello Python Lover!

property(fget = None, fset = None, fdel = None, doc = None)

This returns a property attribute. fget, sfet, and fdel take functions for getting, setting, and deleting an attribute value.

slice(stop)

slice(start, stop[, step])

These return a slice object representing the set of indices specified by range(start, stop, step).

>>> s = "Hello Python Lover!"

>>> slicing = slice(3)   # slicing the first 3 items out of an object

>>> print(s[slicing])   # this will take the first three characters from the s

Hel

@staticmethod

This function decorator is used to declare a method as static. A static method can be called on the class or an instance.

In [ ]:

class FTool():

    @staticmethod

    def percentage(a, b):

        return a/b

r = FTool.percentage(13, 265)

print(f"{13}/{256} is {r}")

Out [ ]:

13/256 is 0.04905660377358491

super([type[, object-or-type]])

This returns a proxy object that delegates method calls to a parent or sibling type class. It is used for accessing inherited methods that have been overridden in a class.

In [ ]:

class FTool():

    @staticmethod

    def percentage(a, b):

        return a/b

print(super(FTool))

Out [ ]:

<super: <class 'FTool'>, NULL>

The superclass is NULL because FTool is not a subclass of any class except object, which doesn’t count.

Expressions

Expressions are important program constructs. An expression is made up of data items, variables, constants, and function calls joined by proper operators. The precedencies of the operators are as follows:

  1. 1. Within arithmetic operators, other operators take precedence over addition and subtraction.
  2. 2. Arithmetic operators take precedence over comparison operators.
  3. 3. Membership operators, identity operators, and comparison operators take precedence over logic operators.
  4. 4. Among logic operators, the order of precedence, from high to low, is not > and > or.

Coding Alert

Python language is case-sensitive. Be sure to use the right case when typing!

Expressions are used almost everywhere in a program and will be evaluated to a value or object in a general term. According to the type of the value or object from evaluation, an expression can be any of the following.

Arithmetic Expressions

An arithmetic expression’s value is always one of the following: an integer, float, or complex. An arithmetic expression can be made of data, variables, function calls, and arithmetic operators. When mixed data types appeared in an expression, the value type of the expression will be the most general data type. For example, the value of 3 + 5.6 will be a float number.

String Expressions

The string expression’s value is a string. String expressions are made of strings, string operators, functions and methods that return a string.

Boolean Expressions

The Boolean expression’s value is either True or False. Boolean expressions can be made of data, comparison operators, and logical operators. Note that although Python has True and False defined as logical true and false, it treats 0, None, empty string, empty list, empty tuple, set, and dictionary as False and treats everything else as True.

Other Expressions

The values of some expressions may be a list, tuple, set, dictionary or even a complex object. For example, some functions and methods can return a list or an object of a user-defined class, and the operator + can be used to combine two strings or lists together.

The following are some examples of expressions in Python:

12 + 35.6 - 36 * 3 + x   # integer and float numbers can be mixed

235 + x ** k   # 235 plus x to the power of k

2 < j and j in list_x   # 2 is less than j and j is a member of list x

Expressions are often used on the right-side of an assignment operator, such as

total = a1 + a2 + a3

i *= j + 2   # the same as i = i * (j + 2)

Coding Alert

In Python, # is used to add end-of-line comments. Anything behind # is ignored by PVM.

Coding Practice

Within VS Code, create a new Jupyter Notebook and rename it section-2.1, or double-click the notebook name on the left-hand file navigation area to open the notebook if you have already created one. In a cell, type the following code and hit Shift+Enter to run the code. Then manually evaluate the expression within the curly braces of the print statement and compare your result to the one given by the code. Explain why the results are different.

x, y = 10.23, 5.2

m, n = 27, 8

print(f'{x * y + 27 // n}')

2.2 Higher-Level Constructs of Python Programs

The constructs you learned in section 2.1 are small and meant to be used as parts of bigger ones. The big constructs of programs are called statements, which give explicit instructions to computers to act upon.

Structure of Python Programs

Before diving into the details of writing statements in Python, this section will first look at the general structure of a Python program and the coding style widely agreed upon among the Python community, which will make it so the programs that you write are readable to others.

For a simple application, a single Python file (with py as its extension) may be enough to contain all the program code needed to implement the application; for a more complex application, however, several or even hundreds of Python files may be needed. Of these files, there will be only one Python file defining the starting point of the program that implements the application, while all other files are used as modules to be imported into the main Python file, either directly or indirectly. So essentially, the relationships of all the Python files used for an application can be depicted as a tree in which the root is the main Python file.

The modules used directly or indirectly by the main Python program may be from the standard libraries installed with Python or from those installed later using the conda or pip command as needed.

Regarding coding style, see PEP 8: Style Guide for Python Code (https://pep8.org/), which describes in great detail how Python code should be written. Read it thoroughly and review it whenever you are unsure. Below are the highlights:

  1. 1. A Python program/script file should begin with a docstring as the main documentation of the program file, stating the application and functionality of the program, as well as the author and revision history.
  2. 2. In a script file, use double blank lines to separate the actual program code from the documentation section at the beginning of the file.
  3. 3. Also use double blank lines to separate top-level function and class definitions.
  4. 4. Use a single blank line to surround the definition of a method in a class definition.

This diagram has three branches with two modules each that have arrows between them representing the imports, all pointing to the main file.

Figure 2-5: Illustration of the structure of files for a Python application

  1. 5. Pay attention to indentation, especially when an expression, a simple statement, or the header of a compound statement is too long and needs to cross multiple lines.
    1. a. When an expression or a statement needs a closing brace, bracket, or parenthesis mark to complete it, there is no need to escape (\) newline at the end of an unfinished line.
    2. b. When a string needs to cross multiple lines, newline must be escaped by putting a backslash at the end of each unfinished line.
    3. c. The four-space rule is optional. The next line can be started wherever it makes more sense, such as in the column next to the opening delimiter.

In addition to the rules of coding, it’s important to maintain a consistent coding style and to make sure that the programs not only are easy to read and understand but also look neat and nice.

Documentation and Comments

As mentioned above, some lines of documentation, called docstring, are needed at the very beginning of each Python script/program file to state the purpose and functionality of the program, who made it and when, and notes for you and others who may read the program.

The following sample program calculates the area of a circle for a given radius. It shows how docstring is used in the program file.

1

"""

2

This program is used to calculate the area of a circle. It will take an input as

3

a radius, then calculate and print out the area.

4

5

File name: circle.py

6

Author: John Doe

7

Date: March 30, 2019

8

Version: 1.0

9

"""

10

11

12

radius = int(input("tell me the radius:"))   # take input from user

13

area = 3.14 * radius ** 2   # calculate the area

14

print(f"The area of a circle with radius {radius} is {area}")   # print

15

Please note the triple quotation marks on line 1 and line 9. The triple quotation marks on line 1 mark the start of the docstring, whereas the triple quotation marks on line 10 mark the end of the docstring. The quotation marks can be single or double, but they must be the same. You can also add docstrings for functions, classes, class methods, or other code blocks in the program as needed, but the opening triple quotation marks and ending triple quotation marks must be indented the same amount as the code block. You will see how this should be done in later chapters, with examples.

Please also note the comments starting with a # at the end of lines 13, 14, and 15. They are called end-of-line comments or block notes. An end-of-line comment is usually used to explain what the code on the line does. Everything behind the # mark on that line is ignored by Python Virtual Machine (PVM) and intended for only humans to read. An end-of-line comment can also be started at the beginning of a line.

The difference between docstrings and end-of-line comments is that docstrings are formal documentation of the program or module and are accessible through the built-in help() function, with the _doc_ variable automatically attached to each module, function, class and method, whereas end-of-line comments are not. As well, utility tools such as pydoc are available for generating formal documentation for a program or module from the docstrings within each Python file. The revised version of program circle.py is shown below, in which we defined a function named area, with docstrings added to the function and the program.

1

"""

2

The purpose: revised circle.py program with more docstrings, to demonstrate how docstrings and

3

inline documentation is used in Python programs.

4

5

This program is designed to calculate the area of a circle. It takes an input from the user for the radius and

6

calculates and prints out the area.

7

8

File name: circle-v2.py

9

Author: John Doe

10

Date: March 30, 2019

11

Version: 1.0

12

"""

13

14

def area(r):

15

"""To calculate the area of a circle for a given radius."""

16

  return 3.14 * r ** 2   # calculate the area

17

"""Add docstring after return statements?"""

18

19

radius = int(input("tell me the radius:"))   # take input from user

20

print(f"The area of a circle with radius {radius} is {area(radius)}")   # printout

21

22

"""I want to add more docstrings."""

The following are some general rules for program documentation:

  1. 1. A docstring should also be written for every function, class, and public method right after the header of the definition. Docstrings must be indented the same amount as the suite of function or class definition.
  2. 2. Limit the maximum line length to 79 or 72 characters if the line is part of a docstring.
  3. 3. Use inline comments whenever necessary.
  4. 4. Some code may need more than one line of comments, which makes it a block comment. A block comment should be written right before the code and indented to the same level as the code below.

Coding Trick

Document! Document! Document!

Documentation is necessary not only for users but for the programmer who made the program. The programmer may think they know everything about the program, but time can blur their memory.

Simple Statements

Normally, a simple statement is contained within a single logical line, though Python allows several simple statements to appear on one line separated by semicolons. There will be examples of this later.

Expression Statement

Simply put, expression statements in Python programs are just expressions in mathematical terms. Any expression can be used as a statement, and PVM will evaluate every expression statement, but the result is only displayed in Python interactive mode, as shown in the following code sample in the Python Shell:

Code sample in Python interactive mode

1

2

>>> 2 * 3.14 * 15

3

94.2

4

>>> 3.14 * 15 ** 2

5

706.5

6

>>>

7

8

So if you are using Python in interactive mode, you can simply type expressions without using the print statement to see the result of the calculation, just like a powerful calculator.

We can also have expression statements in Jupyter Notebook, but when there are several expression statements in the same cell, it will only show the result of the last expression, as shown in the following example:

In [ ]:

2 * 3.14 * 15

3.14 * 15 ** 2

Out [ ]:

706.5

We mentioned earlier in this subsection that you can also put several simple statements on the same line, but you must separate them with semicolons. This is shown in the following examples:

Code sample in Python interactive mode

1

2

>>> 2 * 3.14 * 15; 3.14 * 15 ** 2

3

94.2

4

706.5

5

>>> 

6

7

8

The expression statement above can also be given in Jupyter Notebook, as shown below. In Jupyter Notebook, however, you have to press Shift+Enter or click the play button to run the scripts in an active cell:

In [ ]:

2 * 3.14 * 15; 3.14 * 15 ** 2

Out [ ]:

706.5

Again, in Jupyter Notebook, even if multiple expression statements are on the same line, only the result of the last expression statement will be displayed.

Assignment Statement

The assignment statement is one of the most important statements and is used most often in programs because it is a common requirement to keep the result of computing or information processing in the computer memory for future uses. It does so by assigning the result to a variable.

In section 2.1, we saw a list of assignment operators. Formally, an assignment statement is made of a variable on the left and an expression on the right of an assignment operator, either = or an augmented one such as +=. We have already seen some examples of assignment statements before, but the following code sample includes a few more examples:

In [ ]:

d = 15

r = d / 2

x = d * 3.14

a = r * r * 3.14

print(f"diameter = {d}; radius = {r}; circumference = {x}; area is {a}")

Out [ ]:

diameter = 15; radius = 7.5; circumference = 47.1; area is 176.625

Augmented Assignment

In programming, we often take the value of a variable, perform an operation on it, then put the result back to the variable. That is when augmented assignment comes into play.

In section 2.1, we saw several augmented assignment operators. In general, for an assignment in the form of

x = x <operator> v

the augmented assignment can be used in the following form:

x <operator>= v

The following are some examples of augmented assignments:

In [ ]:

y = 10

n = 5

print(f"y is {y}; n is {n}")

y *= n   # y * n is assigned to y; it is equivalent to y = y * n

print(f"y is {y}; n is {n}")

n += 2

y /= n

print(f"y is {y}; n is {n}")

Out [ ]:

y is 10; n is 5

y is 50; n is 5

y is 7.142857142857143; n is 7

To understand these augmented assignment statements, we need to consider the memory location referred to by a variable, such as y with respect to time. Take y *= n as an example. At time t0 before the actual assignment starts, the value of y (data stored in the memory referred to by y, which is 10 at time t0) is taken out, and multiplied by n, whose value is 5 at time t0; then time t1—the result, which is 50 (from 10 * 5)—is stored in the memory location referred to by variable y.

Coding Alert

The number of value items must be enough for the variables to be assigned.

Multiple Assignments

Also, for convenience and efficiency, you can assign values to multiple variables in a single assignment statement. There are several ways of doing multiple assignments, as shown in the following examples:

In [ ]:

x, y = 1, 2   # assign 1 to x, assign 2 to y

(x, y) = (1, 2)   # it is the same as x, y = 1, 2

x, y = [1, 2]   # it is the same as x, y = 1, 2

k, *l = [1, 2, 3, 5]   # this will assign 1 to k, and assign the rest to l as list, because of *l

x, *y, z = [1, 2, 3, 5, 6, 7]   # this will assign 1 to x, 7 to z, [2, 3, 5, 6] to y

print(f"x = {x}; y = {y}; z = {z}")

Out [ ]:

x = 1; y = [2, 3, 5, 6]; z = 7

In the last example above, *l, *y tells PVM that variable l and y can take a variable-length list of values.

Conditional Assignments

Additionally, in Python, you may even assign different values to a variable under different conditions, as shown in the following example:

Code sample in Python interactive mode

1

>>> marks = 90

2

>>> gr = 'pass' if marks >= 60 else 'fail'   # note that elif clause does not work on the conditional assignment

3

>>> gr

4

'pass'

5

>>> marks = 50

6

>>> gr = 'pass' if marks >= 60 else 'fail'

7

>>> gr

8

'fail'

As you will see throughout the text, there are many fancy ways of making statements in Python, and that’s why Python is a very powerful language. Indeed, the full power of a programming language can only be materialized by the best programmers.

Annotated Assignment Statement

We know that variables in Python are dynamically typed. Sometimes, however, it is nice to indicate what type of data is expected for a variable. In Python, this is done by annotating the variable using a colon followed by the name of the data type, as shown in the following example:

marks: float = 86.5   # variable marks will hold a float number

However, Python will not complain if other types of data are assigned, as shown below:

>>> marks: float = "Python"

>>> marks

'Python'

>>>

To annotate the type of value returned from a function, you need to use -> followed by the data type, right before the colon, as shown in the following example:

In [ ]:

def literal_grade(marks:float) -> str:

  return 'fail' if marks < 60 else 'pass'

print(literal_grade(88))

Out [ ]:

pass

In this example, marks:float determines that a float number is expected for marks when calling the function, and -> str dictates that a string is to be returned.

It must be made clear that the actual type of a variable is still determined by the value it holds, and annotation added to a variable or function doesn’t really change the type of the variable or the value returned from a function. So annotations are more for programmers as reminders.

print Statement

The print statement is another one of the most important statements. It is used to output (to a terminal by default) so that a program can tell human users the result of calculations or information processing, the value of an object, or the status of the program. The following are some examples of print statements:

In [ ]:

print("this is my first print statement.")

print("it will take about ", round(300/110), "hours to drive from Edmonton to Calgary")

Out [ ]:

this is my first print statement.

it will take about 3 hours to drive from Edmonton to Calgary

The print statement can evaluate multiple arguments and print out the values. If the arguments are all constant strings, there will be no need to separate them into multiple arguments. Separate arguments are needed only when some arguments are expressions, like the round(300/110) in the above example. If you do not like separations, introduced in release 3.0, Python provides a neat way to include expressions all in a single pair of quotation marks, as shown in the following example:

In [ ]:

print(f"it will take about {round(300/110)} hours to drive from Edmonton to Calgary")

Out [ ]:

it will take about 3 hours to drive from Edmonton to Calgary

Please note the f—which is a flag or prefix—before the opening quotation mark and the curly brackets around the expression. Without the f flag, everything will be taken literally as part of the string, without evaluation.

If you want one portion of the string to be put on one line and the other portion on the next line, you may insert \n between the two portions in the string, as below:

In [ ]:

print(f"it will take about {round(300/110)} hours \nto drive from Edmonton to Calgary")

Out [ ]:

it will take about 3 hours

to drive from Edmonton to Calgary

In addition to \n, other escape sequences that we discussed previously may also be included in a string.

There may be times that you want to include an escape sequence such as \n in a string as is. To achieve that effect, you either use the r flag before the opening double quotation mark or use another backslash \ before the escape sequence to cancel the first backslash (escape), as shown in the following example:

In [ ]:

print(r"there will be no escape \n to newline")   # using the r flag

print("there will be no escape \\n to newline")   # using double backslash

Out [ ]:

there will be no escape \n to newline

there will be no escape \n to newline

Without the r flag, the sentence will be printed on two lines, as shown in the following example:

In [ ]:

print("there will be no escape \nto newline")

Out [ ]:

there will be no escape

to newline

Normally, a \n (newline) will be automatically appended to the output from each print statement by default, so that the output from the next print statement will print on a new line. If you want the output from a print statement to end with something else rather than a new line, you may use the end keyword argument to specify how the output should be ended. In the following example, output from the first print statement will be ended with a whitespace, so that outputs from the two print statements will be on the same line:

In [ ]:

print("this is my first print statement.", end=" ")

print("it will take about ", round(300/110), "hours to drive from Edmonton to Calgary")

Out [ ]:

this is my first print statement. it will take about 3 hours to drive from Edmonton to Calgary

Formally, a print statement may take the following form when used:

print(value0, value1, value2,…, sep=' ', end = '\n', file = sys.stdout, flush = False)

where value0, value1,… are values to be printed to a file stream; optional keyword argument sep defines what is used to separate value0, value1,…; optional keyword argument end tells how the output from the print statement should end; optional keyword argument file defines what file stream the output should be printed on; and optional keyword argument flush tells how the output should be flushed. The meanings and purposes of these optional keyword arguments are explained in Table 2-16.

Table 2-16: Key arguments of the print statement

Keyword argument

Values that can be taken

Default value

sep

it takes a string as its argument and inserts it between values

a space

end

it also takes a string as argument but appends it to the last value of the output stream

a new line

file

it is a file handle such as that returned by an open statement

sys.stdout

flush

it takes a Boolean value (True or False) indicating whether to forcibly flush the output stream

False

Please note that a program may need to output different types of data not only correctly but also nicely. In 5.1, we will learn how to construct well-formulated strings from various types of data.

input Statement

The input statement is another important one you must learn and use correctly and effectively. Contrary to the print statement, the input statement is used to get information from users through the keyboard, as shown in the following example in Jupyter Notebook:

In [ ]:

your_age = input("Please tell me your age:")

print("Now I know your age is", your_age)

Out [ ]:

Please tell me your age: 39

Now I know your age is 39

Please note that everything taken from users through the input statement is treated as a string. If you are expecting a number, such as an integer, you must convert the string into its respective data type, as shown in the following example:

In [ ]:

your_age = input("Please tell me your age:")

your_age = int(your_age)

print(f"In 50 years your age will be {your_age + 50}")

Out [ ]:

Please tell me your age: 39

In 50 years, your age will be 89

As you may have guessed already, the input statement takes one argument as a prompt to tell users what to do and what the program is expecting from the user.

If you want to provide more detailed instructions in the prompt to the user, you may use the triple quotation marks to include multiple lines of instruction as prompt:

In [ ]:

sl = input("""Your choices

A: to get the average mark

M: to get the mean of all marks

H: to get the highest mark

L: to get the lowest mark

Q: to exit the program

Please select___""")

Out [ ]:

Your choices

A: to get average the mark

M: to get the mean of all marks

H: to get the highest mark

L: to get the lowest mark

Q: to exit the program

Please select___

As you can see, this can be a good way to make a menu for some terminal-based applications.

assert Statement

The assert statement is used to test if a condition is true in a program. It may take one of two forms, as shown in Table 2-17.

Table 2-17: Semantics of assert statement

Syntax

Meaning

assert <condition>

if <condition> is false, the program will stop and raise AssertionError

if <condition> is True, the program will run ahead

assert <condition>,

<error message>

if <condition> is false, the program will stop and raise AssertionError, along with <error message>

The assertion statement is very useful in debugging your programs, because it can be used to check the value of a variable or a certain condition of the program. If the condition is not met as expected, the program would stop and let you check what’s going on, as shown in the following examples:

In [ ]:

def average_incomes(incomes):

  assert len(incomes) != 0, "Error: need at least one income"

  return sum(incomes) / len(incomes)

incomes = [35892, 13487, 56852, 135278, 87542]

print("Average of incomes is",average_incomes(incomes))

incomes = []

print("Average of incomes is",average_incomes(incomes))

Out [ ]:

Average of incomes is 65810.2

----------------------------------

AssertionError Traceback (most recent call last)

<ipython-input-2-201cb13363c6> in <module>

6 print("Average of incomes is",average_incomes(incomes))

7 incomes = [] --

8 print("Average of incomes is","average_incomes(incomes))

<ipython-input-2-201cb13363c6> in average_incomes(incomes)

1 def average_incomes(incomes):

-- 2 assert len(incomes) != 0, "Error: there must be at least one income"

3 return sum(incomes)/len(incomes)

4

5 incomes = [35892, 13487, 56852, 135278, 87542]

AssertionError: Error: there must be at least one income

pass Statement

As the name implies, this statement does nothing. It is used as a placeholder in places where you don’t have the actual code yet. As an example, assume you have the class Student in your design for a project, but the implementation details of the class, except the name, are yet to be worked out. You can use the pass statement to hold the place of the details, as shown below:

In [ ]:

class Student():

  pass

s1 = Student()

s2 = Student()

With the pass statement in place, this piece of code can run as part of a big program without raising an exception.

Note that a pass statement won’t let you get out of a loop. You will need to use the break statement to get out of a loop.

del Statement

This statement is used to delete an object. Because Python treats everything as an object, you can use this statement to delete everything you’ve defined.

In [ ]:

grade = 99

print(f"grade = {grade}")

del grade

print(f"grade = {grade}")

Out [ ]:

grade = 99

----------------------------------

NameError Traceback (most recent call last)

<ipython-input-9-2b1bea6f987e> in <module>

3

4 del grade

-- 5 print(f"grade = {grade}")

NameError: name 'grade' is not defined

Deleting an object will free up the memory locations occupied by the object. Computer memory is a precious resource in computing. Python objects, even objects of built-in data types—such as list, tuple, set, and dictionary—can take up a great deal of memory. Deleting the objects that are no longer used will free up memory and make it available for other objects and other applications.

return Statement

The return statement is one of the most important statements in Python (and some other languages as well). It is used to return a value from a function—a very important construct of all programs. The following is an example:

In [ ]:

def cube(n):

  return n ** 3

print(f'The cube of 23 is {cube(23)}')

Out [ ]:

The cube of 23 is 12167

This function simply takes a number and returns n to the power of 3.

Please note that in Python, the return statement doesn’t have parentheses around the value to be returned. Even if you want to return multiple values from a function, you only need to use commas to separate the values behind the return keyword. The return statement will automatically pack all the values in a tuple and then return them.

In the following example, we define a function of a modular operation but return the quotient and the remainder at the same time:

In [ ]:

def modular(a, b):

  assert b != 0, 'Zero divisor'

  return a // b, a % b

print(modular(13, 6))

Out [ ]:

(2, 1)

open Statement

The open statement is used to open a file for writing, reading, appending, or updating (reading and writing). The following is an example:

f = open("c:\\workbench\\myprimes.txt", 'r')

This opens the file specified by c:\\workbench\\myprimes.txt and creates a file object ready for reading. Reading is the default mode when you open a file without the second argument. Hence the following statement does the same as the above statement:

f = open("c:\\workbench\\myprimes.txt")

To open a file for writing, w is used for the second argument:

f = open("c:\\workbench\\myprimes.txt", 'w')

When a file is opened for writing, the old data will be overwritten if there is already data in the file. To keep the old data and append new data to the file, use a for the second argument instead:

f = open("c:\\workbench\\myprimes.txt", 'a')

If you want to create a file only if the file doesn’t exist, use x for the second argument, to mean exclusive creation of the file:

f = open("c:\\workbench\\myprimes.txt", 'x')

This would avoid accidentally overwriting a file.

By default, data written to a file opened with w, a, or x is text. The data on a file can also be in binary format. To explicitly indicate whether data on a file are or should be text or binary, you can use t or b with r, w, a, or x, as shown in the following examples:

f3 = open("c:\\workbench\\mykey.dat", 'bw')

f5 = open("c:\\workbench\\mykey.dat", 'br')

yield Statement

The yield statement is used in place of the return statement in some special circumstances when defining a function. When the yield statement is used in defining a function, the function becomes a generator in Python terms, as shown in the following example:

In [ ]:

def odds(n):

  for i in range(n):

    yield 2 * i + 1 # yield makes the function a generator

odd_numbers = odds(12)

print(f"type of object odd_numbers is {type(odd_numbers)}")

for i in odd_numbers:

  print(i, end = ' ')

Out [ ]:

type of object odd_numbers is <class 'generator'>

1 3 5 7 9 11 13 15 17 19 21 23

When we say a function becomes a generator, we mean that an object of the generator class is returned from the function.

What is a generator object? For now, you may consider it a dynamic list whose members are generated and used dynamically on the fly, without using a big bunch of memory to store the whole list. The following is an example of a generator:

Object_generator = (x ** 3 for x in range(13))

If we run

for i in Object_generator:

  print(i)

we will see the following members:

  • 0, 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728,

However, if we try to get the length of the generator object with the following statement:

print(f"{len(object_generator)}")

we will get the following error:

TypeError: object of type 'generator' has no len()

This confirms that an object of type generator has no length.

raise Statement

When some errors occur in a Python program, exceptions will be automatically raised and the program will stop running, unless the exception is handled with the try-except statement. Such errors include operations deemed illegal by Python. In some cases, an exception needs to be explicitly applied when a certain condition is met. In the previous section, we saw how an exception can be raised with the assert statement. In the following example, we show how to raise an exception with the raise statement.

In [ ]:

total = 0

for i in range(39):

  mark = int(input("Tell me a mark:"))

  if mark < 0:

    raise Exception("No negative mark is accepted!")

    total += mark

print(f'average mark is {total / 39}')

Out [ ]:

Tell me a mark: -12

----------------------------------

Exception Traceback (most recent call last)

<ipython-input-13-f4aa3f6c4326> in <module>

3 mark = int(input("Tell me a mark:"))

4 if mark < 0:

-- 5 raise Exception("No negative mark is accepted!")

6 total += mark

7 print(f'average mark is {total / 39}')

Exception: No negative mark is accepted!

This piece of code is used to calculate the average marks of 39 students, but it considers a negative mark unacceptable and will raise an exception.

break Statement

The break statement is used to get out of a loop and continue to the next statement. Here is an example:

In [ ]:

for i in range(10):

  print(i, end = " ")

  if i == 8:

    print(f"\nget out of the loop when i = {i}")

  break

Out [ ]:

0 1 2 3 4 5 6 7 8

get out of the loop when i = 8

continue Statement

The continue statement is used within a loop code block to continue to the next iteration of the loop and ignore the rest of the code block. This statement can be very useful if you don’t want to run some statements when some condition is met.

import Statement

The import statement is used to import modules into a program file or a specific class within the module. The following is an example of how to import the standard math module into the program:

In [ ]:

import math

print(f"98 ** 3 = {math.pow(98, 3)}")

Out [ ]:

98 ** 3 = 941192.0

global Statement

A global statement simply declares, within a code block such as function or class, that some identifiers/names such as variables should be treated as globally writable. Without a global statement, a variable defined outside of a function or class may be read, but writing to the variable will raise an exception, as shown in the following examples:

In [ ]:

gravity = 9.807   # gravity on the earth's surface, global variable

r_earth = 6371000   # the earth's mean radius 6371000 metres

def changed_gravity(m):   # m is the distance from the earth

  gravity = gravity * (r_earth/(r_earth+m)) ** 2   # decrease gravity by 2

  return gravity

print(f'gravity at 99999 metres above sea level is {changed_gravity(99999)} or {gravity}')

Out [ ]:

----------------------------------

UnboundLocalError Traceback (most recent call last)

<ipython-input-36-7f10379e5fb0> in <module>

6 return gravity

7

-- 8 print(g_force(99999))

<ipython-input-36-7f10379e5fb0> in g_force(m)

3

4 def changed_gravity(m):

-- 5 gravity = gravity * (r_earth/(r_earth+m))**2

6 return gravity

7 UnboundLocalError: local variable 'gravity' referenced before assignment

In the code above, gravity is first introduced outside the function definition. It became a global variable by the rule of naming scopes. Inside the definition of function changed_gravity, the name was defined again by putting it on the left side of the assignment, but only locally by default, according to the rules. However, this local variable is used on the right side of the same assignment statement. That is how the exception has occurred.

Since what we actually want is to use the globally defined variable gravity on both sides of the assignment statement within the function definition, we need to explicitly declare that, as shown in the following example revised from above:

In [ ]:

gravity = 9.807   # gravity on the earth's surface, global variable

r_earth = 6371000   # the earth's mean radius is 6371000 metres

def changed_gravity(m):   # m is the distance from the earth

  global gravity

  gravity = gravity * (r_earth / (r_earth+m)) ** 2

  return gravity

print(f'gravity at 99999 metres above sea level is {changed_gravity(99999)} or {gravity}')

Out [ ]:

gravity at 99999 metres above sea level is 9.506238807104731 or 9.506238807104731

As you can see, the value of global variable gravity has now been changed within the function.

nonlocal Statement

We have seen global variables and local variables, and how global variables are accessible globally, whereas local variables are only accessible within a local scope such as a function. There is something between global and local called nonlocal. The nonlocal statement can be used to declare a list of variables that are not local but refer to variables defined in the nearest enclosing scope but excluding global variables. This may happen when defining a function within another function, as shown in the following example:

In [ ]:

def outer_logger():

  event = 'Something has happened.'

def inner_logger():

  nonlocal event

  event += "Something else has happened as well."

  print("inner log:", event)

inner_logger()

  print("outer log:", event)

outer_logger()

Out [ ]:

inner log: Something has happened. Something else has happened as well.

outer log: Something has happened. Something else has happened as well.

help Statement

The help statement is used to invoke a helping system and is often used in Python interactive mode to get help on modules, statements, functions, or methods.

Code sample in Python interactive mode

1

>>> help(str)

2

Help on class str in module builtins:

3

4

 class str(object)

5

 | str(object = '') -> str

6

 | str(bytes_or_buffer[, encoding[, errors]]) -> str

7

 |

8

 | Create a new string object from the given object. If the encoding or

9

 | any errors are specified, then the object must expose a data buffer

10

 | that will be decoded using the given encoding and error handler.

11

 | Otherwise, returns the result of object.__str__() (if defined)

12

 | or repr(object).

13

 | encoding defaults to sys.getdefaultencoding().

14

 | errors defaults to 'strict'.

15

 |

16

 | Methods defined here:

17

 |

18

 | __add__(self, value, /)

19

 | Return self+value.

20

 |

21

 | __contains__(self, key, /)

22

 | Return key in self.

23

 |

24

 | __eq__(self, value, /)

25

 | Return self==value.

26

 |

27

 | __format__(self, format_spec, /)

28

 | Return a formatted version of the string as described by format_spec.

29

 |

30

 |

31

 | __ge__(self, value, /)

32

 -- More --

Compound Statements

In the previous section, we studied individual statements that can be used in programming with Python. In this section, we study compound statements and ways to make various compound statements in Python.

In Python, a compound statement consists of at least one clause, and each clause is made of a header and a suite, or code block. A header starts with a keyword such as if, for, while, class, def, try, else, except, finally, and so on and ends with a colon :, as described below:

  • <header>:
  •     <code block>

What can be on the header line depends on the keyword leading the header. You will learn more about this in the following chapters.

Code Blocks

In programs, some statements are grouped and run in sequence as a unit or a suite. We call such a group of statements a code block.

Unlike C, C++, Java, and some other languages that use curly brackets to make code blocks, Python uses indentation to form code blocks. In Python, a program can have multiple code blocks, and code blocks can be nested with proper indentation. Statements intended to be in the same code block must use the same indentation. The following is an example:

Code sample

1

 i, s = 1, 1   # the first statement must be started at the very beginning

2

3

 while I <= 100:   # this compound statement is in the same code block

4

    s *= i   # this is the first statement in the code block/suite

5

    i += 1   # this is the second statement in the code block/suite

6

7

 print("the product of 1x2x3 … 100 is ", s)

The sample program above has two simple statements on lines 1 and 7, and one compound statement on lines 3 to 5. The header of the compound statement begins with the keyword while, and its suite is a code block that consists of two simple statements. Because statements on lines 1, 3, and 7 are in the same code block, they must be indented the same, whereas statements on lines 4 and 5 must be further indented to form a code block as a suite for the while compound statement.

Rules of Indentation

To ensure that your programs are properly indented, follow the following rules:

  1. 1. The first line of code of a program must start at the very first column of line, though there can be some blank lines before the first line of code, for better readability, if you like.
  2. 2. All lines of code in the same code block must be indented the same.
  3. 3. The suite of a compound statement must be indented further than the header of the compound statement.
  4. 4. All code blocks that are at the same level must use the same indentation.
  5. 5. All lines of code in the same suite must use the same indentation.

Rules of Spacing

The rules of spacing are about how to space out words within a line of script or code and how to space lines of scripts. Some of the rules must be followed, while other rules are for readability or are merely convention among Python programmers:

  1. 1. There must be at least one space between two words.
  2. 2. As a convention, there should be only one space between two words.
  3. 3. Also as a convention, there should be one space before each operator and one space behind each operator in an expression. So x>y should be written as x > y.
  4. 4. For better readability, there should be no space between a unary negation operator (−) and the term it negates. So - x should be written as -x.
  5. 5. Also for readability, in a function call, there should be no space between a function name and the list of parameters. So abs (y) should be written as abs(y).
  6. 6. The same goes for definitions of functions. There should be no space between the function name and the list of arguments.
  7. 7. There should be no blank lines between lines of simple statements if they are intended to be in the same code block.
  8. 8. For better readability, there should be a blank line between simple statement(s) and compound statements if they are in the same code block, as shown in the following sample code:

Code sample

1

i, s = 1, 1   # first statement must be started at the very beginning

2

3

while I <= 100:   # this compound statement is in the same code block

4

  s *= i   # statement must be indented

5

  i += 1   # second statement in the code block/suite

6

7

print("the product of 1x2x3 … 100 is ", s)

8

Please note the blank line between line 1 and line 3, as well as between lines 5 and 7.

if Statement

An if statement is used to run a block of statements under a condition. The header of an if statement begins with the keyword if, followed by a logical expression of a condition, and then a colon, as shown below:

if <condition>:

    <suite or code block>

A diagram asking if a condition has been met, with arrows pointing outward labeled “Yes” and “No.” “Yes” leads to a rectangle labeled “suite.”

Figure 2-6: Flowchart of an if statement

Here is an example:

Code sample

1

 mark = float(input("Please input your mark:"))

2

3

 if mark >= 0:

4

   print(f"The mark is {mark}.")

5

Note that although Python allows the suite to be on the same line as the header, as shown in the following sample, for readability, that is not preferable.

if mark >= 0: print(f"The mark is {mark}.") # allowed but not preferred

if-else Statement

In the example above, the if statement can only make one selection. To do something in particular if the condition is not met, the else clause can be added. The syntax of if-else statement is shown below, and the corresponding flowchart is shown in Figure 2-7.

if <condition>:

  <code block 1>

else:

  <code block 2>

A diagram asking if a condition has been met, with arrows pointing outward labeled “Yes” and “No.” “Yes” leads to suite 1, and “No” leads to suite 2.

Figure 2-7: Flowchart of the if-else statement

The code sample shown above can be rewritten as follows by adding an else clause:

Code sample

1

 mark = float(input("please input your mark:"))

2

3

 if mark >= 0:>

4

    print(f"The mark is {mark}.")

5

 else:

6

    print("Incorrect input! A mark cannot be a negative number.")

7

if-elif Statement

The if-else statement can only handle double selections. How can we handle multiple selections in Python? For example, in addition to telling whether a mark is legitimate or not, we may also want to convert the percentage mark to a letter grade. In Python, that can be done with an if-elif or if-elif-else statement. The syntax of the if-elif statement is shown below:

if <condition 1>:

  < suite 1 >

elif <condition 2>:

  < suite 2 >

elif <condition 3>:

  < suite 3 >

…

Three items asking if the condition has been met with responses “Yes” and “No” leading out from each to either the next question or suite 1 or 2.

Figure 2-8: Flowchart of the if-elif-elif-…

The code that can tell the letter grade from a percentage grade is shown below:

Code sample

1

 number_grade = round(float(input("please tell me a numeric grade between 0 and 100:")))

2

if number_grade >= 90:

3

  print(f"alpha/letter grade for {number_grade}% is A+")

4

elif number_grade >= 85:

5

  print(f"alpha/letter grade for {number_grade}% is A")

6

elif number_grade >= 80:

7

  print(f"alpha/letter grade for {number_grade}% is A-")

8

elif number_grade >= 76:

9

  print(f"alpha/letter grade for {number_grade}% is B+")

10

elif number_grade >= 73:

11

  print(f"alpha/letter grade for {number_grade}% is B")

12

elif number_grade >= 70:

13

  print(f"alpha/letter grade for {number_grade}% is B-")

14

elif number_grade >= 67:

15

  print(f"alpha/letter grade for {number_grade}% is C+")

16

elif number_grade >= 64:

17

  print(f"alpha/letter grade for {number_grade}% is C")

18

elif number_grade >= 60:

19

  print(f"alpha/letter grade for {number_grade}% is C-")

20

elif number_grade >= 55:

21

  print(f"alpha/letter grade for {number_grade}% is D+")

22

elif number_grade >= 50:

23

  print(f"alpha/letter grade for {number_grade}% is D")

24

elif number_grade >= 0:

25

  print(f"alpha/letter grade for {number_grade}% is F")

26

else:

27

  print("Numeric grade must be a positive integer!")

if-elif-else Statement

An else clause can be added to the end of an if-elif statement in case something special needs to be done if all the conditions are not met.

while Statement

The while statement is used to run a block of code repeatedly as long as a given condition is met. The syntax of the statement is as follows:

while <condition>:

  < a suite >

Three items asking if numbered conditions have been met with “Yes” and “No” leading out from each to either the next question or suite 1, 2, 3, or 4.

Figure 2-9: Flowchart of an if-elif-…elif-else statement

The following is an example:

Code sample

1

 i = 1

2

3

 while i <= 10:

4

    print(f"I am counting to {i}")

5

    i += 1

The loop is ended when not (I <= 10). The while statement is more advantageous when used to form a loop if we only know when the loop should end, as shown in the following word-guessing program:

Code sample

1

 cnt, your_guess = 0, ""

2

3

 while (your_guess.lower()) != "python":

4

    your_guess = input("Guess which programming language is my favourite: ")

5

6

    cnt += 1

7

 print(f"Congratulations! You got it in just {cnt} guesses")

for Statement

A for statement provides another way to form a loop and is best for when the loop runs through an iterable, such as a list, a tuple, a string, a generator, a set, or even a dictionary. The syntax of the for statement is as follows:

for <iteration variable(s)> in <iterable>:

  < a suite >

Note that there can be more than one iteration variable if needed, but it is more common to have only one iteration variable.

The following is an example:

Code sample: for statement with a string

1

 cnt = 0

2

 my_string = "this is a secret"

3

 for c in my_string:

4

    print(c)

5

    cnt += 1

6

7

8

 print(f"there are {cnt} characters in ({my_string})")

9

Code sample: for statement with a set

1

 week_set = set(('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'))

2

 for w in week_set:

3

    print(w)

4

Code sample: for statement with a dictionary

1

 week = {1: 'Mon', 2: 'Tue', 3: 'Wed', 4: 'Thu', 5: 'Fri', 6: 'Sat', 7: 'Sun'}

2

 for w in week.keys():

3

    print(week[w], " in key and value pair in dictionary")

4

def Statement

The def statement is used to define new functions or methods if defined within a class definition. The syntax of def statement is as follows:

def <function_name>(<list of arguments>):

  < code block >

where function_name should be a unique identifier within the current scope, and the list of arguments can be empty. The details of defining and using functions will be presented in Chapter 6. For now, you need only be concerned with the definition of a simple function so that you know how the def statement is used. The function is to calculate a given number x to the power of 10, and return x*x*x*x*x*x*x*x*x*x:

In [ ]:

def power10(x):

  s = x

  for i in range(9):

    s *= x

    return s

print(f'power10({2}) = {power10(2)}')

Out [ ]:

2 to the power of 10 = 1024

class Statement

The class statement is used to define new classes. The syntax of defining a new class that only inherits from the base class (object) is as follows:

Class class_name:

  < suite >

or

Class class_name(object):

  < suite >

To define a new class that inherits from classes other than object, the syntax is as follows:

Class Class_name(<list of base classes>):

  < suite >

try-except Statement

The try-except statement is used to handle errors and exceptions, especially when certain errors are expected. The following are some common types of errors that you may encounter in your programs:

ArithmeticError

FileExistsError

LookupError

FloatingPointError

FileNotFoundError

IndexError

OverflowError

InterruptedError

KeyError

ZeroDivisionError

IsADirectoryError

MemoryError

AssertionError

NotADirectoryError

NameError

AttributeError

PermissionError

UnboundLocalError

BufferError

ProcessLookupError

BrokenPipeError

EOFError

TimeoutError

ConnectionAbortedError

ImportError

ReferenceError

ConnectionRefusedError

ModuleNotFoundError

RuntimeError

ConnectionResetError

Refer to https://docs.python.org/3/library/exceptions.html for a detailed discussion about the exceptions and error types defined in Python.

The following is an example showing how to handle errors from user input that use 0 for the denominator.

Code sample: for statement with dictionary

1

 try:

2

    a = int(input("give me a number:"))

3

    b = int(input("give me another number:"))

4

    print(f"{a} / {b} = {a / b}")

5

 except ZeroDivisionError:

6

    print(f"incorrect second input {b}!")

7

The details of error and exception handling in programs will be discussed in Chapter 4.

with Statement

The with statement is used to provide a context for the execution of a code block. The mechanism is a bit complex, but the following may provide some help. Remember that the with statement works only on objects that have special methods __enter__() and __exit__() implemented in accordance with Python context management protocol (PEP 343). For the mechanisms behind the with statement, read https://effbot.org/zone/python-with-statement.htm or search the internet for more details.

The general syntax of the with statement is as follows:

With <expression of object> as < variable referring to the object>:

<suite>

where the value of <expression of the object> will be an object on which the context management protocol has been implemented and the <variable referring to the resulted object> will often be used in the suite. A good and common example of using the with statement is dealing files, which, when opened, are objects with context management protocol implemented. The following is an example:

Code sample: with statement

1

 """

2

 This program will get an input of a big integer from user, and

3

 find all the prime numbers not greater than the integer input from the user, and

4

 write all the prime numbers into a text file.

5

"""

6

 m = int(input("""

7

    Please tell me a big integer number and

8

    then I can find all the primes less than

9

    the prime number:"""))

10

 import math as mt

11

 with open("c:\\workbench\\myprimes.txt", 'w') as p:

12

    i = 2

13

    while i <= m:

14

      flag = True

15

      j = 2

16

      while j <= int(mt.pow(i,1/2)) + 1 and flag:

17

        if i % j == 0:

18

          flag = False

19

          j += 1

20

        if flag:

21

          p.write(str(i)+ "\n")

22

          i += 1

Chapter Summary

  • • Vocabulary is important for any language, and even more important for computer languages, because computers will not understand your programs at all if you have used the wrong vocabulary.
  • • For programming languages, including Python, vocabulary includes various types of data, operators, built-in functions, reserved words (including keywords), and variables identified by user-defined names (also called identifiers).
  • • Identifiers must begin with a letter or underscore in the ASCII table, then be followed by letters, digits, and/or an underscore.
  • • Identifiers in Python are case-sensitive, which means that A1 and a1 are two different identifiers.
  • • Within the Python community, there are conventions for how identifiers should be made and used for identifying different things in Python programs.
  • • Simple data types include integer numbers, float numbers, Boolean numbers, and complex numbers.
  • • Complex numbers are represented as a + bj or a − bj, where a and b are integers or float numbers.
  • • Compound data are made of other data that can be of two types: simple or compound.
  • • A string is a sequence of characters within a pair of single or double quotation marks.
  • • Some special characters in a string must be represented using an escape sequence, such as \n for newline, \t for tab, and \\ for a backslash, and so on.
  • • In a string, all characters are indexed starting from 0, so that each individual character can be accessed using its index.
  • • There are many functions available to manipulate strings.
  • • There are three ways of formatting strings: using placeholders, using the format method, and using the f prefix before a string. The last one is preferred.
  • • A list is a sequence of data within a pair of square brackets.
  • • Members of a list are also indexed, and each individual member can be accessed through its index.
  • • A tuple is a sequence of data within a pair of parentheses.
  • • Members of a tuple are also indexed, and each individual member can also be accessed through its index.
  • • While individual members of a list can be deleted or changed, individual members in a tuple cannot be deleted or changed.
  • • A set is a collection of data within a pair of curly braces.
  • • Members in a set are not indexed, so individual members in a set cannot be accessed through the index.
  • • A dictionary is a collection of key-value pairs within a pair of curly braces.
  • • Keys are used to access the values of a dictionary.
  • • In Python, everything can be treated as an object.

Exercises

  1. 1. Indicate which of the following are not legitimate Python identifiers to name variables, functions/methods, and classes, and explain why.

This

3da

My_name

for

i9

vote

$s

_sum_

cLearance

method

lists

t5#

  1. 2. Write a single statement to complete each of the following tasks:
    1. a. Read an integer from user into variable k.
    2. b. Print a multiple-line mailing label with your name and home address, including the postal code.
    3. c. Print the area of a circle with a radius of 13.
    4. d. Assign the cube of 23 to variable x.
    5. e. Print the square of 12, 25, and 56, respectively, on one line.
  2. 3. Evaluate the following expressions
    1. a. 23 + 16 / 2
    2. b. round(78.3)
    3. c. pow(2,3) + 5
    4. d. sum([1,3,5,7,9])/13
    5. e. bin(9)
    6. f. divmod(13, 5)
    7. g. int(38.6)//7
    8. h. (3.5 + 6.7j) + (5.3 + 12.9j)
    9. i. 'Well' * 3 + '!'
  3. 4. Mentally run the following code blocks and state what each code block will display.
    1. a. x = 5
    2.     y = 6
    3.     print(x + y)
    4. b. m = 5
    5.     k = 3
    6.     print(f’{m}**{k} = {m**k}’)
    7. c. m, k = 35, 12
    8.     m //= k
    9.     print(m)
    10. d. m, k = 35, 12
    11.     m %= k
    12.     print(m)

Projects

  1. 1. Write a program to read a float number from the user into variable s, then calculate and print the area of a square with s as the length of its side.
  2. 2. Write a program to read two numbers and calculate the product of the two numbers.
  3. 3. A parking lot charges $2.50 per hour. Write a program to read the number of hours a vehicle has parked, then calculate and print the total to be paid for parking.
  4. 4. The arithmetic mean of several numbers is the sum of all these numbers divided by the number of these numbers. For this project, write a program that will generate three numbers from users and calculate and display the arithmetic mean of these three numbers.
  5. 5. A cube has 6 faces and 12 edges, all of the same length. Write a program that takes a number from the user as the length of an edge and calculate and display the total surface area of the cube.

Annotate

Next Chapter
Chapter 3. Flow Control of Statements
PreviousNext
Powered by Manifold Scholarship. Learn more at
Opens in new tab or windowmanifoldapp.org