© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
G. GutaPragmatic Python Programminghttps://doi.org/10.1007/978-1-4842-8152-9_1

1. Expression: How to Compute

Gabor Guta1  
(1)
Budapest, Hungary
 

“Expressions are formed from operators and operands.”

Brian W. Kernighan, Dennis M. Ritchie

One of the basic building blocks of programming languages is the expression, which serves to describe a logical or mathematical relation . In this chapter, you will learn how exactly an expression denotes relations between objects, how expressions can be used in statements, and how the objects can be labeled by names.

As an example, take the calculation of the price of an order. The formula is as follows: the price of the product multiplied by the quantity plus the shipping cost. Let’s look at how it is calculated in Python if the product’s price is 500 USD, two pieces are ordered, and the shipping cost is 200 USD.

Listing 1-1 shows an expression consisting of numbers (integers) and operators . The order of operations is determined by specific rules (much like those you can recall from your elementary school education).
500*2 + 200
Listing 1-1

A Simple Expression

Caution

Spaces should not be inserted before the expressions and statements shown in this chapter, and they should not be broken into multiple lines. This is important as the space(s), tabulators at the beginning of the lines, and line breaks do have a special meaning in Python. The relevant rules are detailed later in the chapter.

The computer processes the expression in Listing 1-1 in multiple steps. Integers are considered objects, which, in this case, are integer type ones. The structure referred to as the expression tree and shown in Figure 1-1a is constructed of integer objects and operators . In the figure the rectangles are objects or operators; if the objects correspond to an operator, they are linked with lines to the operator. You can find a bit more about this standard notion at the end of the chapter. The expression tree is constructed by assigning objects to an operator, among which the operation is to be performed. In the expression tree, the result of another operator can also be assigned to an operator, not just an object. This is indicated by connecting it to another operator, meaning that it is to be performed first, and the resulting object will be used then. The uppermost element of the expression tree is the operator to be performed last.

The computer interprets the expression tree by performing the operators between objects first. In the example, this is the leftmost multiplicative operator at the bottom. The result of this operator will be a new integer object with the value of 1000. Figure 1-1b shows the resulting intermediate expression tree , along with the addition operator between the integer objects with the values 1000 and 200, and the result is an integer object value 1200, as shown in Figure 1-1c.

An illustration has 3 parts. Left one depicts integer 500, integer 2 are under operator asterisk, operator asterisk, integer 200 are under operator plus. The middle one depicts integer 1000, and integer 200 under the plus operator. The right one depicts the integer 1200.

Figures 1-1a, 1-1b, and 1-1c

Simple expression

If there is uncertainty about the operation order, placing brackets is encouraged, as in Listing 1-2.
((500*2) + 200)
Listing 1-2

Fully Parenthesized Expression

The expression without brackets and the fully bracketed expression have the same meaning for the computer. Notably, the expressions can be of any complexity; however, there is a certain level of complexity where they become difficult to understand.

Expressions with Additional Types

In Listing 1-1, we have seen integers as objects on which to perform the operators. Expressions , however, can be used in the general sense, whereas operators can be performed between objects of various types. In addition to the integer type objects, other types of objects will also be covered, e.g., Boolean types (true/false values) and strings. You will learn how to create your own type in Chapter 3.

The type of the particular object is important also because certain operators can be executed only by objects of a specified type. If, for example, an attempt was made to add an integer and a string, an error will be raised. When the operation has been successfully executed, the resulting object will always have a type (determined by the operation, the object performing the operation, and the type of the other object participating in the operation).

Boolean Type in an Expression

Listing 1-3 shows an expression where two integers are compared. When comparing two integers, the created new value will be of the Boolean type . The true value is denoted by the word True, while the false value is represented by False. Part of this expression tree on the left side of the comparison sign is the same as the previous example, and its evaluation is also the same. Thus, the last step will be carrying out the comparison, wherein the result of comparing the two integers will be a True object.
500*2 + 200 >= 1000
Listing 1-3

Boolean Expression

String Type in an Expression

Listing 1-4 contains string objects. The string type objects are characters between single or double quotation marks. From these quotation marks, the computer will know where characters forming the string begin and where they end and that there is no need to interpret them, just to handle them as any text. The addition operator between strings means concatenation. The first step upon evaluation of this expression is the formation of a novel string object from the two left string objects, and then in the next step, the resulting string object is created by the concatenation of the newly created string object and the right-side object.
'no' + ' ' + 'discount'
Listing 1-4

Operation Between Strings

Expressions with Conditional Operators

A conditional expression can describe the computation that the result should be one or another value depending on some condition. This expression is interpreted among three objects. The first object is of any type, the supposed value when the condition is fulfilled. The second object is of Boolean type , the condition itself, after the word if. The last object is the expected value when the condition is not fulfilled, located after the word else. (As you would expect, any of the objects can be substituted with an expression.) Listing 1-5 demonstrates how to combine the conditional expression with the types reviewed so far.
'5%' if 500*2+200 >= 1000 else 'none'
Listing 1-5

Conditional Expression

The task solved by the example is the following: if the amount of the order is greater than 1000, a string containing the discount rate would be created with the values 5% or none. Figure 1-2 shows the expression trees formed upon evaluation of the expression.

An Illustration has 5 parts. a. integer 500, integer 2 are under operator asterisk; operator asterisk, integer 200 are under operator plus; operator plus, integer 1000 are under greater than or equal to operator, that is under if-else operator, along with string 5 percent, string none. Expression is evaluated in b, c, d, and e depicts string 5 percent.

Figures 1-2a, 1-2b, 1-2c, 1-2d, and 1-2e

Expression with multiple types

Floating-Point Number Type in an Expression

Finally, let’s look at the number types. Three kinds of number types are distinguished in Python : integers, floating, and complex numbers. You have already seen examples for the integers. The float type can store the decimal fractions. Listing 1-6 shows an expression wherein two decimal fractions with the same value are added (the first number object was written in the usual format as 0.05, while the other one was in 5*10-2 format).
0.05 == 5e-2
Listing 1-6

Floating-Point Numbers

Complex Number Type in an Expression

Complex numbers (used in higher mathematical computations) are called the complex type . The simplest way a complex number could be considered is a pair of decimal fractions wherein the first one is the real value, and the second one is the imaginary one. The imaginary value corresponds to the square root of -1. It is checked in Listing 1-7, if (0+1j)2 is really equal to the value of -1.
(0+1j)**2 == -1
Listing 1-7

Complex Numbers

During the design of the Python language , it was a vital design decision that it should contain a small number of built-in types, and at first sight, the behavior of those types is the same as that of the other, not built-in types. Only five data types are examined more thoroughly here; the rest will be discussed in Chapters 5 and 6.

Tip

In the Python language , it is possible to put the comparisons into a chain, meaning the 0 < a and a < 100 expressions can be written in the form of 0 < a < 100. The two expressions are equivalent, except that in the second case the expression standing in the place of a is computed only once. This notation can also be used between more than two comparisons.

Variable Names

Now that we have seen how to carry out computation in specific cases, let’s look at how a computation can be generalized. For this case, objects are assigned to variable names. Variable names may be thought of most simply as labels. Variable names usually begin with a letter and continue with letters or digits. The expression in Listing 1-5 could be rewritten by first assigning the numbers to variable names , as shown in Listing 1-8. The advantage of this approach is that in case we were to compute the expression for other numbers, we simply change only the assignment statements in lines 1–3 and would not have to modify the expressions.
PRICE = 500
QUANTITY = 2
LIMIT = 1000
total_amount = PRICE * QUANTITY
d_available = total_amount >= LIMIT
discount = '5%' if d_available else 'none'
Listing 1-8

Assignment Statements

To express the intent that the variable names to which the value once assigned will not require change, the variable names are capitalized. This notation is not more than a convention, and the Python language does not prevent them from being changed.

The resulting expression is thus much easier to understand. Importantly, not the formula itself is assigned to the variable name, but an object created upon computation of the expression instead. It is always necessary to assign an object to the variable name before it is used (it must appear on the left side of the equation before it can appear on the right side).

Variable names are also used to break down complicated expressions into simpler ones. This can be accomplished by assigning some part of the expression to the variable names and then using the variable names in place of the extracted expressions. Furthermore, if the variable names assigned to the particular expressions are chosen well, the meaning of the expression will be more explicit.

Tip

When do you have to insert space between characters? The short answer is: when the characters without space would evidently have a different meaning. For example, the meanings of a + b and a+b are the same; thus, the space can be left out. But the cases of a b and ab are different; the two names (identifiers) would become a single name. Table 1-1 shows some examples. If spaces do not affect the meaning, they can be inserted or omitted, depending on readability. The detailed answer will be given in the section “Advanced Details.”

Table 1-1

Effects of Spaces Between Characters

Without Space

With Space

Interpretation

a+b

a + b

Identical.

a=2

a = 2

Identical.

ab

a b

Adding a space between alphabetic characters turns the single name into two separate names, which are in most cases syntactically incorrect (an important exception is when one of the names is a keyword).

12

1 2

Adding a space between numeric characters turns a single literal into two separate literals, which are in most cases syntactically incorrect.

a1

a 1

Adding a space between an alphabetic and a numeric characters turns the single name into a name and a literal, which are in most cases syntactically incorrect (an important exception is when the name is a keyword).

1a

1 a

Adding a space between a numeric and an alphabetic characters turns the syntactically incorrect character sequence into a literal and a name, which are in most cases also syntactically incorrect (an important exception is when the name is a keyword like 1 or); in earlier versions of Python 1or character sequence was syntactically correct, but know it is deprecated and will cause a syntax error in the future.

Statements

Listing 1-8 showed a program consisting of multiple lines. Each line is one statement, more precisely an assignment statement. Programs consist of statements that are executed one after the other, thereby exerting some effect on their environment. The default in Python is that one line is one statement. The recommended maximal line length is 79 characters. Listing 1-9 shows how a long statement can be stretched to multiple lines (lines 3 to 7) or multiple statements can be condensed into a single line (line 7). When a line is too short for a statement, part of the statement can be brought over to the following line after an end-of-line backslash (). Should we want to compact multiple statements in a line, the statements would have to be separated by a semicolon (;). Both notations should generally be avoided.
PRICE = 500
QUANTITY = 2
PRICE =
500
QUANTITY =
2
PRICE = 500; QUANTITY = 2
Listing 1-9

Statements

Integer objects are assigned to variable names in the previous example. If, for example, statements in the second and third lines were replaced, an error would occur since there are no objects yet assigned to the quantity label. It is also a consequence of the stepwise statement execution that no object assigned to a variable name would change (except for the unit price) if one more PRICE = 450 line were inserted at the end of the program. For example, the d_available variable name would still point to an object with a true value. To change the assignments, the statements from line 3 to line 5 would have to be re-executed.

The assignment statement consists of a name, an assignment operator, and an expression. In Python , the equal sign means the result of the right- side expression is assigned to the left-side variable name. (The double equal sign is used to test the equality of two expressions.) The assignment statement is not an expression; therefore, it does not have a return value. To obtain an object assigned to the variable name as an expression, the := walrus operator can be used, but it can be used only in restricted cases (details of the walrus operator will be explained in Chapter 5).

Deletion of a Variable Name

Variable names can also be deleted by the del statement. In Listing 1-10, after the variable name difference is deleted, reading the variable name content results in an error. Objects assigned to the variable names are automatically unallocated when they are not referenced anymore (i.e., when they are not assigned to any variable names). Referencing to the variable name difference after Listing 1-10 would cause a NameError error.
difference = 550 - 500
del difference
Listing 1-10

Deletion of a Variable Name

Note

The source code elements are the expressions, statements, and concepts touched upon later. The name source code (a code readable for humans) originates from the fact that it is the source of the executable code run by the computer. Files containing the source code are referred to as source files . We can speak about a program when we want to emphasize that it is about the source code realizing an independent and meaningful task. For completeness, programs that can be run as direct source code are usually called scripts . Unfortunately, these denominations are often used loosely in the literature and leave the correct interpretation to the reader.

Additional Language Constructs

In the program fragments described so far, objects are expressed by specific integer, string, and Boolean (True and False) values. Their collective term is literals . Operators are used between them. You have seen the if and else names in the conditional expressions . Names with such special meaning are called keywords . The pass keyword represents the no operation statement. This statement is used to designate that a statement would follow, but our deliberate intention is that nothing happens at that point of the program.

The text located after the character # up to the end of the line is called a comment that is used to place any textual information. A comment is a message to the reader of the source code and can help in understanding the program. If variable names in the program are chosen well, a minimum amount of commenting is necessary.

Multiline comments can be achieved with multiline strings. Multiline strings start and end with a triple quotation mark (typically """), and line breaks are allowed inside the string. Technically these are not comments, but expressions. So, multiline comments must always start in a separate new line. You will see in Chapter 2 that these multiline comments can have a special role depending on their position in the source code . Listing 1-11 shows some examples.
pass #this statement does nothing
# this line is only a comment
""" these lines form
a multiline
comment """
Listing 1-11

Pass Statement and Comments

Statements and Expressions in Practice

With type annotations, the expected type of object to be assigned to the variable name can be expressed. Python is a dynamically typed language, which means that the type of a variable name depends solely on the type of the assigned object. This means that currently Python does not check if these type annotations are correct. Originally, Python did not have any notation to explicitly add typing information as it was considered extra effort to maintain and makes the code more inflexible. As Python is used for large and complex programs, these annotations become more useful for the developers and tools. External tools can be used to verify whether the assigned object types are consistent with the type annotations without running the program. Use of external tools will be described in Chapter 6. The type is specified after the variable name, separated from it by a colon, as shown in the Listing 1-12.
PRICE: int = 500
QUANTITY: int = 2
LIMIT: int = 1000
total_amount: int = PRICE * QUANTITY
d_available: bool = total amount >= LIMIT
discount: str = '5%' if d_available else 'none'
Listing 1-12

Assignments with Type Definitions

It is crucial for the readability of the program to put spaces in certain spots in the expressions and statements. The documentation of Python contains a recommendation for the placement of spaces to ensure the best readability:
  • It is recommended to insert a space on both sides of an equal signs; and put a space only after colons.

  • Extra spaces should not be inserted for parentheses, but spaces are recommended so that the context is preserved.

  • Spaces are inserted around the operators as a default; an exception is if the order of operations in the expression is other than simply from left to right, since there are parentheses, or certain operations should be executed sooner. In this case, spaces are removed around operations executed sooner, such as in the case of (a+2) * (b+4) or a*2 + b*4.

If required, the aim or use of the statements can be documented by a comment placed after it (beginning with the character #, as discussed earlier). Lengthier comments can be placed among the statement lines, and each line should begin with the character #. It is recommended that the information recorded here should be such that it could not be figured out from the variable names and the type annotations.

Tip

An expression can be included in the so-called formatted string literals (or f-strings). In this case, there is a letter f (as shown in Listing 1-13) before the string’s opening quotation mark, and the expressions are within the quotation marks, between the braces. The result of these expressions will be inserted after they are converted to a string.

In the f-strings , format specifiers can also be added after the expression, separated by a colon (:). Listing 1-14 shows the format of the variable PRICE1 as a decimal fraction with two decimal places and shows writing out variable PRICE2 as an integer filled with 0s, up to five digits.

PRICE1 = 10
PRICE2 = 2500
Difference of f’{PRICE1} and {PRICE2} is {PRICE2-PRICE1}'
Listing 1-13

Formatted String Literals

f'{PRICE1:.2f}, {PRICE2:05d}'
Listing 1-14

Formatted String Literals with Format Specifiers

Advanced Details

This section describes technical details in reference manual style and advanced concepts that may need more technical background.

Names

You saw that names (also called identifiers) can be given to objects. The following characters can be present in a name: beginning with a letter or an underscore and continuing with a letter-like character, underscore, or digit. Letter-like means that other categories are added to characters considered letters in the Unicode standard, namely, the “nonspacing mark,” the “spacing combining mark,” and the “connector punctuation” categories. Within names Python discriminates lowercase and uppercase letters, but certain character combinations can be regarded the same according to the NFKC standard. It is recommended to use only letters of the English alphabet in names.

Keywords and Special Names

There are certain names that have special meaning in Python ; these are called keywords and are shown in Table 1-2. You have already learned the meanings of the keywords True and False, and the meanings of the other ones will be gradually introduced in subsequent chapters.
Table 1-2

Keywords

and

as

assert

async

await

break

class

continue

def

del

elif

else

except

False

finally

for

from

global

if

import

in

is

lambda

None

nonlocal

not

or

pass

raise

return

True

try

while

with

yield

Names both beginning and ending with a double underscore character may have a special meaning in the Python language . Therefore, your own variables should not be denoted in this way. A single or double underscore only at the beginning of the name is not subject to this restriction. Their function is detailed in Chapter 3. A single underscore after a variable name is used in case the name would otherwise be a keyword . Finally, a single underscore character as a variable name is used to signal that the value of the variable won’t be used, but defining a variable name is required for syntactic constraints.

Literals

Literals represent objects corresponding to their meanings. Rules applied to the bool, complex, float, int, and str type values are as follows:
  • The value of a Boolean can be true or false. The true value is denominated by True, while false is signified by False.

  • There are also rules applied for integers . Simple decimal integers begin with a digit that is not zero and continue with any digit. If a zero is written, any integer of zeros can follow, but no other digits. If an integer is written in a system other than decimal, the b, o, or x letters after a zero digit annotate the following number in the binary, octal, or hexadecimal number system; then the particular number itself is written according to the rules of the particular number system. (For example, in terms of the binary number system, digits can be only 0 or 1, while in the case of the hexadecimal system, besides the number 9, the lowercase or uppercase letters between A and F are allowed. Lowercase or uppercase letters are both allowed for the letters denoting the number system, as they are for the numbers in the hexadecimal system.) Numbers can always be separated by underscoring. Listing 1-15 shows examples of the previously mentioned syntax.

42
0b10_1010
0o52
0x2A
Listing 1-15

Integers in Various Number Systems

  • Floats or, more precisely, floating-point numbers, are those always represented in the decimal system: a dot is placed within the integer or around it, or the integer exponent of number 10 multiplying the particular number is written after the number, separated by a letter e. Floating-point numbers used in Python are according to the IEEE 754 standard.

  • Complex numbers , in turn, can be represented by two floats. One of them is the imaginary part that is denoted by a letter j written after a float; according to this notation, the 1j corresponds to the square root of -1.

  • Strings are written between pairs of quotation marks, ' or ". The meanings of the two kinds of quotation marks are the same, but it is recommended to select one and use that one consistently. An exception is when the original text itself contains a kind of quotation mark. In this case, it is recommended to use the other kind at both ends of the string. If you want to write a multiline string, it will have to be between the characters of ''' or """. Any character except the quotation mark can appear within a string. If you would like to write the same characters as the opening and closing quotation marks, we have to use a backslash character before them. After the backslash, other characters can denote otherwise not representable characters (according to Table 1-3).

  • The character r can be present before strings with the effect of the backslash character working as a simple character. This is useful in describing access paths (for example, the r 'C:Users' notation is equivalent to 'C:\Users') and regular expressions. The letter f can also be present before strings, meaning that if an expression is written between the characters { and }, it is computed, and the result will be inserted as a string (see the former paragraph on formatted string literals ). The letter b may also occur; you can find a more detailed description about it in Appendix B.

Table 1-3

Escape Character Table

Character

Meaning

and “new line”

The backslash and the new line will be ignored.

\

The backslash itself ().

a

ASCII bell character (BEL).



ASCII backspace (BS).

f

ASCII form feed (FF).

ASCII linefeed (LF).

ASCII carriage return (CR).

ASCII horizontal tabulation (TAB).

v

ASCII vertical tabulation (VT).

ooo

Character code with a value of ooo in an octal number system.

xhh

Character code with a value of hh in a hexadecimal number system.

Characters with Special Meaning

Table 1-4 summarizes characters having a special meaning in Python. Operations are denoted in the expressions by the operator characters. Delimiters occur primarily in statements. Other special characters serve to denote values or comments. There are characters that can be used only in literals.
Table 1-4

Characters with Special Meaning

Category

Characters

Operators

<<

>>

&

^

~

:=

 

<

>

<=

>=

==

!=

 

Delimiters

,

:

.

;

@

=

->

+=

-=

*=

/=

//=

%=

@=

&=

|=

^=

<<=

>>=

**=

 

Other special characters

"

#

   

Can be used only in strings

$

?

    

The dot can appear within a decimal fraction. Three consecutive dots may be present one after the other, which is called an ellipsis literal . This is not used in core Python, only in some extensions (e.g., NumPy).

Table 1-5 shows that the precedence of the operators is shown downward increasing. Stronger operations will be performed first. If strengths were equal, applying the operations takes place from left to right. An exception is exponentiation with a reverse direction of application.
Table 1-5

Precedence of Operators

Operators

Meaning

x := y

Assignment expression

x if y else z

Conditional expression

x or y

Logical or

x and y

Logical and

not x

Logical negation

x in y, x not in y,x is y, x is not y,x < y, x <= y, x > y,x >= y, x != y, x == y

Membership tests,identity tests, and comparisons

x | y

Bitwise or

x ^ y

Bitwise exclusive or

x & y

Bitwise and

x << y, x >> y

Bitwise shift

x + y, x - y

Addition, subtraction

x / y, x // y, x % y

Division, integer division, remainder

+x, -x, ~x

Positive, negative, bitwise negation

x**y

Raising to the power

(x)

Expression in parentheses

Python Standards

The Python language is defined in The Python Language Reference. The content of the book covers basically this document. In addition, several language-related standards will be described in the Python Enhancement Proposals; they are usually referenced as PEP plus a number. An often mentioned PEP document is PEP 8, which contains a recommendation for formatting the Python source code.

Object Diagram Notation

Figures used in the chapter are represented in the object diagram notation of the Unified Modeling Language (UML) . These diagrams can represent objects and their connections of a particular moment. Rectangles represent objects in the diagrams. The names of the objects appear as text written into the rectangle. The names of the objects are always written underlined, optionally with its type after it preceded by a colon. Lines between the rectangles denote connections. Objects in the figures are denoted according to their value, and the value is not represented by a separate instance variable.

Key Takeaways

  • In the chapter, you learned about the concept of an expression, which is one of the most important building blocks of programming languages. An expression describes operations between objects. Usually, the goal of their usage is to construct a new object needed for the next step of processing (e.g., calculating the sum of the price of products).

  • The statements describe a step of a program and make changes in the execution context. The assignment statement, which assigns an object to a name, is a good example of this. An expression can serve as a statement, but statements cannot stand where expressions are expected.

  • The variable name is the first tool to organize your program. For example, a complex expression can be broken into several simpler expressions of which results are assigned to variable names and then combined in a final step.

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

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