This lecture further explains different types of variables in Python, branching statements, how to define functions, and what Python modules are.
Programming glossary
The following table summarizes some of the important keywords in this lecture for you.
Expression | Description |
---|---|
dictionary | A collection of `key:value` mapping pairs, in which the values can be obtained by calling the value's key. |
hashable | A Python object (e.g., variable) that has a hash value which never changes during its lifetime. |
immutable | A variable or value that cannot be modified. Assignments to elements of immutable values cause a runtime error. Example immutable Python entities are tuples and strings. |
invocation | The process of calling an object's method, usually done through <object name>.<method name> notation. |
list | A sequence of comma-separated heterogenous values next to each other. |
method | Similar to a function, a method is a predefined built-in Python script that performs a specific task on the data object to which the method belongs. |
mutable | A variable or value that can be modified. Examples of mutables in Python are lists, and dictionaries. |
set | An unordered collection of unique elements, just like the mathemtical sets. |
string | A sequence of characters next to each other. |
tuple | An immutable data value that contains related elements. Tuples are used to group together related data, such as a person’s name, their age, and their gender. |
Variables in Python (continued)
A variable is simply a name that we assign to a specific value, in order to avoid repeating the same value frequently in the code, thus writing a cleaner, less error-prone script/code. As we discussed before, Python has 6 main variable types:
- Number
- String
- List
- Tuple
- Dictionary
- Set and Frozenset
We will get to each of these below. But before that, here are some official and unofficial tips on the variable naming conventions in Python.
Variable naming convention in Python
A Python variable can only begin with letter or underscore _. Numbers are only valid if they appear inside or at the end of the variable name. Other symbols are syntactically invalid anywhere in a variable name.
123new_var = 2.5 # This is an invalid name
File "<ipython-input-10-0e3e63931842>", line 1
123new_var = 2.5 # This is an invalid name
^
SyntaxError: invalid syntax
new_var$ = 2.5 # symbols are not valid in Python variable names
File "<ipython-input-12-71f3fbc68938>", line 1
new_var$ = 2.5 # symbols are not valid in Python variable names
^
SyntaxError: invalid syntax
amir = "teacher"
print('Amir is a', amir)
Amir is a teacher
123amir = "teacher" # Wrong name for variable
File "<ipython-input-38-85ed673cd303>", line 1
123amir = "teacher"
^
SyntaxError: invalid syntax
life_expectancy = 120; print( "The life expectancy for the millennials is projected to be %d years! (But don't believe it...)" % (life_expectancy) );
The life expectancy for the millennials is projected to be 120 years! (But don't believe it...)
Python reserved names (keywords)
There are some limitation as what names you can choose for your variables, even if they completely obey the Python syntax standard. Variable names in Python cannot be the same as Python keywords, which are simply names that reserved for a specific purpose in Python programming. A keyword as variable name, function name or any other identifier. They are used to define the syntax and structure of the Python language. Note that Python keywords are case-sensitive. There are already more than 30 keywords in Python 3. In order to see a complete list of all keywords use the following python codes,
In [38]: import keyword
In [39]: print(keyword.
keyword.iskeyword keyword.kwlist keyword.main
In [39]: print(keyword.kwlist)
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
In [40]: keyword.kwlist # same thing as above, but each keyword printed on a new line.
Out[40]:
['False',
'None',
'True',
'and',
'as',
'assert',
'break',
'class',
'continue',
'def',
'del',
'elif',
'else',
'except',
'finally',
'for',
'from',
'global',
'if',
'import',
'in',
'is',
'lambda',
'nonlocal',
'not',
'or',
'pass',
'raise',
'return',
'try',
'while',
'with',
'yield']
Note that all keywords except True
, False
and None
are in lowercase and they must be written as lowercase. To understand the meaning and function of each of these keywords, see this page.
Meaning of underscore _ in Python
Frequently, as you learn more about Python, you will notice the presence of underscores in Python variables, function and method names. Depending on where and how underscore appears in a Python name, it can have a different meaning.
1. Underscore as word separator in variable/function naming
The convention in Python programming is to separate multiple words in Python variable names by underscore. For example,
an_example_long_variable_name = 123
Of course, this is totally a convension. But I highly recommend you to follow the conventions that everyone else follows, so that you can understand other people’s codes and others can understand your code easily.
2. Underscore meaning in Python interpreter
A variable named solely by underscore _ in Python interpreter points to the result of the last executed statement in the interactive interpreter session. This convention was first implemented by the standard CPython interpreter, but now other implementations are also following the convention.
In [1]: _
Out[1]: ''
In [2]: a = 120
In [3]: _
Out[3]: ''
In [4]: a + a
Out[4]: 240
In [5]: _
Out[5]: 240
3. _ as a dummy name in Python scripts
The underscore _ can be used as a dummy name in Python scripts, a name for an entity that does play an important role in the code, for example, the index of a loop. This allows the next person who reads the code to know which entites (variables, …) are dummy and not intended to be used.
a = 1
b = 2
print("a =",a,"b =",b)
a = 1 b = 2
_ = a
a = b
b = _
print("a =",a,"b =",b) # the values are swapped. _ is just a dummy indtermediate variable.
a = 2 b = 1
4. Underscore as an indicator of the local-scope of a variable/function
A single underscore that appears at the beginning of a name in Python code indicates that the name has to be treated as private by the programmer. In other words, a name starting with _ is for internal use. In Python documentation the following note exist about such names:
A name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.
For Python module functions, if you use from module_name import __all__
instead of from module_name import *
, then all internal names in the module (that begin with _) will be imported to your environment as well.
5. Double Underscore Before and After a Name (e.g., __init__
)
Such names are special method names used by Python. This is just a convention, that is, a way for the Python system to use names that won’t conflict with user-defined names. These names can be typically overridden to define the desired behaviour for when Python calls them. For example, the __init__
method is often overridden when writing a Python class. We will get to these topics later on in this course.
A good review of underscore in Python can be found here.
Number variables
We have already extensively discussed number values in the previous lecture. Basically, everything that we have said about number values, holds also for variables of type number. But here is a very cool fear of number values and variables, that we skipped over in our previous lecture. When you define a Python number variable (or value), then python interpreter automatically allows you to perform some pre-defined operations on the variable/value by default. To access these operations, the dot .
syntax has to be used. Type the variable name, followed by .
, and then press tab
in your IPython/Jupyter editor. Depending on the type of number (integer/float/complex) you will get a different set of operations that are allowed on the variable. The following shows some examples in IPython environment.
In [18]: a = 120 # This is an integer variable
In [19]: a.
a.bit_length a.conjugate a.denominator a.from_bytes a.imag a.numerator a.real a.to_bytes
In [19]: a.conjugate
Out[19]: <function int.conjugate>
In [20]: a.conjugate()
Out[20]: 120
In [21]: a.imag
Out[21]: 0
In [22]: a.real
Out[22]: 120
In [23]: a = 120.5 # Now 'a' is a float variable
In [24]: a.
a.as_integer_ratio a.conjugate a.fromhex a.hex a.imag a.is_integer a.real
In [25]: a.as_integer_ratio() # Gives out the two numbers whose division is the value of the variable 'a'.
Out[25]: (241, 2)
In [28]: a.is_integer() # 120.5 is not a whole number! (it would be True if a = 120.0)
Out[28]: False
You can repeat the above for a complex number and see what you get.
In [33]: a = 1+1j
In [34]: a.
a.conjugate a.imag a.real
In [34]: a.conjugate()
Out[34]: (1-1j)
String variables
Just as with numbers, string is another variable/value type in Python with many handy features that come withit. For example, if you create a string variable or value, fllowed by .
and then press tab
you will see a long list of methods that can be applied on the string,
In [8]: my_string = 'this is a String'
In [9]: my_string.
my_string.capitalize my_string.find my_string.isdigit my_string.isupper my_string.replace my_string.split my_string.upper
my_string.casefold my_string.format my_string.isidentifier my_string.join my_string.rfind my_string.splitlines my_string.zfill
my_string.center my_string.format_map my_string.islower my_string.ljust my_string.rindex my_string.startswith
my_string.count my_string.index my_string.isnumeric my_string.lower my_string.rjust my_string.strip
my_string.encode my_string.isalnum my_string.isprintable my_string.lstrip my_string.rpartition my_string.swapcase
my_string.endswith my_string.isalpha my_string.isspace my_string.maketrans my_string.rsplit my_string.title
my_string.expandtabs my_string.isdecimal my_string.istitle my_string.partition my_string.rstrip my_string.translate
In [9]: my_string.upper()
Out[9]: 'THIS IS A STRING'
In [10]: my_string.swapcase()
Out[10]: 'THIS IS A sTRING'
Strings are immutable
Although strings (both values and variables) can be indexed letter by letter, keep in mind that they cannot be changed (mutated) to something new. In other words, string are immutable.
In [11]: my_string = 'Amir Shahmoradi'
In [13]: my_string[0] = 'a'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-27fc86283e06> in <module>()
----> 1 my_string[0] = 'a'
TypeError: 'str' object does not support item assignment
The correct way of doing this would be through the indirect use of string methods or string slicing.
In [18]: my_string = my_string[:4] + ' ' + my_string[4:] # mutating my_string: add a space between first and last names.
In [19]: my_string
Out[19]: 'Amir Shahmoradi'
It is often very useful to know the length of a string. This can be done using len()
function.
In [32]: len(my_string)
Out[32]: 16
In [33]: len(my_string[0:5])
Out[33]: 5
Testing if a string is part of another string
We have already discussed some boolean string operations in Lecture 4. There are howver two more boolean operations that deserve to be mentioned here.
In [48]: text = "Engineering Computation program at UT Austin, is the first of its kind in the nation"
In [49]: "comp" in text # test if "comp" is part of the "text" string variable.
Out[49]: False
In [50]: "Comp" in text
Out[50]: True
In [51]: "comp" not in text # test if "comp" is NOT part of the "text" string variable.
Out[51]: True
To know more about string values and variables in general, visit this page.
List variables
List is another standard variable in type in Python and is composed of an ordered set of values (elements), each of which is identified by an index. Lists are defined by brackets []
.
In [47]: emptyList = [] # initiate an empty list
In [48]: emptyList
Out[48]: []
In [40]: myList = [ 0,1,2,'Amir',complex(1,2j) ]
In [41]: myList
Out[41]: [0, 1, 2, 'Amir', (-1+0j)]
In [42]: myList[0] # note that list index always begins with 0
Out[42]: 0
List slices
In [43]: myList[:-1] # all list elements from beginning to end, similar to myList, or myList[:]
Out[43]: [0, 1, 2, 'Amir']
In [44]: myList[:]
Out[44]: [0, 1, 2, 'Amir', (-1+0j)]
In [45]: myList[-1:] # select only the last element in list
Out[45]: [(-1+0j)]
In [46]: myList[::-1] # Creat list in reverse order.
Out[46]: [(-1+0j), 'Amir', 2, 1, 0]
Lists vs. Strings
You may have already noticed that lists behave very similar to strings in Python. In fact, both List and String are examples of ordered sets in Python known as sequence. The only difference between list and python is that the elements of strings have to be all of type character, whereas lists do not have such restriction, as seen in the example above.
Nested lists
Lists can also contain other lists as elements. This way you can create matrices of numbers as well.
In [53]: smallList = [1,2,3]
In [54]: list_of_lists = [ 10 , 100.0 , ['amir','shahmoradi'] , smallList ]
In [55]: list_of_lists
Out[55]: [10, 100.0, ['amir', 'shahmoradi'], [1, 2, 3]]
In [56]: my_matrix = [ [1,2,3] , [4,5,6] , [7,8,9] ]
In [57]: my_matrix[0][2] # the first index points to the 0th element in the list of lists, and the second index calls the list that is the first element of the big list.
Out[57]: 3
In [68]: my_matrix[5-5][(2+2)//2] # note that list indices can be the result of arithmetic operations too.
Out[68]: 3
In [61]: len(my_matrix) # This function gives the length of the list of lists.
Out[61]: 3
In [62]: list_of_lists
Out[62]: [10, 100.0, ['amir', 'shahmoradi'], [1, 2, 3]]
In [63]: len(list_of_lists[0]) # The first element, being an integer, does not have a length
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-63-11f2bd3dda3d> in <module>()
----> 1 len(list_of_lists[0])
TypeError: object of type 'int' has no len()
In [64]: len(list_of_lists[2]) # but the third element in the list, is itself a list, so it does have a length
Out[64]: 2
Operations on lists
Two mathematics operations +
and *
are also meaningful for lists, just as it is for string sequences.
In [8]: list1 = [1,2,3]
In [9]: list2 = [4,5,6]
In [10]: list1 + list2
Out[10]: [1, 2, 3, 4, 5, 6]
In [11]: list1 * 3
Out[11]: [1, 2, 3, 1, 2, 3, 1, 2, 3]
In [12]: (list1 + list2) * 3
Out[12]: [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
In addition, once a list is created, by default, a list of pre-defined operations (methods) are available to act on the list content. To access these methods, again use .
notation, just as you did for strings before.
In [13]: list1.
list1.append list1.clear list1.copy list1.count list1.extend list1.index list1.insert list1.pop list1.remove list1.reverse list1.sort
In [13]: list1
Out[13]: [1, 2, 3]
In [14]: list1.append(4) # append number 4 to the end of list1
In [15]: list1
Out[15]: [1, 2, 3, 4]
In [16]: list1.append([1,1,1]) # append the given list to the end of list1
In [17]: list1
Out[17]: [1, 2, 3, 4, [1, 1, 1]]
In [18]: list1.count(1) # count the number of times 1 appears as element of list1
Out[18]: 1
In [19]: list1[-1].count(1) # count the number of times 1 appears as element in the list appearing as the element in list1.
Out[19]: 3
In [20]: list1[-2].count(4) # Note that count is a method only for lists, and therefore cannot be applied to numbers.
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-21-2add981bfc56> in <module>()
----> 1 list1[-2].count(4)
AttributeError: 'int' object has no attribute 'count'
In [23]: list1.extend([1,1,1]) # extend list1 by 3 more members
In [24]: list1
Out[24]: [1, 2, 3, 4, [1, 1, 1], 1, 1, 1]
In [25]: list1.count(1) # This time counting 1, gives 4, since the list was extended by 3 more '1'.
Out[25]: 4
Here is a useful reference for available list methods in Python.
Lists are mutable (unlike Strings)
Another major difference between list sequences and string sequences in Python is that the elements of lists can be changed (mutated) to something new.
In [26]: people = [ 'Amir' , 'Jake' , 'Travis' ]
In [27]: people
Out[27]: ['Amir', 'Jake', 'Travis']
In [28]: people[0] = 'Brandon'
In [29]: people
Out[29]: ['Brandon', 'Jake', 'Travis']
In [30]: people.remove('Brandon')
In [31]: people
Out[31]: ['Jake', 'Travis']
Deleting list elements
Deleting list elements can be done by either value of the element, or using its index, like the following,
In [138]: a = [1,2,3,1,2,3]
In [139]: a.remove(1) # remove the first element correponding to value of 1.
In [140]: a
Out[140]: [2, 3, 1, 2, 3]
In [141]: a.remove(1) # remove the first element correponding to value of 1.
In [142]: a
Out[142]: [2, 3, 2, 3]
In [143]: del a[0:3:2] # delete element indices 0, 2
In [144]: a
Out[144]: [3, 3]
Concatenating a list of strings
If a list is all string values, you can use the following string method .join()
to concatenate the content og the list.
In [155]: mylist = ['The' , 'weather' , 'is' , 'rainy' , 'today' , 'and' , 'cold' , 'only' , '22' , 'F.']
In [156]: " ".join(mylist)
Out[156]: 'The weather is rainy today and cold only 22 F.'
Tuple variables
Tuples are a type of Python variables very similar to list sequences, except that they are immutable, meaning that, once generated, they cannot be changed. Another difference is that, tuples use parentheses for definition, whereas lists use square brackets.
In [33]: emptyTuple = ()
In [34]: single_element_tuple = (1,) # ATTN: note the comma after the element
In [35]: tuple1 = (1, 2, 3, 'amir', 'Jake')
In [36]: single_element_tuple
Out[36]: (1,)
In [37]: type(single_element_tuple)
Out[37]: tuple
In [38]: single_element_tuple = (1)
In [39]: single_element_tuple
Out[39]: 1
In [40]: type(single_element_tuple)
Out[40]: int
Creating a tuple is as simple as putting different comma-separated values. Optionally you can put these comma-separated values between parentheses also.
In [46]: tuple2 = 1,2,3,4 # another way of creating a tuple
In [47]: type(tuple2)
Out[47]: tuple
Modifying the content of Tuples
Tuples are an example of data structure in Python, used for organizing and grouping data. Once a tuple is created, its content cannot be changed or manipulated anymore. However, its elements can be called just like lists.
In [48]: tuple2[0]
Out[48]: 1
In [49]: tuple2[1:3]
Out[49]: (2, 3)
In [50]: tuple2. # press tab key to get the list methods
tuple2.count tuple2.index
In [51]: tuple2.count(2) # count the number of members that are 2
Out[51]: 1
In [52]: tuple2.count(5) # count the number of members that are 5
Out[52]: 0
In [53]: tuple2.index(2) # get the index of the first member in tuple that is 2
Out[53]: 1
In [54]: tuple2.index(5) # get the index of the first member in tuple that is 5. (error! 5 is not a member)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-54-f0077f9af98b> in <module>()
----> 1 tuple2.index(5)
ValueError: tuple.index(x): x not in tuple
Moreover, although the content of tuple cannot be changed, there is nothing to prevent the programmer from redefining the tuple with new content,
In [106]: tuple1 = (1, 2, 3, 'amir', 'Jake')
In [107]: tuple1
Out[107]: (1, 2, 3, 'amir', 'Jake')
In [108]: tuple1 = ('Travis','Caleb','Lucero') + tuple1[-1:] # redefining tuple1
In [109]: tuple1
Out[109]: ('Travis', 'Caleb', 'Lucero', 'Jake')
But pay attention that the above, all the terms in the assigment must be a tuple, otherwise you will get an error like the following (e.g., a single member of a tuple, is not a tuple by itself),
In [110]: tuple1 = (1, 2, 3, 'amir', 'Jake')
In [111]: tuple1 = ('Travis','Caleb','Lucero') + tuple1[-1] # Note that tuple1[-1] is a string, and not a tuple!
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-111-4c6018fb7529> in <module>()
----> 1 tuple1 = ('Travis','Caleb','Lucero') + tuple1[-1]
TypeError: can only concatenate tuple (not "str") to tuple
In [112]: type(tuple1[-1])
Out[112]: str
In [113]: type(tuple1[-1:])
Out[113]: tuple
Note also the difference between +
operations in the above tuple redefinition, and ,
operations below,
In [126]: tuple1 = (1, 2, 3, 'amir', 'Jake')
In [127]: tuple1 = ('Travis','Caleb','Lucero') + tuple1[-1:]
In [128]: tuple1
Out[128]: ('Travis', 'Caleb', 'Lucero', 'Jake')
In [129]: tuple1 = (1, 2, 3, 'amir', 'Jake')
In [130]: tuple1 = ('Travis','Caleb','Lucero') , tuple1[-1:]
In [131]: tuple1
Out[131]: (('Travis', 'Caleb', 'Lucero'), ('Jake',))
Tuples can be heterogeneous, as in the above example, meaning that each member of tuple can be a tuple itself, a list, or any other variable type.
Dictionary variables
The past three data types discussed in the previous secitons — strings, lists, and tuples — are of type sequence. For sequences, we have seen above that we use integers as indices to access the values these variables contain. Dictionaries are yet another built-in variable type in Python. A dictionary variable is a sequence of pairs of {key: value}. Instead of using numbers to index elements (as in list, string, tuple), dictionaries use keys in order to retrieve the key’s value. The keys can be any immutable type (string, number and tuple). Values can be any type (heterogeneous, mutable), just like the elements of a list or tuple. Dictionaries are also called associative arrays since they associate a key with a value. One way to create a dictionary is to start with the empty dictionary and add key:value
pairs.
In [161]: age = {} # empty dictionary
In [162]: age
Out[162]: {}
In [163]: type(age)
Out[163]: dict
In [164]: age = { 'amir':120 , 'jake':22 , 'Lucero':19 , 'Travis':20 }
In [165]: age
Out[165]: {'Lucero': 19, 'Travis': 20, 'amir': 120, 'jake': 22}
In [166]: age['Lucero']
Out[166]: 19
Some important features of dictionaries are the following:
- A dictionary is a collection of key-value pairs.
- A dictionary is a set of key:value pairs.
- All keys in a dictionary must be unique.
- In a dictionary, a key and its value are separated by a colon (:).
- Each key-value pair is separated by a comma from another pair in dictionary.
- All the key-value pairs together are listed between curly brackets
{ }
. - Query the dictionary using square brackets
[ ]
, inside of which you type the key, and the output will be the value correponding to the key.
Three ways of constructing distionaries
The are three basic ways for creating dictionaries in Python.
1. Create empty dictionary and then add key-value pairs to it.
In [1]: dic = {}
In [2]: dic['amir'] = 'teacher'
In [3]: dic
Out[3]: {'amir': 'teacher'}
In [4]: dic['Jake'] = 'student'
In [5]: dic['Travis'] = 'student'
In [6]: dic
Out[6]: {'Jake': 'student', 'Travis': 'student', 'amir': 'teacher'}
2. Create a dictionary from a list if tuples, using Python’s built-in function dict()
. The input argument of dict()
is a list of tuples,
In [7]: month = dict( [ ( 1 , 'Jan') \
...: , ( 2 , 'Feb') \
...: , ( 3 , 'Mar') \
...: , ( 4 , 'Apr') \
...: , ( 5 , 'May') \
...: , ( 6 , 'Jun') \
...: , ( 7 , 'Jul') \
...: , ( 8 , 'Aug') \
...: , ( 9 , 'Sep') \
...: , (10 , 'Oct') \
...: , (11 , 'Nov') \
...: , (12 , 'Dec') ] )
In [8]: month
Out[8]:
{1: 'Jan',
2: 'Feb',
3: 'Mar',
4: 'Apr',
5: 'May',
6: 'Jun',
7: 'Jul',
8: 'Aug',
9: 'Sep',
10: 'Oct',
11: 'Nov',
12: 'Dec'}
In [9]: month[5]
Out[9]: 'May'
But, be careful to not override the Python’s function dict()
by your user-defined variable or function of the same name, otherwise you will get an error like the following,
In [10]: dict = 5
In [11]: new_dic = dict([('amir','teacher')]) # This will give error because dict is not pointing to the built-in function dict() anymore! It was overridden by the above assignment.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-10-271a21fe772b> in <module>()
----> 1 new_dic = dict([('amir','teacher')])
TypeError: 'int' object is not callable
3. Create a dictionary from two lists in parallel. Let’s say the keys and values of our desired dictionary, each are in the form of a list. The question is now, if there is an easy Pythonic way to combine these two lists of keys and values to get a dictionary? The answer is yes, and it is achieved by a Python function named zip()
.
In [1]: person = ['amir','jake','travis']
In [2]: role = ['teacher','student','student']
In [3]: person_role_dict = dict( zip( person , role ) )
In [4]: type(person_role_dict)
Out[4]: dict
In [5]: person_role_dict
Out[5]: {'amir': 'teacher', 'jake': 'student', 'travis': 'student'}
Manipulating dictionary variables
1. Removing a dictionary key-value pair
This can be done using Python’s del
command,
In [10]: person_role_dict
Out[10]: {'amir': 'teacher', 'jake': 'student', 'travis': 'student'}
In [11]: del person_role_dict['amir']
In [12]: person_role_dict
Out[12]: {'jake': 'student', 'travis': 'student'}
2. Adding a dictionary key
In [14]: person_role_dict
Out[14]: {'jake': 'student', 'travis': 'student'}
In [15]: person_role_dict['amir'] = 'teacher' # adding a new key-value pair ('amir' : 'teacher')
In [16]: person_role_dict
Out[16]: {'amir': 'teacher', 'jake': 'student', 'travis': 'student'}
2. Changing the value of a key
In [17]: person_role_dict['amir'] = 'instructor' # changing the value of the key 'amir'
In [18]: person_role_dict
Out[18]: {'amir': 'instructor', 'jake': 'student', 'travis': 'student'}
3. Getting the length of dictionary (number of key-value pairs)
In [19]: len(person_role_dict)
Out[19]: 3
4. Using dictionary methods
Just as with other Python variable types, typing the name of a dictionary that is already defined, followed by .
followed by pressing the tab
key (in a good Python editor) will show you the list of methods that can act on the dictionary.
In [20]: person_role_dict.
person_role_dict.clear person_role_dict.get person_role_dict.pop person_role_dict.update
person_role_dict.copy person_role_dict.items person_role_dict.popitem person_role_dict.values
person_role_dict.fromkeys person_role_dict.keys person_role_dict.setdefault
In [20]: person_role_dict.keys()
Out[20]: dict_keys(['amir', 'jake', 'travis'])
In [21]: list ( person_role_dict.keys() )
Out[21]: ['amir', 'jake', 'travis']
In [22]: type ( person_role_dict.keys() )
Out[22]: dict_keys
In [23]: type ( list ( person_role_dict.keys() ) )
Out[23]: list
In [24]: person_role_dict.values()
Out[24]: dict_values(['instructor', 'student', 'student'])
In [10]: person_role_dict
Out[10]: {'amir': 'teacher', 'jake': 'student', 'travis': 'student'}
In [27]: person_role_dict.pop('amir') # remove the key-value pair ('amir':'teacher') and return the corresponding value of the key as output.
Out[27]: 'instructor'
In [28]: person_role_dict
Out[28]: {'jake': 'student', 'travis': 'student'}
Dictionary representation of sparse matrices
We already discussed in the above, the usefulness of nested lists in creating matrices. Now suppose we have a sparse matrix, whose most elements are zero, except a few non-zero elements. An alternative to using nested lists, which can also take less memory of the device, is to use a dictionary representation of the sparse matrix.
In [16]: sparseMatrixList = [ [ 0 , 0 , 0 , 1 ]
....: , [ 2 , 0 , 0 , 0 ]
....: , [ 0 , 5 , 0 , 0 ]
....: , [ 0 , 0 , 0 , 3 ]
....: , [ 0 , 0 , 8 , 0 ]
....: ]
In [17]: sparseMatrixList
Out[17]: [[0, 0, 0, 1], [2, 0, 0, 0], [0, 5, 0, 0], [0, 0, 0, 3], [0, 0, 8, 0]]
In [18]: sparseMatrixDict = { (0,3): 1 , (1,0): 2 , (2,1): 5 , (3,3): 3 , (4,2): 8 }
In [19]: sparseMatrixDict
Out[19]: {(0, 3): 1, (1, 0): 2, (2, 1): 5, (3, 3): 3, (4, 2): 8}
Set variables
Besides all the aforementioned variable types in Python, there is another Python variable type that is useful for constructing and manipulating unordered collection of unique elements. Common uses of sets include membership testing, removing duplicates from a sequence, and computing standard math operations on sets such as intersection, union, difference, and symmetric difference.
Like other collections, sets support x in set
and len(set)
operations. Being an unordered collection, sets do not record element position or order of insertion. Accordingly, sets do not support indexing, slicing, or other sequence-like behavior.
There are currently two built-in set types, set and frozenset. The set type is mutable — the contents can be changed using methods like add() and remove().
In [61]: a = set( [ 1,2,3,(1,2),'amir' ] )
In [62]: a.
a.add a.difference a.intersection a.issubset a.remove a.union
a.clear a.difference_update a.intersection_update a.issuperset a.symmetric_difference a.update
a.copy a.discard a.isdisjoint a.pop a.symmetric_difference_update
In [62]: a.add('jake')
In [63]: a
Out[63]: {(1, 2), 1, 2, 3, 'jake', 'amir'}
In [64]: a.add([1,3]) # Note that mutable types cannot appear in a set!
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-64-2a5b54498213> in <module>()
----> 1 a.add([1,3])
TypeError: unhashable type: 'list'
Sets can be also simply created by {}
.
In [71]: a = {1,2,3}
In [72]: type(a)
Out[72]: set
The frozenset type is immutable and hashable (i.e., its contents cannot be altered after it is created). It can therefore be used as a dictionary key or as an element of another set.
In [69]: a = frozenset( [ 1,2,3,(1,2),'amir' ] )
In [70]: a.
a.copy a.intersection a.issubset a.symmetric_difference
a.difference a.isdisjoint a.issuperset a.union
In [70]: type(a)
Out[70]: frozenset
Note that mutable types can neither appear in a set nor a frozenset. You can obtain more information about sets and frozensets and the methods that can act on them in the Python library reference.
Assignment statements in Python
In Python, an assignment statement is one line of Python code that contains at least one equal sign =
and the purpose of it is to associate name(s) with a certain value in the program. Assignment statements are the only Python statements that do not start with a keyword. In most cases, the assignment statement will only contain one target name, one equal sign, and one expression (reduced to one single value that is assigned to the name).
A binding is an association between a name and a value. Note that in Python, unlike many other languages, names themselves are not associated with a specific variable types. A name is just a label, and therefore it can be bound to any value of any type at any time. For example,
In [50]: a = 'some text'
In [51]: a
Out[51]: 'some text'
In [52]: a = 2
In [53]: a
Out[53]: 2
Aliasing vs. copying
It is very important to understand the difference between alias assignment statements and copy assignment statements. As far as assignments are concerned, all data types in Python can be divided into two categories:
- simple data types (e.g., int, float, string, tuple)
- container data types (e.g., list, dict, set, …)
For simple data types, an assignment means that their value is copied to the assigned variable.
In [80]: x = 1
In [81]: y = x # An assignment statement that copies the value of x into y.
In [82]: x = 2 # Now changing the value of x, won't change the value of y.
In [83]: x
Out[83]: 2
In [84]: y
Out[84]: 1
For container data types, an assignment in the form of copy can be computationally and memory-wise very expensive, and so it makes sense, when an assignment involves container types as values, then the new name would only point to the original container. In other words, the new assignment provides an alias for the container value.
In [85]: a = [1,2,3]
In [86]: b = a # In this assignment, b is simply an alias for a. The value of a is NOT copied into b
In [87]: a
Out[87]: [1, 2, 3]
In [88]: b
Out[88]: [1, 2, 3]
In [89]: a is b # a and b have the same identity
Out[89]: True
In [90]: a == b # a and b have the same value
Out[90]: True
In [91]: a = [1,2,3]
In [92]: b = [1,2,3]
In [93]: a is b # a and b don't have the same identity anymore, since they are not pointing to the same value anymore.
Out[93]: False
In [94]: a == b # Despite not being identical, a and b still have the same value.
Out[94]: True
If you want to get a copy of a container object, instead of an alias for it, you should use the copy
method of the container object.
In [97]: a = [1,2,3]
In [98]: b = a.copy() # Copy the content of a into b
In [99]: a is b
Out[99]: False
In [100]: a == b
Out[100]: True
Conclusion:
So, keep in mind that, assignments in which the value to be assigned is a container type (e.g., list, dict, set) will result in an alias, and not a fresh copy of the original value.
Multiple simultaneous assignments in one line
A shortcut way of aliasing multiple variables with one single value is the following,
In [101]: a = b = c = 3
In [102]: a is b
Out[102]: True
In [103]: a is b is c
Out[103]: True
In [104]: a == b == c
Out[104]: True
Here, an integer object is created with the value 1, and all three variables are assigned to the same memory location. This is also true for container variable types.
In [105]: a = b = c = [1,2,3]
In [106]: a is b is c
Out[106]: True
You can also assign multiple objects to multiple variables all in the same asignment statement. But keep in mind that the number of assignments on both sides of equal sign must be equal.
In [1]: a, b, c = 1, 2, "amir"
In [2]: a
Out[2]: 1
In [3]: b
Out[3]: 2
In [4]: c
Out[4]: 'amir'
<br>
Here, two integer objects with values 1 and 2 are assigned to variables a and b respectively, and one string object with the value “amir” is assigned to the variable c. This form of assignment in the above is basically like setting the tuple (a,b,c) = (1,2,"amir")
. This is why it is important that both sides of the equal sign have the same number of elements. Here are some other examples:
In [5]: a, b, c = 3, 3, 3
In [6]: a is b
Out[6]: True
In [7]: a == b
Out[7]: True
In [57]: [ a , b ] = [ 5 , 4 ]
In [58]: a
Out[58]: 5
In [59]: [ a , b ] = ( 5 , 4 )
In [60]: a
Out[60]: 5
In [61]: [a,b] = [c,d] = [4,5]
In [62]: a is b
Out[62]: False
In [63]: a is c
Out[63]: True
In [64]: [a,b] is [c,d]
Out[64]: False
In [65]: [a,b] is [4,5]
Out[65]: False
In [66]: [a,b] == [c,d]
Out[66]: True
In [67]: [a,b] == [4,5]
Out[67]: True
Value swapping
The traditional way of swapping values of two variables in mostprogramming languages is like the following,
In [68]: a = 5
In [69]: b = 7
In [70]: _ = a
In [71]: a = b
In [72]: b = _
In [73]: a
Out[73]: 7
In [74]: b
Out[74]: 5
With either Python lists or tuples, this swapping can be achived neatly in just one line of code,
In [75]: (a,b) = (b,a)
In [76]: a
Out[76]: 5
In [77]: b
Out[77]: 7
In [78]: [a,b] = [b,a]
In [79]: a
Out[79]: 7
In [80]: b
Out[80]: 5