diff --git a/comprehensions.html b/comprehensions.html index 6d19fbe..79db3bf 100644 --- a/comprehensions.html +++ b/comprehensions.html @@ -16,13 +16,13 @@ body{counter-reset:h1 3}
Difficulty level: ♦♦♢♢♢
-❝ FIXME ❞
— FIXME +❝ Our imagination is stretched to the utmost, not, as in fiction, to imagine things which are not really there, but just to comprehend those things which are. ❞
— Richard Feynman
This chapter will teach you about list comprehensions, dictionary comprehensions, and set comprehensions: three related concepts centered around one very powerful technique. But first, I want to take a little detour into two modules that will help you navigate your local file system. -
os modulePython 3 comes with a module called os, which stands for “operating system.” The os module contains a plethora of functions to get information on — and in some cases, to manipulate — local directories, files, processes, and environment variables. Python does its best to offer a unified API across all supported operating systems so your programs can run on any computer with as little platform-specific code as possible.
@@ -61,7 +61,7 @@ body{counter-reset:h1 3}
os.chdir() function, I used a Linux-style pathname (forward slashes, no drive letter) even though I’m on Windows. This is one of the places where Python tries to paper over the differences between operating systems.
-os.path moduleWhile we’re on the subject of directories, I want to point out the os.path submodule. os.path contains functions for manipulating filenames and directory names.
@@ -106,7 +106,7 @@ body{counter-reset:h1 3}
os.path also contains the os.path.splitext() function, which splits a filename and returns a tuple containing the filename and the file extension. You use the same technique to assign each of them to separate variables.
-glob moduleThe glob module is another tool in the Python standard library. It’s an easy way to get the contents of a directory programmatically, and it uses the sort of wildcards that you may already be familiar with from working on the command line.
@@ -142,70 +142,82 @@ body{counter-reset:h1 3}
.py extension and contain the word test anywhere in their filename.
-Now you’re ready to learn about comprehensions. +
Every modern file system stores metadata about each file: creation date, last-modified date, file size, and so on. Python provides a single API to access this metadata. You don’t need to open the file; all you need is the filename. + +
+>>> import os +>>> print(os.getcwd()) ① +c:\Users\pilgrim\diveintopython3\examples +>>> metadata = os.stat('feed.xml') ② +>>> metadata.st_mtime +1247520344.9537716 +>>> import time ③ +>>> time.localtime(metadata.st_mtime) ④ +time.struct_time(tm_year=2009, tm_mon=7, tm_mday=13, tm_hour=17, + tm_min=25, tm_sec=44, tm_wday=0, tm_yday=194, tm_isdst=1) ++
+# continued from the previous example +>>> metadata.st_size ① +3070 +>>> import humansize ++>>> humansize.approximate_size(metadata.st_size) ② +'3.0 KiB'
In the previous example, the glob.glob() function returned a list of relative pathnames. The first example had pathnames like 'examples\feed.xml', and the second example had even shorter relative pathnames like 'romantest1.py'. As long as you stay in the same current working directory, these relative pathnames will work for opening files or getting file metadata. But if you want to construct an absolute pathname — i.e. one that includes all the directory names back to the root directory or drive letter — then you’ll need the os.path.abspath() function.
+
+
+>>> import os
+>>> print(os.getcwd())
+c:\Users\pilgrim\diveintopython3\examples
+>>> print(os.path.abspath('feed.xml'))
+c:\Users\pilgrim\diveintopython3\examples\feed.xml
One of the most powerful features of Python is the list comprehension, which provides a compact way of mapping a list into another list by applying a function to each - of the elements of the list. - -
>>> li = [1, 9, 8, 4] ->>> [elem * 2 for elem in li] ① -[2, 18, 16, 8] ->>> li ② -[1, 9, 8, 4] ->>> li = [elem * 2 for elem in li] ③ ->>> li -[2, 18, 16, 8]-
elem*2 and appends that result to the returned list.
-FIXME Here are the list comprehensions in the buildConnectionString function that you declared in Chapter 2:
-
-
["%s=%s" % (k, v) for k, v in params.items()]
-
-First, notice that you're calling the items function of the params dictionary. This function returns a list of tuples of all the data in the dictionary.
+
A list comprehension provides a compact way of mapping a list into another list by applying a function to each of the elements of the list.
->>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
->>> params.keys() ①
-['server', 'uid', 'database', 'pwd']
->>> params.values() ②
-['mpilgrim', 'sa', 'master', 'secret']
->>> params.items() ③
-[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
+>>> a_list = [1, 9, 8, 4]
+>>> [elem * 2 for elem in a_list] ①
+[2, 18, 16, 8]
+>>> a_list ②
+[1, 9, 8, 4]
+>>> a_list = [elem * 2 for elem in a_list] ③
+>>> a_list
+[2, 18, 16, 8]
keys method of a dictionary returns a list of all the keys. The list is not in the order in which the dictionary was defined
- (remember that elements in a dictionary are unordered), but it is a list.
-values method returns a list of all the values. The list is in the same order as the list returned by keys, so params.values()[n] == params[params.keys()[n]] for all values of n.
-items method returns a list of tuples of the form (key, value). The list contains all the data in the dictionary.
-Now let's see what buildConnectionString does. It takes a list, params., and maps it to a new list by applying string formatting to each element. The new list will have the same number of elements
-as items()params., but each element in the new list will be a string that contains both a key and its associated value from the params dictionary.
-
-items()
->>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
->>> params.items()
-[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
->>> [k for k, v in params.items()] ①
-['server', 'uid', 'database', 'pwd']
->>> [v for k, v in params.items()] ②
-['mpilgrim', 'sa', 'master', 'secret']
->>> ["%s=%s" % (k, v) for k, v in params.items()] ③
-['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
-params.items() list. This is another use of multi-variable assignment. The first element of params.items() is ('server', 'mpilgrim'), so in the first iteration of the list comprehension, k will get 'server' and v will get 'mpilgrim'. In this case, you're ignoring the value of v and only including the value of k in the returned list, so this list comprehension ends up being equivalent to params.keys().
-params.values().
-elem * 2 and appends that result to the returned list.
+FIXME +
+>>> glob.glob('*.xml')
+['feed-broken.xml', 'feed-ns0.xml', 'feed.xml']
+>>> [os.path.abspath(filename) for filename in glob.glob('*.xml')]
+['c:\\Users\\pilgrim\\diveintopython3\\examples\\feed-broken.xml',
+ 'c:\\Users\\pilgrim\\diveintopython3\\examples\\feed-ns0.xml',
+ 'c:\\Users\\pilgrim\\diveintopython3\\examples\\feed.xml']
+
+
>>> print("\n".join(["{0:>8} {1}".format(humansize.approximate_size(os.stat(f).st_size, False), os.path.abspath(f)) for f in glob.glob('*.py')]))
2.5 KB c:\Users\pilgrim\diveintopython3\examples\alphametics.py