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.

Table 1. Some programming phrases that are discussed in this lecture.
Expression Description
dictionaryA collection of `key:value` mapping pairs, in which the values can be obtained by calling the value's key.
hashableA Python object (e.g., variable) that has a hash value which never changes during its lifetime.
immutableA 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.
invocationThe process of calling an object's method, usually done through <object name>.<method name> notation.
listA sequence of comma-separated heterogenous values next to each other.
methodSimilar 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.
mutableA variable or value that can be modified. Examples of mutables in Python are lists, and dictionaries.
setAn unordered collection of unique elements, just like the mathemtical sets.
stringA sequence of characters next to each other.
tupleAn 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:

  1. simple data types (e.g., int, float, string, tuple)
  2. 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




Comments