Some of today's topics are covered in these sections of Think Python:
And in these chapters of Introducing Python:
5. Text Strings
7. Tuples and Lists
9. Functions
Here are some additional notes.
Python includes f-strings, which are formatted strings that can contain interpolated values. For example:
color1 = 'blue' color2 = 'green' print(f'The sky is {color1} and the field is {color2}')
Write the character f
immediately before a string
to indicate that it is a formatted string. Interpolated values can be
arbitrary expressions:
x = 14 y = 22 print(f'The sum is {x + y}.')
You may optionally specify a format code after each interpolated value to indicate how it should be rendered as a string. Some common format codes include
d – an integer in decimal (base 10)
x – an integer in hexadecimal (base 16)
f – a floating-point number in fixed-point (i.e. not exponential) notation. This format code may optionally be preceded by a period ('.') followed by an integer precision, which indicates how many digits should appear after the decimal point.
For example:
m = 127 e = 2.718281828459045 print(f'm in hex is {m:x}') # prints 'm in hex is 7f' print(f'e is {e:.4f}') # prints 'e is 2.7183'
There are many more format codes which you can use to specify exact field widths, whether values should be left- or right-justified, and so on. See the Python library documentation for a complete description of these.
Suppose we create a couple of lists as follows:
>>> x = [3, 5, 7, 9] >>> y = x >>> z = [3, 5, 7, 9]
Now the variables x and y refer to the same list. If we change x[0], then the change will be visible in y. However, z is a different list, and a change to x[0] will not be visible there:
>>> x[0] = 33 >>> y[0] 33 >>> z[0] 3
Python provides two different operators for testing equality. The
first is the ==
operator:
>>> x == y True >>> x == z True
This operator tests for structural equality. In other words, given two lists, it compares them element by element to see if they are equal. (It will even descend into sublists to compare elements there as well.)
The second equality operator is the is
operator:
>>> x is y True >>> x is z False
This operator tests for reference equality. In other words, it returns true only if its arguments actually refer to the same object.
You may
want to use each of these operators in various situations. Note that
is
returns instantly, whereas == traverses lists in their entirety and
so may be slower if lists are large.
Consider this program:
def inc(i): i += 1 print(i) j = 7 inc(j) print(j)
The program will print
8 7
Here is why. First the function inc receives the value i = 7. The statement "i += 1" sets i to 8, and inc writes this value.
Now control returns to the top-level code after the function definition. The value of j is still 7! That's because Python passes integer arguments by value: a function receives a local copy of the value that was passed. A function may modify its local copy, but that does not change the corresponding value in the caller, i.e. the code that called the function. And so the second number printed by this program is 7.
Now consider this variant:
def inc(l): l[0] += 1 print(l[0]) a = [3, 5, 7] inc(a) print(a[0])
This program will print
4 4
This program behaves somewhat differently from the preceding one, because Python passes lists by reference. When the program calls inc(a), then as the function runs l and a are the same list. If we modify the list in the function, the change is visible in the caller.
Really this is similar to behavior that we see even without calling functions:
a = 4 b = a a += 1 # does not change b a = [4, 5, 6] b = a a[0] = 7 # change is visible in b[0]
Consider this Python program:
x = 7 def abc(a): i = a + x return i def ha(): i = 4 print(abc(2)) print(x + i)
The variable x declared at the top is a global variable. Its value is visible everywhere: both inside the function abc(), and also in the top-level code at the end of the program.
The variables i declared inside abc() and ha() are local variables. They are different variables: when the line "i = a + x" executes inside abc(), that does not change the value of i in ha().
Now consider this variation of the program above:
x = 7 i = 4 def abc(a): i = a + x return i print(abc(2)) print(x + i)
In this version, the variables x and i declared at the top are both global. abc() declares its own local i. This is not the same as the global i. In particular, when abc() runs "i = a + x", this does not change the value of the global. The local i is said to shadow the global i inside the function body.
Local variables are a fundamental feature of every modern programming language. Because a local variable's scope (the area of the program where it is visible) is small, it is easy to understand how the variable will behave. I recommend making variables local whenever possible.
In the program above, what if we want the function abc() to use the global i, rather than making a new local variable? We can achieve this by declaring i as global:
x = 7 i = 4 def abc(a): global i i = a + x return i print(abc(2)) print(x + i)
Now the line "i = a + x" will update the global i.
Notice that in all of the programs above, abc() is able to read the global x without declaring it as global. But if a function wants to write to a global variable, it must declare the variable as global.
To be more precise, here is how Python determines whether each variable in a function is local or global:
If there is
a global
decaration, the variable is
global.
Otherwise, if the function only reads the variable, it is considered global (and must be defined somewhere outside the function). If the function ever writes to the variable, it is considered local.
Note that it is impossible to write a function that uses both a local variable "x" and also a global variable "x". Each variable name such as "x" is either always local or always global within a single function body.
We solved this exercise in the tutorial:
A country is holding a lottery in which 5 winning numbers are chosen at random from the range 1..25. No two of these numbers will be the same. For example, the winning numbers could be 2 – 4 – 9 – 18 – 22, or 5 – 6 – 11 – 15 – 24.
Write a program that randomly selects 5 winning numbers and prints them on a single line in ascending order.
Here's the solution we wrote:
import random l = 26 * [ False ] # l[0], l[1] .... l[25] count = 0 # how many numbers we have already while count < 5: i = random.randint(1, 25) if not l[i]: l[i] = True count += 1 s = '' for i in range(1, 26): if l[i]: s = s + str(i) + ' ' print(s)
Here's another possible solution, which you may wish to compare with the preceding one:
import random nums = list(range(1, 26)) # [1, 2, ... 25 ] selected = [] for x in range(5): k = random.randint(0, len(nums) - 1) selected.append(nums[k]) del nums[k] s = '' for i in sorted(selected): s = s + str(i) + ' ' print(s)