Learning Python - Day 4
???????????? ?????????? ?? ??
Experienced Full Stack Engineer | Next.JS, MERN
Installing and Starting Python
Overview
In this module, we'll cover obtaining and installing Python on your system for Windows, Ubuntu Linux, and macOS. We'll write some basic Python code and become acquainted with the essentials of Python programming culture, such as the Zen of Python. Though we'll never forget the origins of the name of the language. There are two major versions of the Python language, Python 2, which is the widely?deployed legacy language, and Python 3, which is the present and future of the language. It's now over a decade since the transition from Python 2 to Python 3 was begun, and we strongly recommend that all new projects are begun with Python 3 as Python 2 will not be maintained from the year 2020. That said, most of the Python code we will demonstrate will work without modification between the last version of Python 2, which is Python 2.7, and recent versions of Python 3, such as Python 3.8. However, there are some key differences, and in a strict sense, the languages are incompatible. We'll be using Python 3 for this course, and everything we show will work on Python 3.6 or later, and most things will work on Python 3.3 or later. We're also confident that everything we present will apply to future versions of Python 3, so don't be afraid to try those as they become available.
Installing Python
Before we can start programming in Python, we need to get hold of a Python environment. Python is a highly portable language available on all major operating systems. You will be able to complete this course on Windows, Mac, or Linux, and the only major section where we diverge into platform specifics is coming right up, as we install Python 3. As we cover the three platforms, feel free to skip over the sections which aren't relevant for you. Let's see how to install Python 3 on Windows 10. For Windows, you need to visit the official Python website at python.org and then navigate via the Downloads tab to the downloads for Windows and click the button to begin downloading the latest Python 3 version. When given the option, choose to run the installer. After the installer starts, be sure to enable the option to add Python to the PATH environment variable before moving on by clicking Install Now. You may be asked to approve the Python Installer making changes to your device, which you should accept. After a few seconds, the installer will complete and you can close the installer and your web browser. We'll be working with Python from the command line, so via the Start button, choose Windows PowerShell. On older versions of Windows, you may need to use the Command shell instead, and start Python just by typing python, followed by Enter. Welcome to Python. The triple arrow prompt shows you that Python is waiting for your input. At this point, you might want to skip forward while we show you how to install Python on Mac and Linux. Now let's see how to install Python 3 on macOS. For macOS, you need to visit the official Python website at python.org. Navigate via the Downloads tab to the downloads for macOS, and click the button to begin downloading the latest Python 3 version. A PKG file downloads, which, when opened, launches the Python Installer. Continue through the install process, accepting the license agreement and using the default installation location. You may need to provide your password as you go. Although macOS does include a Python interpreter, it's the legacy Python 2.7 version, and for this course we use Python 3. The Python 3 version we're installing here will sit alongside your system Python 2 and won't interfere with the correct operation of your Mac. When Python is installed, you can clean up by moving the installer to the trash. To use Python, open a terminal, here we're using Spotlight to do so, and run Python 3 from the command line. Welcome to Python. The triple arrow prompt shows that Python is waiting for your input. The last operating system we'll look at is Linux, which is the easiest of all. Recent versions of Ubuntu Linux include Python 3 out of the box, so no installation is required. To begin using Python, open a terminal. On Ubuntu we can do this by using the search function accessible through the Ubuntu icon on the top left, entering terminal, and launching the terminal application. In the terminal, you should be able to start Python 3. Welcome to Python. The triple arrow prompt shows you that Python is waiting for your input. If you're using a version of Linux other than Ubuntu, you'll need to find out how to invoke and, if necessary, install Python 3 on your system.
Interactive Python
Now that Python is installed and running, we can immediately start using it interactively. This is a good way to get to know the language, as well as a useful tool for experimentation and quick testing during normal development. This Python command?line environment is a read, eval, print loop. Python will read whatever input we type in, evaluate it, print the result, and then loop back to the beginning. You'll often hear it referred to as simply the REPL. When started, the REPL will print some information about the version of Python you're running, and then it will give you a triple?arrow prompt. This prompt tells you that Python is waiting for you to type something. Within an interactive Python session, you can enter fragments of Python programs and see instant results. Let's start with some simple arithmetic. As you can see, Python reads our input, evaluates it, prints the result, and loops around to do the same again. We can assign the variables in the REPL, print their contents simply by typing their name, and refer to them in expressions. Within the REPL, you could use the special underscore variable to refer to the most recently printed value, this being one of the very few obscure shortcuts in Python, or you can use the special underscore variable in an expression. Remember though that this useful trick only works at the REPL. The underscore doesn't have any special behavior in Python scripts or programs. Notice that not all statements have a return value. When we assigned 5 to x, there was no return value, only the side effect of bringing the variable x into being. Other statements have more visible side effects. Try typing print Hello, Python, at the prompt, you'll need parentheses after the print and quotes around the text, then press enter. You'll see that Python immediately evaluates and executes this command, printing the string Hello, Python and returning you to another prompt. It's important to understand that the response here is not the result of the expression being evaluated and displayed by the REPL. Rather, it is a side effect of the print function. As an aside, print is one of the biggest differences between Python 2 and Python 3. In Python 3, the parentheses are required, whereas in Python 2, they are not. This is because in Python 3, print is a function call. More on functions later. At this point, we should show you how to exit the REPL and get back to your system shell prompt. We do this by sending the end of file control character to Python. Although, unfortunately, the means of sending this character varies across platforms. If you're on Windows, press Ctrl+Z followed by Enter to exit. If you're on Mac or Linux, press Ctrl+D to exit. If you regularly switch between platforms and you accidentally press Ctrl+Z on a UNIX?like system, you will inadvertently suspended the Python interpreter and return to your operating system's shell. To reactivate Python by making it a foreground process again, simply run the fg command and press Enter a couple of times to get the triple?arrow Python prompt back.
Significant Whitespace
Now that you have a working Python REPL, let's look at some basic code structure. Start your Python 3 interpreter using the Python or Python 3 command for Windows or Unix?like systems, respectively. The control flow structures of Python, such as for loops, while loops, and if statements, are all introduced by statements which are terminated by a colon, indicating that the body of the construct is to follow. For example, for loops require a body, so if you enter for i in range 5, Python will change the prompt to 3 dots to request you provide the body. One distinctive and sometimes controversial aspect of Python is that leading whitespace is syntactically significant. What this means is that Python uses indentation levels rather than the braces used by other languages to demarcate code blocks. By convention, contemporary Python code is indented by four spaces for each level, so we provide those four spaces and a statement to form the body of the loop. Our loop body will contain a second statement. So after pressing Return and getting another three dot prompt, we'll enter another four spaces, followed by a call to the built?in print function. To terminate our block, we must enter a blank line into the REPL. With the block complete, Python executes the pending code, printing out the multiples of 10, less than 50. Looking at a screen full of Python code, we can see how the indentation clearly matches and, in fact, must match the structure of the program. Even if we replace the code by gray lines, the structure of the program is clear. Each statement terminated by a colon starts a new block and introduces an additional level of indentation, which continues until the de?dent restores the indentation to a previous level. Each level of indent is typically four spaces, although we'll cover the rules in more detail in a moment. Python's approach to significant white space has three great advantages. First, it forces developers to use a single level of indentation in a code block. This is generally considered good practice in any language because it makes code much more readable. Second, code with significant whitespace doesn't need to be cluttered with unnecessary braces, and you never need to have code standard debates about where the braces should go. All code blocks in Python code are easily identifiable and everyone writes them the same way. Third, significant whitespace requires that a consistent interpretation must be given to the structure of the code by the author, the Python runtime system, and future maintainers who need to read the code. As a result, you could never have code that contains a block from Python's point of view, but which doesn't look like it from a cursory human perspective. The rules for Python indentation can seem complex, but are straightforward in practice. The whitespace you use can be either tabs or spaces. The general consensus is that spaces are preferable to tabs, and four spaces has become a standard in the Python community. One essential rule is never to mix spaces and tabs. The Python interpreter will complain, and your colleagues will hunt you down. You are allowed to use different amounts of indentation at different times, if you wish. The essential rule is that consecutive lines of code at the same indentation level are considered to be part of the same code block. There are some exceptions to these rules, but they almost always have to do with improving code readability in other ways, for example, by breaking up necessarily long statements over multiple lines. This rigorous approach to code formatting is programming as Guido intended it, or indented it. This philosophy of placing a high value on code qualities, such as readability, gets to the very heart of Python culture, something we'll take a short break to explore now.
Python Culture
Many programming languages are at the center of a cultural movement. They have their own communities, values, practices, and philosophy, and Python is no exception. The development of the Python language itself is managed through a series of documents called Python Enhancement Proposals, or PEPs. One of the PEPs, called PEP 8, explains how you should format your code, and we follow its guidelines throughout this course. It is PEP 8, which recommends we use 4 spaces for indentation in new Python code. Another of these PEPs, called PEP 20, is called The Zen of Python. It refers to 20 aphorisms describing the guiding principles of Python, only 19 of which have been written down. Conveniently, The Zen of Python is never further away than the nearest Python interpreter as it can always be accessed from the REPL by typing import this. Throughout this course, we'll be highlighting particular nuggets of wisdom from the Zen of Python in Moments of Zen, to understand how they apply to what we have learned. As we've just introduced Python significant indentation, this is a good time for our first Moment of Zen. Readability counts, clarity matters, so readability makes for valuable code. In time, you'll come to appreciate Python's significant whitespace for the elegance it brings to your code and the ease with which you can read other's.
The Python Standard Library
As mentioned earlier, Python comes with an extensive standard library, an aspect of Python often referred to as batteries included. The standard library is structured as modules, a topic we'll discuss in depth later in this course. What's important at this stage is to know that you gain access to standard library modules by using the import keyword. The basic form of importing a module is simply the import keyword followed by a space and the name of the module. For example, let's see how we can use the standard libraries math module to compute square roots. At the Triple Arrow prompt, we type import math. Since import is a statement which doesn't return a value, Python doesn't print anything if the import succeeds and were immediately returned to the prompt. We can access the contents of the imported module by using the name of the module, followed by a dot, followed by the name of the attribute in the module that you need. Like many object?oriented languages, the dot operator is used to drill down into object structures. Being expert Pythonistas, we have inside knowledge that the math module contains a function called SQRT. Let's try to use it. But how can we find out what other functions are available in the math module? The REPL has a special function, help, which can retrieve any embedded documentation from objects for which it has been provided, such a standard library modules. To get help, simply type help. We'll leave you to explore the first form for interactive help on your own time. We'll go for the second option and pass the math module as the object for which we want help. You can use the Space bar to page through the help. If you're on Mac or Linux, use the arrow keys to scroll up and down. Browsing through the functions, we can see that there is a math function for computing factorials. Press Q to exit the help browser and return us to the Python REPL. Practice using help to request specific help on the factorial function, press Q to return to the REPL. Let's use the factorial function, which accepts an integer and returns an integer. Notice how we need to qualify the function name with the name of the module containing it. This is generally good practice as it makes it abundantly clear where the function is coming from. That said, it can result in code that is excessively verbose. To see that, let's use factorial to compute how many ways there are to draw three fruit from a set of five fruit using some math we learned in school. This simple expression is quite verbose with all those references to the math module. The Python import statement has an alternative form that allows us to bring a specific function from a module into the current namespace. This is a good improvement, but it's still a little long winded for such a simple expression. A third form of the import statement allows us to rename the imported function. This can be useful for reasons of readability or to avoid a namespace clash. Useful as it is, we recommend that this feature be used infrequently and judiciously. Remember that when we used factorial alone, it returned an integer, but our more complex expression for combinations is returning a floating point number. This is because we've used pythons floating point division operator, the single forward slash. We can improve our expression since we know it will only ever return integral results by using Python's integer division operator, which is a double forward slash. What's notable is that many other programming languages would fail on the above expression for even moderate values of n. In most programming languages, regular garden variety signed integers can only store values less than 2 to the 31st power. However, factorials grow so fast that the largest factorial you can fit into a 32?bit signed integer is 12 factorial since 13 factorial is too large. In most widely?used programming languages, you would need more complex code or more sophisticated mathematics merely to compute how many ways there are to draw 3 fruit from a set of 13 fruits. Python encounters no such problems and can compute with arbitrarily large integers limited only by the memory in your computer. Let's try the larger problem of computing how many different pairs of fruit we can pick from 100 different fruits assuming we can lay our hands on so much fruit. Just to emphasize how large the size of the first term in that expression is, calculate 100 factorial on its own. This is a number vastly larger than even the number of atoms in the known universe with an awful lot of digits. If, like me, you're curious to know exactly how many digits, we can convert our integer to a text string and count the number of characters in it like this.
Scalar Types, Operators, and Control Flow
Overview
Now that you've got a functional Python REPL on your system, we can start to work with the fundamentals of the language. In this module of Core Python: Getting Started, you'll start to learn about Python's fundamental scalar types. We'll look at basic use of relational operators, and we'll introduce basic flow?control mechanisms. Python comes with a number of built?in data types. These include primitive scalar types like integers, as well as collection types like dictionaries. These built?in types are powerful enough to be used alone for many programming needs, and they can be used as building blocks for creating more complex data types. In this section, we cover the basic scalars, int for whole numbers; float for numbers with fractional parts; None, an important placeholder value; and bool, used for True and False values. We'll provide basic information about these now, showing their literal forms and how to create them. We've already seen quite a lot of Python integers in action. Python integers are signed, and have, for all practical purposes, unlimited precision, meaning they can contain as many digits as you need. Integer literals in Python are specified in decimal, and may also be specified in binary with the 0b prefix, in octal with the 0o prefix, or in hexadecimal with the 0x prefix. We can also construct integers by a call to the int constructor. This can convert from other numeric types, such as floats, to integers. Note that the rounding of integers is always towards zero. The int constructor can also convert strings to integers. You can even supply an optional number base when converting from a string. For example, to convert from base 3, provide the value 3 as the second argument to the int constructor. Floating point numbers are supported in Python by the float type. Python floats are implemented as IEEE?754 double?precision floating point numbers with 53 bits of binary precision. This is equivalent to between 15 and 16 significant digits in decimal. Any literal number containing a decimal point is interpreted by Python as a float. Scientific notation can be used, so for large numbers, such as the approximate speed of light in meters per second, 3 times 10 to the eighth, we can write 3e8, and for small numbers like Planck's constant, 1.616 times 10 to the negative thirty?fifth, we can enter 1.616e?35. Notice how Python automatically switches the display representation, that is, the format it prints to the REPL, to the most readable form. As with integers, we can convert to floats from other numeric or string types using the float constructor. We can pass int values to the float constructor, and we can pass strings. This is also how we create the special floating point values nan, or not a number, as well as positive infinity and negative infinity. One important rule to remember is that the result of any calculation involving int and float is promoted to a float. You can read more about Python's number types in Python's documentation. Python has a special null value called None, spelled with a capital N. None is frequently used to represent the absence of a value. The Python REPL never prints None results, so typing None into the REPL has no effect. None could be bounded to variable names just like any other object, and we can test whether an object is None by using Python's is operator. We can see here that the result of the is operator in this case is True, which brings us conveniently onto the bool type. The bool type represents logical states, and plays an important role in several of Python's control flow structures, as we'll see shortly. As you probably expect, there are two bool values, True and False, both spelled with initial capitals. There is also a bool constructor which can be used to convert from other types to bool. Let's look at how it works. For integers, zero is considered Falsy and all other values Truthy. We see the same behavior with floats, where only zero is considered Falsy. When converting from collections, such as strings or lists, only empty collections are treated as Falsy. For lists, which we'll look at shortly, the empty list is Falsy, while any non?empty list is Truthy. Similarly, empty strings are Falsy, while any other strings are Truthy. It's worth noting that the bool constructor may not behave as you expect when passing in the strings True and False. Since both are non?empty strings, both result in True. These conversions to bool are important, because they are widely used in Python if statements and while loops, which accept bool values into the condition. We'll look at these constructs soon.
领英推荐
Relational Operators
Bool values are commonly produced by Python's relational operators, which can be used for comparing objects. These include value equality or equivalents, value inequality or inequivalence, less than, greater than, less than or equal to, and greater than or equal to. Two of the most widely used relational operators are Python's equality and inequality tests. These test whether two objects are equivalent or inequivalent, that is, whether one can be used in place of the other or not. We'll learn more about the notion of object equivalents later in the course, but for now, we'll just compare simple integers. Let's start by assigning or binding a value to the variable g. We test for equality with the == operator, and we test for inequality using the not equals operator, an exclamation point followed by an equal sign. We can also compared the order of quantities using the rich comparison operators. We check if one object is less than another with the less than operator. We can append an equal sign to this operator to test for less than or equal. Likewise, we check if an object is greater than another with the greater than operator, and as with less than, there is the related greater than or equal operator.
Control Flow
Now that we've examined some basic built?in types, we'll look at two important control flow structures, which depend on the conversions to the bool type, if statements and while loops. We'll start with if statements, also known as conditional statements. Conditional statements allow us to branch execution based on the value of an expression. The form of the statement is the if keyword, followed by an expression, terminated by a colon to introduce a new block. Let's try this at the REPL. Remembering to indent four spaces within the block, we add some code to be executed if the condition is true. We terminate the blocked by entering a blank line. Because the condition is self?evidently true, the block executes, and we see the string, It's true!, printed to the REPL. Conversely, if the condition is false, the code in the block does not execute. The expression used with the if statement will be converted to a bool, just as if the bool constructor had been used, so explicitly constructing a bool in the if statement is exactly equivalent to using a bare string. Thanks to this useful shorthand, explicit conversion to bool using the bool constructor is rarely used in Python. The if statement supports the optional else?claus that goes in a block introduced by the else keyword followed by colon, which is indented to the same level as the if keyword. To start the else block, in this case, we just omit the indentation after the three dots. For multiple conditions, you might be tempted to nest if statements inside else blocks like this. Whenever you find yourself doing this though, you should consider using Python's lf keyword, which is a combined else?if. As the Zen of Python reminds us, flat is better than nested. This version is altogether easier to read.
While-loops
Python has two types of loop, for loops and while loops. We've already briefly introduced for loops back when we introduced significant white space, and we'll return to them soon, but right now we'll cover for loops. While loops in Python are introduced by the while keyword, which is followed by a Boolean expression. As with the condition for if statements, the expression is implicitly converted to a Boolean value, as if it had been passed to the bool constructor. The while statement is terminated by a colon because it introduces a new block. Let's write a loop at the REPL, which counts down from 5 to 1. We'll initialize a counter variable called C to 5, and keep looping until we reach zero. Another new language feature here is the use of the augmented assignment operator, a minus sign followed by an equal sign to subtract one from the value of C on each iteration. Similar augmented assignment operators exist for other basic math operators, such as plus and multiply. Because the condition, also called the predicate, will be implicitly converted to bool, just as if a call to the bool constructor present, we could replace the above code with the following version. This works because the conversion of the integer value of C to bool results in true until we get to zero, which converts to false. That said, to use this short form in this case might be described as unPythonic because, referring back to the Zen of Python, explicit is better than implicit, and we place a higher value on the readability of the first form over the concision of the second form. While loops are often used in Python, where an infinite loop is required. We achieve this by simply passing true as the predicate expression to the while construct. Now you're probably wondering how to get out of this loop and regain control of your REPL. To do this, we press Ctrl+C. Python intercepts this to raise a special exception which terminates the loop. We'll be talking much more about what exceptions are and how to use them later in the course. Many programming languages support a loop construct which places the predicate test at the end of the loop rather than at the beginning. For example, C, C++, C #, and Java support the do while construct. Other languages have repeat until loops instead or as well. This is not the case in Python, where the idiom is to use, while true, together with an early exit facilitated by the break statement, the break statement jumps out of the loop and only the innermost loop, if several loops have nested, and then continues execution immediately after the loop body. Let's look at an example of break, introducing a few other Python features along the way. We start with a while true for an infinite loop. On the first statement of the while block, we used the built in input function to request a string from the user. We assigned that string to a variable called response. We now use an if statement to test whether the value provided is divisible by seven. We convert response to an integer, using the int constructor and then use the modulus operator, the percent symbol to divide by 7 and give the remainder. If the remainder is equal to 0, the response was divisible by 7, and we enter the body of the if block. Within the if block, now two levels of indentation deep, we start with eight spaces and use the break keyword. Break terminates the innermost loop, in this case the while loop, and causes execution to jump to the first statement after the loops. In our case, this is the end of the program. Enter a blank line that the three dots prompt to close both the if block and the while block. Our loop will start executing and will pause at the call to the input function waiting for us to enter a number. Let's try a few. As soon as we enter a number divisible by seven, the predicate becomes true. We enter the if block and then literally break out of the loop, ending the program and returning us to the REPL prompt.
String
Strings in Python have the data type str, spelled s?t?r, and we've been using them extensively already. Strings are sequences of Unicode code points, and for the most part, you can think of code points as being like characters, although they are not strictly equivalent. The sequence of characters in a Python string is immutable, meaning that once you've constructed a string, you can't modify its contents. Literal strings in Python are delimited by quotes, you could use single quotes or double quotes. You must, however, be consistent. For example, you can't use single quotes on one side and double on the other, like this. Supporting both quoting styles allows you to easily incorporate the other quote character into the literal string without resorting to ugly escape character gymnastics. Notice that the REPL exploits the same, quoting flexibility when echoing the strings back to us. Beautiful text strings rendered in literal form, simple elegance. At first sight, support for both quoting styles seems to violate an important principle of Pythonic style from the Zen of Python. There should be one, and preferably only one, obvious way to do it. In this case, however, another aphorism from the same source, practicality beats purity, takes precedence. The utility of supporting two quoting styles is valued more highly than the alternative, a single quoting style combined with more frequent use of ugly escape sequences, which we'll encounter shortly.
String Literals
Adjacent literal strings are concatenated by the Python compiler into a single string, which, although at first it seems rather pointless, can be useful for a nicely formatted code, as we'll see later. If you want a literal string containing newlines, you have two options, use multiline strings or use escape sequences. First, let's look at multiline strings. Multiline strings are delimited by three quote characters rather than one. Here's an example using three double quotes. Notice how, when the string is echoed back to us, the newlines are represented by the \n escape sequence. We can also use three single quotes. As an alternative to using multiline quoting, we can just embed the control characters ourselves. To get a better sense of what we're representing, we can use print to see the string. If you're working on Windows, you might be thinking that newlines should be represented by the carriage return and newline couplet \r\n. There's no need to do that with Python. Since Python 3 has a feature called Universal Newline Support, which translates from the simple \n to the native newline sequence for your platform on input and output. You can read more about Universal Newline Support in PEP 278. We can use the escape sequences for other purposes, too, such as incorporating tabs with \t or allowing us to quote characters within strings by using \ double quote or \ single quote. See how Python is smarter than we are at using the most convenient quote delimiters, although Python will also resort to escape sequences when we use both types of quotes in a string. Because backslash has special meaning, to place a backslash in a string, we escape the backslash with itself. To reassure ourselves that there really is only one backslash in that string, we can print it. You can read more about escape sequences in the Python documentation at python.org. Sometimes, particularly when dealing with strings such as Windows file system paths or regular expression patterns, which use backslashes extensively, the requirement to double up on backslashes can be ugly and error prone. Python comes to the rescue with its raw strings. Raw strings don't support any escape sequences and are very much what you see is what you get. To create a raw string, prefix the opening quote with a lowercase r. We can use the string constructor to create string representations of other types such as integers or floats. Strings in Python are what are called sequence types, which means they support certain common operations for querying sequences. For example, we can access individual characters using square brackets with an integer 0?based index. Note that in contrast to many programming languages, there is no separate character type distinct from the string type. The indexing operation we just used returns a full?blown string that contains a single character element, something we can test using Python's built?in type function. There will be more on types and classes later in the course. String objects also support a wide variety of operations implemented as methods. We can list those methods using help on the string type. Ignore all the hieroglyphics with underscores for now and page down until you see the documentation for the capitalized method. Press Q to quit the help browser, and we'll try to use that method. First, let's make a string that deserves capitalization, the proper noun of a capital city, no less. To call methods on objects in Python, we use the dot after the object name and before the method name. Methods are functions, so we must use the parentheses to indicate that the method should be called. Remember that strings are immutable, so the capitalized method didn't modify c in place, rather, it returned a new string. We can verify this by displaying c, which remains unchanged. You might like to spend a little time familiarizing yourself with the various useful methods provided by the string type. Finally, because strings are fully Unicode capable, we can use them with international characters easily, even in literals because the default source code encoding for Python 3 is UTF?8. For example, if you have access to Norwegian characters, you can simply enter this. Alternatively, you can use the hexidecimal representations of Unicode code points as an escape sequence prefixed by \u, which I'm sure you'll agree, is somewhat more unwieldy. Similarly, you can use the \x escape sequence, followed by a two?character hexidecimal string or an escaped octal string to include Unicode characters in a string literal. There are no such Unicode capabilities in the otherwise similar bytes type, which we'll look at next.
Bytes
Bytes are very similar to strings, except that rather than being sequences of Unicode code points, they are sequences of, well, bytes. As such, they are used for raw binary data and fixed?width single?byte character encodings such as ASCII. As with strings, they have a simple, literal form using quotes, the first of which is prefixed by a lower case b. There is also a bytes constructor, but it's an advanced feature and we won't cover it in this fundamentals course. At this point, it's sufficient for us to recognize bytes literals, and understand that they support most of the same operations as string, such as indexing, which returns the integer value of the specified byte, and splitting, which you'll see returns a list of bytes objects. To convert between bytes and strings, we must know the encoding of the byte sequence used to represent the string's Unicode code points as bytes. Python supports a wide variety of encodings, a full list of which can be found at python.org. Let's start with an interesting Unicode string which contains all the characters of the 29?letter Norwegian alphabet, a pangram. We'll now encode that using UTF?8 into a bytes object. See how the Norwegian characters have each been rendered as pairs of bytes. We can reverse that process using the decode method of the bytes object. Again, we must supply the correct encoding. We can check that the result is equal to what we started with, and display it for good measure. This may seem like an unnecessary detail so early in the course, especially if you operate in an anglophone environment, but it's a crucial point to understand since files and network resources such as HTTP responses are transmitted as byte streams, whereas we often prefer to work with the convenience of Unicode strings.
List
Python lists, such as those returned by the string split method are sequences of objects. Unlike strings, lists are mutable, insofar as the elements within them can be replaced or removed, and new elements can be inserted or appended. Lists are a workhorse of Python data structures. Literal lists are delimited by square brackets, and the items within the list separated by commas. Here is a list of three numbers and a list of three strings. We can retrieve elements by using square brackets with a zero?based index, and we can replace elements by assigning to a specific element. See how lists can be heterogeneous with respect to the types of the objects. We now have a list containing a string, an integer, and another string. It's often useful to create an empty list, which we can do using empty square brackets. We can modify the list in other ways. Let's add some floats to the end of the list using the append method. There are many other useful methods for manipulating lists, which we'll cover in a later module. There's also a list constructor, which can be used to create lists from other collections such as strings. Finally, although the significant whitespace rules in Python can at first seem very rigid, there is a lot of flexibility. For example, if at the end of the line brackets, braces or parentheses are unclosed, you can continue on the next line. This can be very useful for long, literal collections, or simply to improve readability. See also how we're allowed to use an additional comma after the last element. This is an important maintainability feature.
Dict
Dictionaries are completely fundamental to the way the Python language works and are very widely used. A dictionary maps keys to values, and in other languages, is known as a map or an associative array. Let's look at how to create and use them in Python. Literal dictionaries are created using curly braces containing key?value pairs. Each pair is separated by a comma, and each key is separated from the corresponding value by a colon. Here, we use a dictionary to create a simple telephone directory. We can retrieve items by key using the square brackets operator and update the values associated with the key by assigning through the square brackets. If we assign to a key that has not yet been added, a new entry is created. Be aware that in Python versions prior to 3.7, the entries in the dictionary can't be relied upon to be stored in any particular order. As of Python 3.7, however, entries are required to be kept in insertion order. Similarly, to lists, empty dictionaries can be created using empty curly braces. We'll revisit dictionaries in much more detail in a later module
For-loop
Now that we have the tools to make some interesting data structures, we'll look at Python's second type of loop construct, the for loop. For loops in Python correspond to what are called for each loops in many other programming languages. They request items one by one from a collection, or more strictly, from an iterable series, but more on that later, and assign them in turn to a variable that we specify. Let's create a collection and use a for loop to iterate over it. If you iterate over dictionaries, you get the keys, which you can then use within the for loop body to retrieve values. Here we define a dictionary mapping string color names to hexadecimal integer color codes. Note that we used the ability of the built?in print function to accept multiple arguments. We passed the key and the value for each color separately. See also how the color codes returned to us are in decimal.