Scope of variables
- A variable name only exists inside the body of the function in which it is created.
- It does not exist outside the function or in any other functions.
1def f():2 x = 33 print("In f(), x =", x)45f()6print(x)
In f(), x = 3 NameError: name 'x' is not defined
- The scope of a variable consists of parts of the program where the variable name exists and can be used.
- Each function has its own local scope, which other functions cannot access.
- global scope consists of names accessible by the entire module (Python file).
A variable created inside a function is called a local variable.
A variable created outside any function is called a global variable.
1def f():2 x = 3 # local variable3 # local x is used below!4 print("In f(), x =", x)567x = 100 # global variable8f()9print(x) # global x is used
In f(), x = 3 100
- As we saw above, it is possible to create a local variable with the same name as a global variable.
- These are considered two different variables, and inside the function only the local one will be used.
1def f():2 # global x is used below!3 print("Inside f(), x =", x)456x = 100 # global variable7f()8print(x)
Inside f(), x = 100 100
What will happen if the global variable x is created after the function call f()?
How variable name is looked up?
- Inside a function, when a name is used:
- First, name is searched within the function (local scope) to see if it exists.
- If name is not found in the function, it is searched globally
- Outside a function, name is simply searched globally
- If a name cannot be found anywhere (local or global scope), we get NameError complaining that the name is not defined.
What will be printed in each case?
1def f():2 y = 53 print(x)45x = 106f()
1def f():2 x = 53 print(x)45x = 106f()7print(x)
10
5 10
Function parameters are also local to the function.
Best Practice
- Try to avoid using global variables within functions when possible.
- It is okay to use variables that don’t change (e.g. constants such as π)
- It is also okay to use modules inside functions
Lists — Concatenation + and Replication *
1# lists a and b are joined to produce a third list c:2a = [1, 2]3b = [10, 11, 12]4c = a + b5print(c)6# [1, 2, 10, 11, 12]78a = [1, 2]9# resulting list consists of repeated items of list a:10c = a * 311print(c)12# [1, 2, 1, 2, 1, 2]
membership operators: in and not in
We can use them to test if an object is present in a list.
1a = [1, 2]2b = [10, 11, 12]34print(1 in a) # True5print(11 in a) # False6print(5 not in b) # True78x = 3.149print(x in a or x in b) # False
in/not in operators are very useful in simplifying code:
1# Instead of long conditions like this:2if x == 5 or x == 7 or x == 10:3 # do something
1# Now we can do:2if x in [5, 7, 10]:3 # do something
Slicing a list
Similar to strings, we can also get a sub-list — parts of a list — using slice notation. Slicing creates a new list.
1days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]23print(days[2:5])4# ['Wed', 'Thu', 'Fri']56print(days[:6:2])7# ['Mon', 'Wed', 'Fri']
1days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]23# Make a copy of the whole list4print(days[:])5# ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']67# Makes a reversed copy of the list8print(days[::-1])9# ['Sun', 'Sat', 'Fri', 'Thu', 'Wed', 'Tue', 'Mon']
Iterating through a list
We can either use an index or loop directly over items in a list:
1def average(nums):2 total = 034 for i in range(len(nums)):5 total += nums[i]67 return total / len(nums)89grades = [85, 100, 98, 75]10print(average(grades))
1def average(nums):2 total = 034 for x in nums:5 total += x67 return total / len(nums)89grades = [85, 100, 98, 75]10print(average(grades))
But when we need to modify a list inside a loop we have to use an index:
1def add_bonus(grades, bonus):2 """ Add bonus to each grade in grades list3 (grade should not exceed 100)4 Returns: None5 """6 for i in range(len(grades)):7 grades[i] = min(grades[i] + bonus, 100)8910assignment_grades = [55, 60, 67, 97]11add_bonus(assignment_grades, 5)12print(assignment_grades) # [60, 65, 72, 100]
Built-in functions that work with lists
1grades = [90, 70, 60.5, 70, 80]23# len(x):4# Returns the number of items in the list x.5print(len(grades)) # 567# sum(x):8# Returns the sum of all the numbers in list x.9# A TypeError occurs when some item is not a number.10print(sum(grades)) # 370.5
1grades = [90, 70, 60.5, 70, 80]23# min(x) / max(x) :4# Returns the smallest/largest item in the list x.5# A TypeError occurs if the items cannot be compared.67print(min(grades)) # 60.589print(max(grades)) # 901011print(min(["90", 70, 60.5, 70, 80]))12# TypeError: '<' not supported between instances of 'int' and 'str'
List methods
Python has several methods that we can call on a list object:
1# list.append(x): Adds the item x to the end of the list23grades = [90, 70, 60.5, 70, 80]4grades.append(100)5print(grades) # [90, 70, 60.5, 70, 80, 100]67grades.append("30")8print(grades) # [90, 70, 60.5, 70, 80, 100, '30']910grades.append(False)11print(grades) # [90, 70, 60.5, 70, 80, 100, '30', False]
Example:
1def filter_values(nums, threshold):2 ''' Return a new list to include numbers from3 the list nums that are above threshold4 '''5 new_list = []67 for n in nums:8 if n > threshold:9 new_list.append(n)1011 return new_list1213print(filter_values([3, 1, 2, 5, 4], 3)) # [5, 4]14print(filter_values([3, 1, 2, 5, 4], 5)) # []
1# list.insert(i, x): Adds the item x to the list at index i23grades = [90, 70, 60.5, 70, 80]4grades.insert(0, 100)5print(grades) # [100, 90, 70, 60.5, 70, 80]67# insert() works even when index is greater than length of list8grades = [90, 70, 60.5, 70, 80]9grades.insert(10, "B+")10print(grades) # [90, 70, 60.5, 70, 80, 'B+']
1# list.remove(x):2# Removes the first occurrence of the item x in the list.3# A ValueError occurs if there is no such item.45grades = [90, 70, 60.5, 70, 80, 'B+']6grades.remove(70)7print(grades) # [90, 60.5, 70, 80, 'B+']89grades.remove("B+")10print(grades) # [90, 60.5, 70, 80]1112grades.remove(60)13# ValueError: list.remove(x): x not in list
1# list.pop(i):2# Removes and returns item at index i3# list.pop():4# Removes and returns the last item from the list56grades = [90, 70, 60.5, 70, 80, 'B+']7last_item = grades.pop()8print(last_item) # B+9print(grades) # [90, 70, 60.5, 70, 80]1011second_item = grades.pop(1)12print(second_item) # 7013print(grades) # [90, 60.5, 70, 80]
1# list.count(x) :2# Returns the number of occurrences of the item x.34grades = [90, 70, 60.5, 70, 80, 'B+']5print(grades.count(70)) # 26print(grades.count("B+")) # 17print(grades.count(60)) # 0
1# list.index(x) :2# Returns the index of the first occurrence of item x in list.3# A ValueError occurs if item x is not found in list.45grades = [90, 70, 60.5, 70, 80, 'B+']67print(grades.index(70)) # 18print(grades.index(60)) # ValueError: 60 is not in list
1# list.extend(sequence) :2# Extend list by appending items from the sequence.34grades = [90, 70, 60.5, 70, 80]56grades.extend([100, 95])7print(grades) # [90, 70, 60.5, 70, 80, 100, 95]89grades.extend("cat")10print(grades)11# [90, 70, 60.5, 70, 80, 100, 95, 'c', 'a', 't']
Lists and Strings
There are built-in functions and string methods that allows us to transform strings to/from lists.
1# list(seq): built-in function which converts a sequence (such as2# a string or a list) into a list34fruit = "apple"5letters = list(fruit)6print(letters) # ['a', 'p', 'p', 'l', 'e']
1# s.split(): Breaks the string s using whitespace2# (spaces, tab character and newline) as the separator and3# returns a list of strings containing the separated parts45data = "Red Green Blue"6names = data.split()7print(names) # ['Red', 'Green', 'Blue']89# Multiple spaces are also removed10data = " Red Green Blue "11names = data.split()12print(names) # ['Red', 'Green', 'Blue']
1data = "Red\tGreen\tBlue" # separated by tab2names = data.split()3print(names) # ['Red', 'Green', 'Blue']45data = """Red6Green7Navy Blue"""8names = data.split()9print(names) # ['Red', 'Green', 'Navy', 'Blue']
1# s.splitlines(): Breaks a multi-lines strings into separate lines2# and returns a list containing those lines.34data = """Red5 Green6Navy Blue7"""8names = data.splitlines()9print(names) # ['Red', ' Green', 'Navy Blue']
1# s.strip(): Return a copy of the string with2# leading and trailing whitespace removed.3# s.lstrip(): removes leading whitespace only4# s.rstrip(): removes trailing whitespace only56name = " Green "7print("|" + name + "|")8print("|" + name.strip() + "|")9print("|" + name.lstrip() + "|")10print("|" + name.rstrip() + "|")
| Green | |Green| |Green | | Green|
1# s.strip(chars): Return a copy of the string2# with leading and trailing chars removed.3# s.lstrip(chars): removes leading chars only4# s.rstrip(chars): removes trailing chars only56text = "...#some . text #..."78print(text.strip("."))9print(text.lstrip("."))10print(text.rstrip("."))1112# multiple chars to remove13print(text.strip(". #"))
#some . text # #some . text #... ...#some . text # some . text
1# s.split(sep): Breaks the string s using the separator string sep2# and returns a list of strings containing the separated parts34data = "Red,Green,Blue"5names = data.split(",")6print(names) # ['Red', 'Green', 'Blue']78data = "Red, Green, Blue"9names = data.split(",")10print(names) # ['Red', ' Green', ' Blue']11# notice space in strings above
1# sep.join(L): joins all the strings in the list L using2# the string sep and returns the joined string.34names = ['Red', 'Green', 'Blue']5joined = " ".join(names)6print(joined) # Red Green Blue78# a comma9joined = ",".join(names)10print(joined) # Red,Green,Blue
1# a comma and a space2names = ['Red', 'Green', 'Blue']3joined = ", ".join(names)4print(joined) # Red, Green, Blue56# empty string, no separator7letters = ["a", "p", "p", "l", "e"]8joined = "".join(letters)9print(joined) # apple
Try the problem “Parsing a string” on Ed Lessons.
Try the problem “Puzzle: Switching 100 light bulbs” on Ed Lessons.