Playing With Python #2: More of the Basics
This is the second article on learning how to program with Python, which will go into more language features, tools, and tips to help get you going with becoming a Python programmer.
If you haven’t read the first article of this series, feel free to check out Playing With Python #1: Learning the Basics.
Getting Help
Along with the documentation available online, Python includes a built-in help function that can be used to get more information about topics and objects. In the example below, a string argument is being used to get information about “keywords” and “topics” – more information can be retrieved by passing in a string of one of the topics. I also show getting help documentation about the print command and also show using the interactive help by calling help() with no arguments.
>>> help("keywords")
###
### Here is a list of the Python keywords. Enter any keyword to get more help.
###
### False class from or
### None continue global pass
### True def if raise
### and del import return
### as elif in try
### assert else is while
### async except lambda with
### await finally nonlocal yield
### break for not
>>> help("topics")
###
### Here is a list of available topics. Enter any topic name to get more help.
###
### ASSERTION EXCEPTIONS PACKAGES
### ASSIGNMENT EXECUTION POWER
### ASSIGNMENTEXPRESSIONS EXPRESSIONS PRECEDENCE
### ATTRIBUTEMETHODS FLOAT PRIVATENAMES
### ATTRIBUTES FORMATTING RETURNING
### AUGMENTEDASSIGNMENT FRAMEOBJECTS SCOPING
### BASICMETHODS FRAMES SEQUENCEMETHODS
### BINARY FUNCTIONS SEQUENCES
### BITWISE IDENTIFIERS SHIFTING
### BOOLEAN IMPORTING SLICINGS
### CALLABLEMETHODS INTEGER SPECIALATTRIBUTES
### CALLS LISTLITERALS SPECIALIDENTIFIERS
### CLASSES LISTS SPECIALMETHODS
### CODEOBJECTS LITERALS STRINGMETHODS
### COMPARISON LOOPING STRINGS
### COMPLEX MAPPINGMETHODS SUBSCRIPTS
### CONDITIONAL MAPPINGS TRACEBACKS
### CONTEXTMANAGERS METHODS TRUTHVALUE
### CONVERSIONS MODULES TUPLELITERALS
### DEBUGGING NAMESPACES TUPLES
### DELETION NONE TYPEOBJECTS
### DICTIONARIES NUMBERMETHODS TYPES
### DICTIONARYLITERALS NUMBERS UNARY
### DYNAMICFEATURES OBJECTS UNICODE
### ELLIPSIS OPERATORS
>>> help(print)
### Help on built-in function print in module builtins:
###
### print(*args, sep=' ', end='\n', file=None, flush=False)
### Prints the values to a stream, or to sys.stdout by default.
###
### sep
### string inserted between values, default a space.
### end
### string appended after the last value, default a newline.
### file
### a file-like object (stream); defaults to the current sys.stdout.
### flush
### whether to forcibly flush the stream.
>>> help()
### Welcome to Python 3.14's help utility! If this is your first time using
### Python, you should definitely check out the tutorial at
### https://docs.python.org/3.14/tutorial/.
###
### Enter the name of any module, keyword, or topic to get help on writing
### Python programs and using Python modules. To get a list of available
### modules, keywords, symbols, or topics, enter "modules", "keywords",
### "symbols", or "topics".
###
### You can use the following keyboard shortcuts at the main interpreter prompt.
### F1: enter interactive help, F2: enter history browsing mode, F3: enter paste
### mode (press again to exit).
###
### Each module also comes with a one-line summary of what it does; to list
### the modules whose name or summary contain a given string such as "spam",
### enter "modules spam".
###
### To quit this help utility and return to the interpreter,
### enter "q", "quit" or "exit".
###
### help>
Use this to explore what Python has to offer.
Introduction to Objects
It would be good to address the concept of an object sooner rather than later because in Python, almost everything is an object. An object can have data (attributes) and functions (methods) bundled together to make it easy to work with.
We live in a world full of real objects, so this might be understandable – a clock can have the value of the current time, and it can have controls for setting an alarm. Objects in a computer can be conceptually thought of the same way, though they can sometimes be more abstract things than just physical real-world objects.
You can access an object’s attributes and methods through the dot . operator. For example, let’s say that you made a program with a date object called d. You could access the year attribute by using d.year. You could also call a function on the date, like getting an ISO-formatted string of it by using d.isoformat().
>>> import datetime
>>> d = datetime.date(2026, 7, 12)
>>> d
### datetime.date(2026, 7, 12)
>>> d.year
### 2026
>>> d.isoformat()
### '2026-07-12'
You can see what type an object is by using the type function.
>>> type(12)
### <class 'int'>
>>> type(3.14)
### <class 'float'>
>>> type("Hello")
### <class 'str'>
>>> type([1, 2, 3])
### <class 'list'>
>>> type(d)
### <class 'datetime.date'>
Dir Listing
There is a built-in function in Python that helps you more easily see what attributes and functions an object has – it’s the dir function.
It can be called without any arguments, like dir(), to see what exists in the current scope (this may differ for you, depending on what you might have created or imported, but you can see the datetime we imported and the d date created above). If an object or a module is passed to it, though, it will show what attributes it has.
>>> dir()
### ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'd', 'datetime']
>>> dir("some string")
### ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__',
### '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__',
### '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__',
### '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__',
### '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
### '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__',
### '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode',
### 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum',
### 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower',
### 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust',
### 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix',
### 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip',
### 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title',
### 'translate', 'upper', 'zfill']
>>> import math
>>> dir(math)
### ['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__',
### 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'cbrt', 'ceil',
### 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc',
### 'exp', 'exp2', 'expm1', 'fabs', 'factorial', 'floor', 'fma', 'fmod', 'frexp',
### 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf',
### 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2',
### 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians',
### 'remainder', 'sin', 'sinh', 'sqrt', 'sumprod', 'tan', 'tanh', 'tau', 'trunc',
### 'ulp']
Combined with what had been learned earlier about the help command, you can see how you can explore and find more information about things in Python. For example, in dir(math) above, you can see that it has a sqrt function. You can use the help on that function to get information about how to get the square root of a number.
>>> help(math.sqrt)
### Help on built-in function sqrt in module math:
###
### sqrt(x, /)
### Return the square root of x.
>>> math.sqrt(100)
### 10.0
You might have noticed that some of the attributes in these objects have one or more underscores at the beginning or end. At this point in time, mostly focus on the ones that do not start with underscores. The ones that have them are either used internally by the object and not intended to generally be used by a programmer, or they are to define advanced functions and properties used by objects.
Built-In Capabilities
Now that you know what dir is, we can explore what built-in functionality is available by default by using dir on __builtins__. You don’t need to fully read through all of this output – it is mostly for general awareness.
>>> dir(__builtins__)
### ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
### 'BaseExceptionGroup', 'BlockingIOError', 'BrokenPipeError', 'BufferError',
### 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
### 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError',
### 'Ellipsis', 'EncodingWarning', 'EnvironmentError', 'Exception', 'ExceptionGroup',
### 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
### 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning',
### 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError',
### 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError',
### 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
### 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning',
### 'PermissionError', 'ProcessLookupError', 'PythonFinalizationError',
### 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError',
### 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError',
### 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True',
### 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
### 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
### 'ValueError', 'Warning', 'ZeroDivisionError', '_', '_IncompleteInputError',
### '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__',
### '__package__', '__spec__', 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin',
### 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod',
### 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod',
### 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset',
### 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int',
### 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map',
### 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print',
### 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr',
### 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type',
### 'vars', 'zip']
You might notice a few things in there that we have already used in this article or the previous one, like False, True, None, print, input, int, range, help, and dir.
Some useful numerical functions that are worth looking into are min, max, round, sum. There are other useful functions which we will be either using later or you can look more into on your own.
Tuples
When reading about Python, you might encounter an unfamiliar sounding word – “tuple”. What is a tuple? It’s actually nothing complicated – it’s just multiple values bundled together. Think of single, double, triple, etc. – a tuple can be defined with any number of values.
A variable can be created as a tuple using parentheses and commas ((, ), and ,), or by using the tuple class.
>>> number_tuple = (1, 2, 3, 4, 5)
>>> number_tuple
### (1, 2, 3, 4, 5)
>>> mixed_tuple = ("one", 2, 3.14, True)
>>> mixed_tuple
### ('one', 2, 3.14, True)
>>> single_tuple = (7,)
>>> single_tuple
### (7,)
>>> not_a_tuple = (3)
>>> not_a_tuple
### 3
>>> empty_tuple = tuple()
>>> empty_tuple
### ()
>>> tuple_from_list = tuple([3, 2, 1])
>>> tuple_from_list
### (3, 2, 1)
Tuples can contain a mixture of different value types.
What might look strange is that a tuple with a single value must be created with a comma and nothing after it. The reason is because parentheses have more than one meaning, so without the comma, Python wouldn’t know if you wanted either a tuple or grouping a mathematical expression.
To access values in a tuple, you can get them by index or you can “unpack” them. An index is a numeric value indicating which item from a collection of items that you want, and the syntax involves using square brackets [ and ].
One thing that often confuses new programmers is that in Python and most other programming languages, indexes start at zero instead of one. If you wanted the “third” letter of the alphabet, you would get the letter at index two, because ‘A’ is at index zero, ‘B’ at index one, and ‘C’ at index two. Although this might seem unintuitive, it often makes the math when dealing with indexes simpler.
You will get an error if you try using an index value outside of the range of indexes for the tuple. One thing that might surprise you is that you can use negative indexes to get values off the end of a collection.
>>> mixed_tuple[0]
### 'one'
>>> mixed_tuple[2]
### 3.14
>>> mixed_tuple[10]
### Traceback (most recent call last):
### File "<pyshell#14>", line 1, in <module>
### mixed_tuple[10]
### IndexError: tuple index out of range
>>> mixed_tuple[-1]
### True
>>> mixed_tuple[-2]
### 3.14
I briefly mentioned the other way of using values from a tuple – “unpacking” them. This moves values into variables to make them more convenient to work with. You have to have the same number of variables as there are values in the tuple.
>>> first_name, last_name = ("Albert", "Einstein")
>>> first_name
### 'Albert'
>>> last_name
### 'Einstein'
It is important to understand that tuples and strings are “immutable” – which means that they cannot be changed. Once a tuple is created, you cannot modify any of the values in it or make it bigger or smaller to have a different number of elements.
>>> mixed_tuple[1] = 777
### Traceback (most recent call last):
### File "<pyshell#25>", line 1, in <module>
### mixed_tuple[1] = 777
### TypeError: 'tuple' object does not support item assignment
>>> name = "Mandelbrot"
>>> name[0]
### 'M'
>>> name[0] = 'X'
### Traceback (most recent call last):
### File "<pyshell#32>", line 1, in <module>
### name[0] = 'X'
### TypeError: 'str' object does not support item assignment
Lists
Unlike tuples, lists are “mutable” – items in them can be changed and values can be added or removed to make the list bigger or smaller. This provides a lot more flexibility than tuples. A list is created using square brackets [ and ] or by using the list class.
>>> empty_list = []
>>> empty_list
### []
>>> number_list = [1, 2, 3, 4, 5]
>>> number_list
### [1, 2, 3, 4, 5]
>>> number_list[2]
### 3
>>> mixed_list = ['one', 2, 3.14, True]
>>> mixed_list
### ['one', 2, 3.14, True]
>>> another_empty_list = list()
>>> another_empty_list
### []
>>> list_from_tuple = list((3, 2, 1))
>>> list_from_tuple
### [3, 2, 1]
Lists are created in much the same way as tuples, but using square brackets instead of parentheses. Values are also retrieved by index from lists in the same way as with tuples. As you can see, though, the list can be changed:
>>> number_list[2] = 9
>>> number_list
### [1, 2, 9, 4, 5]
>>> number_list.append(999)
>>> number_list
### [1, 2, 9, 4, 5, 999]
>>> number_list.remove(9)
>>> number_list
### [1, 2, 4, 5, 999]
>>> number_list.pop()
### 999
>>> number_list
### [1, 2, 4, 5]
Since we are using a mutable object, it is a good time to talk a little more about variables. Different variables can actually reference the same object. Think about names – whether you are using “Nathan” or “Nate”, both names are referring to me. Because of this, if there are two variables pointing to the same thing and it is modified through one of the variables, that modification can also be seen in the other variable.
flowchart LR
nate(['Nate' variable])
nathan(['Nathan' variable])
me(['Me' object])
nathan --> me
nate --> me
Below shows how the variables a and b reference the same object in memory, and c just references an object that looks the same but is actually different. It is important to keep in mind the difference between “equivalence”, tested with ==, and actually being the same object, checked using is.
>>> a = [1, 2, 3]
>>> b = a
>>> c = [1, 2, 3]
>>> a == b
### True
>>> a is b
### True
>>> a == c
### True
>>> a is c
### False
>>> a.append(4)
>>> a
### [1, 2, 3, 4]
>>> b
### [1, 2, 3, 4]
>>> c
### [1, 2, 3]
The list object has a number of useful functions that let you do things like sort values, reverse the list, count the number of occurrences of a value, and more. Remember, you can use dir and help to explore and find more information about anything you are seeing in this article. The most important ones to know right now are append, to add items to a list, pop to remove and return the last item from a list (or optionally at an index if one is provided), insert to add a value into a list at an index, and extend to add items from one list into another.
There are a few more things you should know about manipulating lists. Objects can be defined to use mathematical operators in ways different than with ordinary math expressions – this is called “operator overloading”. You had already seen in the previous article multiplication used to repeat a string. The + operator will combine two lists together to make a new list – leaving the original lists unchanged. The * operator will repeat a list, the same way that it repeats strings.
>>> list_a = [1, 2, 3]
>>> list_b = [4, 5, 6]
>>> list_a + list_b
### [1, 2, 3, 4, 5, 6]
>>> list_a * 3
### [1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> list_a
### [1, 2, 3]
>>> list_b
### [4, 5, 6]
A built-in function you will need to know when dealing with collections of values is the len function. It returns the “length” of the collection – or, in other words, how many things are in it.
>>> letter_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letter_list
### ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> len(letter_list)
### 7
>>> len("Hello World")
### 11
>>> len(mixed_tuple)
### 4
You might only need to use part of a list, tuple, or string. Python has a syntax for “slicing” collections that looks similar to indexing, since it uses [ and ], but there are colons : between parts signifying the “start” of the slice, the “end”, and the “step” (used to skip values). Take note of how the slice includes what is at the starting index, but does not include what is at the specified end index of the slice.
If a number is not provided, the default for the start index of the list, length of the list, or a step of 1 is used – depending on what part had been omitted. Negative index values can also be used if you want to get what is at the end of a list. A negative step will step through the list backwards (in reverse).
This slice is a new list, so modifying it does not change anything in the original list.
>>> letter_list[4:]
### ['e', 'f', 'g']
>>> letter_list[:4]
### ['a', 'b', 'c', 'd']
>>> letter_list[2:6]
### ['c', 'd', 'e', 'f']
>>> letter_list[2:6:2]
### ['c', 'e']
>>> letter_list[-3:]
### ['e', 'f', 'g']
>>> letter_list[::3]
### ['a', 'd', 'g']
>>> "Hello World!"[3:9]
### 'lo Wor'
>>> (1, 2, 3, 4, 5)[1:4]
### (2, 3, 4)
>>> "Python"[::-1]
### 'nohtyP'
The final thing I am going to say about lists is a brief mention of “list comprehension”. This is a way of creating lists by using a condensed syntax. Because the intention of these articles is not to be overly comprehensive, I am going to encourage looking them up if you want more information.
In this example, I am showing two ways of creating a list of even numbers. The first uses list comprehension, where there is some logic inside the [ and ] describing how to create the list. In this case, I am multiplying the values iterated over range by two to get the values the list will consist of.
In the second example, I am showing how you can construct an equivalent list without using list comprehension. It is looping over a range of values and adding two times the current iteration’s value to the list to build it up one item at a time.
The last example shows using list comprehension in a more advanced way by iterating over strings in a tuple and only adding to the list the string if the first character of the string is a “t”.
>>> [i * 2 for i in range(10)]
### [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> even = []
>>> for i in range(10):
... even.append(i * 2)
>>> even
### [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> [s for s in ('one', 'two', 'three', 'four', 'five', 'six') if s[0] == 't']
### ['two', 'three']
More About Strings
Now that you had learned a little about collections of data, it might be a good time to show some ways you can use them with strings. The string join method will join together the items from a collection with copies of the string inserted in between them – useful for making comma-separated lists. The split string method will split a string into a list wherever the specified substring is.
>>> alpha = ['a', 'b', 'c', 'd']
>>> ''.join(alpha)
### 'abcd'
>>> ', '.join(alpha)
### 'a, b, c, d'
>>> "1 2 3 4 5".split(' ')
### ['1', '2', '3', '4', '5']
Sets
Sets are a little bit similar to lists, in that they can have items added to them, but they serve a different purpose and behave a little differently. Sets should not be used when order matters – for that you will want to use a list. What sets are good for is quickly checking if an item is in the set. A list will need to use a slower process to find if the item is present or not, but a set can be used to very quickly make that check. I plan on writing a future article explaining more about data structures, so I won’t go into detail here.
Sets are created either using { and } with comma-separated items between them, or by using the set class. The items added to sets must be immutable (technically, it needs to be hashable, which means able to produce a consistent hash value), like strings, tuples, integers, etc.
>>> fruit_set = {"apple", "banana", "orange"}
>>> fruit_set
### {'apple', 'orange', 'banana'}
>>> "apple" in fruit_set
### True
>>> "banana" not in fruit_set
### False
>>> "pear" in fruit_set
### False
>>> "pear" not in fruit_set
### True
>>> fruit_set.add("pear")
>>> "pear" in fruit_set
### True
>>> fruit_set
### {'pear', 'apple', 'orange', 'banana'}
>>> fruit_set.add("pear")
>>> fruit_set
### {'apple', 'banana', 'orange', 'pear'}
>>> fruit_set.remove("apple")
>>> fruit_set
### {'pear', 'orange', 'banana'}
>>> len(fruit_set)
### 3
>>> type(fruit_set)
### <class 'set'>
>>> empty_set = set()
>>> empty_set
### set()
>>> type(empty_set)
### <class 'set'>
The most important set methods to know are add and remove to add and remove items. Unlike lists, which can have duplicates of something in it, adding the same item to a set multiple times only includes it once.
Like with lists and tuples, the len function can be used on a set to see how many items are in it. You can also iterate over items in a set.
Sets are a mathematical concept, so if you are familiar with them from math, you can understand how they might be used in Python. Here are set operations along with their math notation and Python equivalent.
| Operation | Math | Python |
|---|---|---|
| Union | \(A \cup B\) | A | B |
| Intersection | \(A \cap B\) | A & B |
| Difference | \(A \setminus B\) | A - B |
| Symmetric Difference | \(A \triangle B\) | A ^ B |
| Subset | \(A \subseteq B\) | A <= B |
| Proper Subset | \(A \subset B\) | A < B |
| Superset | \(A \supseteq B\) | A >= B |
| Proper Superset | \(A \supset B\) | A > B |
| Membership | \(x \in A\) | x in A |
| Non-membership | \(x \notin A\) | x not in A |
I am not going to explain all of them here, because these articles are intended to quickly help one become aware of what is in Python and not intended to be completely thorough and comprehensive. I can demonstrate what a few of these do, though. “Union” will make a set that contains all the items of both sets. “Intersection” will make a set that contains items that both sets contain. “Difference” will make a set that has items in the first set, but no items from the second set. For more information, see the Wikipedia page on Set (mathematics) “basic operations” section.
>>> A = {1, 2, 3, 4}
>>> B = {3, 4, 5, 6}
>>> A | B
### {1, 2, 3, 4, 5, 6}
>>> A & B
### {3, 4}
>>> A - B
### {1, 2}
>>> A ^ B
### {1, 2, 5, 6}
>>> {1, 2} < A
### True
>>> {1, 2, 3, 4} <= A
### True
>>> {1, 2, 3, 4} < A
### False
>>> 3 in A
### True
>>> 2 not in B
### True
Sets are often very useful for implementing certain kinds of algorithms because they can be used to quickly check if the algorithm had seen something before. For example, if an algorithm was made to solve a maze, a set can be used to check if a hallway looped back around to part of the maze it had been in before.
Dictionaries
Dictionaries are very useful data structures. With a list, you can look up values using a numeric index, but what if you wanted to use something other than an item’s position in the list to find it? That’s where dictionaries can be used. A dictionary can associate a value with a key – most often people use strings for keys, but any built-in immutable (hashable) type can be used. A dictionary can be created using curly braces { and }, with key/value pairs separated by a colon :, or can be created using the dict object.
>>> phone_numbers = {
... "Bob": "555-1234",
... "Andy": "555-7654",
... "Dave": "555-3333"
... }
>>> phone_numbers
### {'Bob': '555-1234', 'Andy': '555-7654', 'Dave': '555-3333'}
>>> phone_numbers["Bob"]
### '555-1234'
>>> phone_numbers.get("Bob")
### '555-1234'
>>> phone_numbers.get("Emily")
>>> phone_numbers["Emily"]
### Traceback (most recent call last):
### File "<pyshell#5>", line 1, in <module>
### phone_numbers["Emily"]
### KeyError: 'Emily'
>>> phone_numbers.get("Emily", "Number Not Found")
### 'Number Not Found'
>>> "Andy" in phone_numbers
### True
>>> for key, value in phone_numbers.items():
... print(f"{key}:\t{value}")
### Bob: 555-1234
### Andy: 555-7654
### Dave: 555-3333
>>> phone_numbers["Janet"] = "555-9999"
>>> phone_numbers.keys()
### dict_keys(['Bob', 'Andy', 'Dave', 'Janet'])
>>> phone_numbers.values()
### dict_values(['555-1234', '555-7654', '555-3333', '555-9999'])
You can get items from a dictionary using either square brackets [ and ], or by using the get method. Note, above, that using the square brackets throws an error if the key is not in the dictionary, but get will either return None by default, or fall back on a value you provide.
You might be wondering why dictionary keys and set items need to be immutable. It would be too much to go into detail about data structure implementations in this article, but I can use a rough analogy to help explain. To optimize data retrieval, the data needs to be stored in the data structure in a way where the key or set element can be quickly found by its value. If the value could change (being mutable), where the object was stored will no longer match its new the value.
As an analogy, imagine you wanted to make it easier to find people so you put them in rooms according to the first letter of their name – Alex in the A room, etc. Now, if Alex were allowed to change his name to Tony, he would still be in the A room, even though his name no longer starts with A. Someone wants you to find Tony, so you look in the room that has a T on the door and cannot find him – he used to be Alex. That’s generally the idea with dictionaries and sets – what are used as dictionary keys or set elements have to stay unchanged so the computer can quickly find what it’s looking for.
If you want to remove an element from a dictionary completely, you can use the del keyword, or you can use the pop method to remove a dictionary entry and return the value. The del keyword can also be used to “delete” list elements, variables, functions, classes, etc.
>>> phone_numbers
### {'Bob': '555-1234', 'Andy': '555-7654', 'Dave': '555-3333', 'Janet': '555-9999'}
>>> del phone_numbers['Andy']
>>> phone_numbers
### {'Bob': '555-1234', 'Dave': '555-3333', 'Janet': '555-9999'}
>>> phone_numbers.pop("Dave")
### '555-3333'
>>> phone_numbers
### {'Bob': '555-1234', 'Janet': '555-9999'}
>>> del phone_numbers
>>> phone_numbers
### Traceback (most recent call last):
### File "<pyshell#35>", line 1, in <module>
### phone_numbers
### NameError: name 'phone_numbers' is not defined
>>> numbers = [1, 2, 3, 4, 5]
>>> numbers
### [1, 2, 3, 4, 5]
>>> del numbers[2]
>>> numbers
### [1, 2, 4, 5]
What the Next Article Will Cover
- Using the Terminal
- Visual Studio Code
- PyCharm
- A Deeper Understanding of Functions
- Advanced Iterating
- Decorators
- Creating Classes and Objects
- Reading From and Writing To Files
- Error Handling
- Useful and Fun Modules