diff --git a/dip2 b/dip2 index dee7d9a..f18bbf2 100644 --- a/dip2 +++ b/dip2 @@ -743,14 +743,14 @@ In fact, every Python function returns a value; if the function ever executes a
So Python is both dynamically typed (because it doesn't use explicit datatype declarations) and strongly typed (because once a variable has a datatype, it actually matters).
You can document a Python function by giving it a doc string.
-
buildConnectionString Function's doc string+You can document a Python function by giving it a
docstring. +Example 2.2. Defining the
buildConnectionStringFunction'sdocstringdef buildConnectionString(params): """Build a connection string from a dictionary of parameters. Returns string."""Triple quotes signify a multi-line string. Everything between the start and end quotes is part of a single string, including carriage returns and other quote characters. You can use them anywhere, but you'll see them most often used when defining - a
doc string. + adocstring.
Everything between the triple quotes is the function's doc string, which documents what the function does. A doc string, if it exists, must be the first thing defined in a function (that is, the first thing after the colon). You don't technically
-need to give your function a doc string, but you always should. I know you've heard this in every programming class you've ever taken, but Python gives you an added incentive: the doc string is available at runtime as an attribute of the function.
Many Python IDEs use the doc string to provide context-sensitive documentation, so that when you type a function name, its doc string appears as a tooltip. This can be incredibly helpful, but it's only as good as the doc strings you write.
+ | Many Python IDEs use the docstring to provide context-sensitive documentation, so that when you type a function name, its docstring appears as a tooltip. This can be incredibly helpful, but it's only as good as the docstrings you write.
|
||
doc string conventions.
-doc string.
-doc strings.
-In case you missed it, I just said that Python functions have attributes, and that those attributes are available at runtime.
A function, like everything else in Python, is an object.
Open your favorite Python IDE and follow along: -
buildConnectionString Function's doc string>>> import odbchelper+
Example 2.3. Accessing the
buildConnectionStringFunction'sdocstring>>> import odbchelper>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"} >>> print odbchelper.buildConnectionString(params)
server=mpilgrim;uid=sa;database=master;pwd=secret @@ -862,7 +857,7 @@ Returns string.
Everything in Python is an object, and almost everything has attributes and methods. All functions have a built-in attribute __doc__, which returns the doc string defined in the function's source code. The sys module is an object which has (among other things) an attribute called path. And so forth.
+
Everything in Python is an object, and almost everything has attributes and methods. All functions have a built-in attribute __doc__, which returns the docstring defined in the function's source code. The sys module is an object which has (among other things) an attribute called path. And so forth.
Still, this begs the question. What is an object? Different programming languages define “object” in different ways. In some, it means that all objects must have attributes and methods; in others, it means that all objects are subclassable. In Python, the definition is looser; some objects have neither attributes nor methods (more on this in Chapter 3), and not all objects are subclassable (more on this in Chapter 5). But everything is an object in the sense that it can be assigned to a variable or passed as an argument to a function (more in this in Chapter 4).
This is so important that I'm going to repeat it in case you missed it the first few times: everything in Python is an object. Strings are objects. Lists are objects. Functions are objects. Even modules are objects. @@ -882,7 +877,7 @@ def buildConnectionString(params): Returns string.""" return ";".join(["%s=%s" % (k, v) for k, v in params.items()])
Code blocks are defined by their indentation. By "code block", I mean functions, if statements, for loops, while loops, and so forth. Indenting starts a block and unindenting ends it. There are no explicit braces, brackets, or keywords.
-This means that whitespace is significant, and must be consistent. In this example, the function code (including the doc string) is indented four spaces. It doesn't need to be four spaces, it just needs to be consistent. The first line that is not
+This means that whitespace is significant, and must be consistent. In this example, the function code (including the docstring) is indented four spaces. It doesn't need to be four spaces, it just needs to be consistent. The first line that is not
indented is outside the function.
Example 2.6, “if Statements” shows an example of code indentation with if statements.
if Statements@@ -2044,9 +2039,9 @@ if __name__ == "__main__":
doc strings, local variables, and proper indentation
+docstrings, local variables, and proper indentation
apihelper.pyIf you have not already done so, you can download this and other examples used in this book.
def info(object, spacing=10, collapse=1):![]()
![]()
- """Print methods and doc strings. + """Print methods and docstrings. Takes module, class, list, dictionary, or string.""" methodList = [method for method in dir(object) if callable(getattr(object, method))] @@ -2089,7 +2084,7 @@ if __name__ == "__main__":
-
The infofunction has a multi-linedoc stringthat succinctly describes the function's purpose. Note that no return value is mentioned; this function will be used solely +The @@ -2103,7 +2098,7 @@ if __name__ == "__main__":infofunction has a multi-linedocstringthat succinctly describes the function's purpose. Note that no return value is mentioned; this function will be used solely for its effects, rather than its value.![]()
The if __name__trick allows this program do something useful when run by itself, without interfering with its use as a module for other programs. - In this case, the program simply prints out thedoc stringof theinfofunction. + In this case, the program simply prints out thedocstringof theinfofunction.@@ -2114,7 +2109,7 @@ if __name__ == "__main__": -info function is designed to be used by you, the programmer, while working in the Python IDE. It takes any object that has functions or methods (like a module, which has functions, or a list, which has methods) and -prints out the functions and their
doc strings. +prints out the functions and theirdocstrings.Example 4.2. Sample Usage of
apihelper.py>>> from apihelper import info >>> li = [] >>> info(li) @@ -2126,7 +2121,7 @@ insert L.insert(index, object) -- insert object before index pop L.pop([index]) -> item -- remove and return item at index (default last) remove L.remove(value) -- remove first occurrence of value reverse L.reverse() -- reverse *IN PLACE* -sort L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1By default the output is formatted to be easy to read. Multi-line
doc strings are collapsed into a single long line, but this option can be changed by specifying0for thecollapseargument. If the function names are longer than 10 characters, you can specify a larger value for thespacingargument to make the output easier to read. +sort L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1By default the output is formatted to be easy to read. Multi-line
docstrings are collapsed into a single long line, but this option can be changed by specifying0for thecollapseargument. If the function names are longer than 10 characters, you can specify a larger value for thespacingargument to make the output easier to read.Example 4.3. Advanced Usage of
apihelper.py>>> import odbchelper >>> info(odbchelper) buildConnectionString Build a connection string from a dictionary Returns string. @@ -2307,7 +2302,7 @@ True@@ -2358,7 +2353,7 @@ True - ![]()
This is where it really gets interesting. odbchelperis a module, soreturns a list of all kinds of stuff defined in the module, including built-in attributes, likedir(odbchelper)__name__,__doc__, and whatever other attributes and methods you define. In this case,odbchelperhas only one user-defined method, thebuildConnectionStringfunction described in Chapter 2. +This is where it really gets interesting. odbchelperis a module, soreturns a list of all kinds of stuff defined in the module, including built-in attributes, likedir(odbchelper)__name__,__doc__, and whatever other attributes and methods you define. In this case,odbchelperhas only one user-defined method, thebuildConnectionStringfunction described in Chapter 2.@@ -2790,7 +2785,7 @@ a test - ![]()
Any callable object may have a doc string. By using thecallablefunction on each of an object's attributes, you can determine which attributes you care about (methods, functions, classes) +Any callable object may have a docstring. By using thecallablefunction on each of an object's attributes, you can determine which attributes you care about (methods, functions, classes) and which you want to ignore (constants and so on) without knowing anything about the object ahead of time.- ![]()
This is a multiline string, defined by escape characters instead of triple quotes. \nis a carriage return, and\tis a tab character. +This is a multiline string, defined by escape characters instead of triple quotes. \nis a carriage return, and\tis a tab character.@@ -2802,7 +2797,7 @@ a test @@ -2836,7 +2831,7 @@ a test square brackets. - ![]()
You can normalize whitespace by splitting a string with splitand then rejoining it withjoin, using a single space as a delimiter. This is what theinfofunction does to collapse multi-linedoc strings into a single line. +You can normalize whitespace by splitting a string with splitand then rejoining it withjoin, using a single space as a delimiter. This is what theinfofunction does to collapse multi-linedocstrings into a single line.Now, let's take it from the end and work backwards. The
for method in methodListshows that this is a list comprehension. As you know,
methodListis a list of all the methods you care about inobject. So you're looping through that list withmethod. -Example 4.22. Getting a
doc stringDynamically>>> import odbchelper +Example 4.22. Getting a
docstringDynamically>>> import odbchelper >>> object = odbchelper>>> method = 'buildConnectionString'
>>> getattr(object, method)
@@ -2867,12 +2862,12 @@ for method in methodList
- ![]()
Now, printing the actual doc stringof the method is easy. +Now, printing the actual docstringof the method is easy.The next piece of the puzzle is the use of
straround thedoc string. As you may recall,stris a built-in function that coerces data into a string. But adoc stringis always a string, so why bother with thestrfunction? The answer is that not every function has adoc string, and if it doesn't, its__doc__attribute isNone. -Example 4.23. Why Use
stron adoc string?>>> >>> def foo(): print 2 +The next piece of the puzzle is the use of
straround thedocstring. As you may recall,stris a built-in function that coerces data into a string. But adocstringis always a string, so why bother with thestrfunction? The answer is that not every function has adocstring, and if it doesn't, its__doc__attribute isNone. +Example 4.23. Why Use
stron adocstring?>>> >>> def foo(): print 2 >>> >>> foo() 2 >>> >>> foo.__doc__@@ -2885,7 +2880,7 @@ True
- ![]()
You can easily define a function that has no doc string, so its__doc__attribute isNone. Confusingly, if you evaluate the__doc__attribute directly, the Python IDE prints nothing at all, which makes sense if you think about it, but is still unhelpful. +You can easily define a function that has no docstring, so its__doc__attribute isNone. Confusingly, if you evaluate the__doc__attribute directly, the Python IDE prints nothing at all, which makes sense if you think about it, but is still unhelpful.@@ -2921,7 +2916,7 @@ True - ![]()
ljustpads the string with spaces to the given length. This is what theinfofunction uses to make two columns of output and line up all thedoc strings in the second column. +ljustpads the string with spaces to the given length. This is what theinfofunction uses to make two columns of output and line up all thedocstrings in the second column.@@ -2931,7 +2926,7 @@ True -You're almost finished. Given the padded method name from the
ljustmethod and the (possibly collapsed)doc stringfrom the call toprocessFunc, you concatenate the two and get a single string. Since you're mappingmethodList, you end up with a list of strings. Using thejoinmethod of the string"\n", you join this list into a single string, with each element of the list on a separate line, and print the result. +You're almost finished. Given the padded method name from the
ljustmethod and the (possibly collapsed)docstringfrom the call toprocessFunc, you concatenate the two and get a single string. Since you're mappingmethodList, you end up with a list of strings. Using thejoinmethod of the string"\n", you join this list into a single string, with each element of the list on a separate line, and print the result.Example 4.25. Printing a List
>>> li = ['a', 'b', 'c'] >>> print "\n".join(li)a @@ -2954,7 +2949,7 @@ c
The
apihelper.pyprogram and its output should now make perfect sense.def info(object, spacing=10, collapse=1): - """Print methods and doc strings. + """Print methods and docstrings. Takes module, class, list, dictionary, or string.""" methodList = [method for method in dir(object) if callable(getattr(object, method))] @@ -2998,7 +2993,7 @@ sort L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1,Chapter 5. Objects and Object-Orientation
This chapter, and pretty much every chapter after this, deals with object-oriented Python programming.
5.1. Diving In
-Here is a complete, working Python program. Read the
doc strings of the module, the classes, and the functions to get an overview of what this program does and how it works. As usual, don't +Here is a complete, working Python program. Read the
docstrings of the module, the classes, and the functions to get an overview of what this program does and how it works. As usual, don't worry about the stuff you don't understand; that's what the rest of the chapter is for.Example 5.1.
fileinfo.pyIf you have not already done so, you can download this and other examples used in this book.
@@ -3141,7 +3136,7 @@ comment=http://mp3.com/artists/95/vxp5
Here is the basic
from module importsyntax:from UserDict import UserDict -This is similar to the
import modulesyntax that you know and love, but with an important difference: the attributes and methods of the imported moduletypesare imported directly into the local namespace, so they are available directly, without qualification by module name. You +This is similar to the
import modulesyntax that you know and love, but with an important difference: the attributes and methods of the imported moduletypesare imported directly into the local namespace, so they are available directly, without qualification by module name. You can import individual items or usefrom module import *to import everything.
@@ -3300,7 +3295,7 @@ class FileInfo(UserDict): - ![]()
Classes can (and should) have doc strings too, just like modules and functions. +Classes can (and should) have docstrings too, just like modules and functions.@@ -3418,7 +3413,7 @@ class FileInfo(UserDict): - ![]()
You can access the instance's doc stringjust as with a function or a module. All instances of a class share the samedoc string. +You can access the instance's docstringjust as with a function or a module. All instances of a class share the samedocstring.@@ -3991,7 +3986,7 @@ call it directly (even from outside the fileinfom- @@ -4025,7 +4020,7 @@ AttributeError: 'MP3FileInfo' instance has no attribute '__parse'In Python, all special methods (like __setitem__) and built-in attributes (like__doc__) follow a standard naming convention: they both start with and end with two underscores. Don't name your own methods and +In Python, all special methods (like __setitem__) and built-in attributes (like__doc__) follow a standard naming convention: they both start with and end with two underscores. Don't name your own methods and attributes this way, because it will only confuse you (and others) later.Before diving into the next chapter, make sure you're comfortable doing all of these things: -
- Importing modules using either
import moduleorfrom module import+- Importing modules using either
import moduleorfrom module import- Defining and instantiating classes
- Defining
__init__methods and other special class methods, and understanding when they are called @@ -6041,7 +6036,7 @@ they solve.Chapter 8. HTML Processing
8.1. Diving in
I often see questions on comp.lang.python like “How can I list all the [headers|images|links] in my HTML document?” “How do I parse/translate/munge the text of my HTML document but leave the tags alone?” “How can I add/remove/quote attributes of all my HTML tags at once?” This chapter will answer all of these questions. -
Here is a complete, working Python program in two parts. The first part,
BaseHTMLProcessor.py, is a generic tool to help you process HTML files by walking through the tags and text blocks. The second part,dialect.py, is an example of how to useBaseHTMLProcessor.pyto translate the text of an HTML document but leave the tags alone. Read thedoc strings and comments to get an overview of what's going on. Most of it will seem like black magic, because it's not obvious how +Here is a complete, working Python program in two parts. The first part,
BaseHTMLProcessor.py, is a generic tool to help you process HTML files by walking through the tags and text blocks. The second part,dialect.py, is an example of how to useBaseHTMLProcessor.pyto translate the text of an HTML document but leave the tags alone. Read thedocstrings and comments to get an overview of what's going on. Most of it will seem like black magic, because it's not obvious how any of these class methods ever get called. Don't worry, all will be revealed in due time.Example 8.1.
BaseHTMLProcessor.pyIf you have not already done so, you can download this and other examples used in this book.
@@ -6712,7 +6707,7 @@ from __future__ import nested_scopesWhat
localsdoes for the local (function) namespace,globalsdoes for the global (module) namespace.globalsis more exciting, though, because a module's namespace is more exciting.[3] Not only does the module's namespace include module-level variables and constants, it includes all the functions and classes defined in the module. Plus, it includes anything that was imported into the module. -Remember the difference between
from module importandimport module? Withimport module, the module itself is imported, but it retains its own namespace, which is why you need to use the module name to access +Remember the difference between
from module importandimport module? Withimport module, the module itself is imported, but it retains its own namespace, which is why you need to use the module name to access any of its functions or attributes:module.function. But withfrom module import, you're actually importing specific functions and attributes from another module into your own namespace, which is why you access them directly without referencing the original module they came from. With theglobalsfunction, you can actually see this happen.Example 8.11. Introducing
@@ -6952,7 +6947,7 @@ at all. It is this last side effect that you can take advantage of.globals- ![]()
Note that the attribute values of the hrefattributes in the<a>tags are not properly quoted. (Also note that you're using triple quotes for something other than adoc string. And directly in the IDE, no less. They're very useful.) +Note that the attribute values of the hrefattributes in the<a>tags are not properly quoted. (Also note that you're using triple quotes for something other than adocstring. And directly in the IDE, no less. They're very useful.)@@ -7138,7 +7133,7 @@ def translate(url, dialectName="chef"): -
Hey, wait a minute, there's an importstatement in this function! That's perfectly legal in Python. You're used to seeingimportstatements at the top of a program, which means that the imported module is available anywhere in the program. But you can +Hey, wait a minute, there's an -importstatement in this function! That's perfectly legal in Python. You're used to seeingimportstatements at the top of a program, which means that the imported module is available anywhere in the program. But you can also import modules within a function, which means that the imported module is only available within the function. If you have a module that is only ever used in one function, this is an easy way to make your code more modular. (When you find that your weekend hack has turned into an 800-line work of art and decide to split it up into a dozen reusable modules, you'll @@ -12093,7 +12088,7 @@ FAILED (failures=10, errors=2)![]()
Running the script runs unittest.main(), which runs each test case, which is to say each method defined in each class withinromantest.py. For each test case, it prints out thedoc stringof the method and whether that test passed or failed. As expected, none of the test cases passed. +Running the script runs unittest.main(), which runs each test case, which is to say each method defined in each class withinromantest.py. For each test case, it prints out thedocstringof the method and whether that test passed or failed. As expected, none of the test cases passed.@@ -13406,7 +13401,7 @@ OK ![]()
- ![]()
Just a note in passing here: this time, I ran the unit test without the -voption, so instead of the fulldoc stringfor each test, you only get a dot for each test that passes. (If a test failed, you'd get anF, and if it had an error, you'd get anE. You'd still get complete tracebacks for each failure and error, so you could track down any problems.) +Just a note in passing here: this time, I ran the unit test without the -voption, so instead of the fulldocstringfor each test, you only get a dot for each test that passes. (If a test failed, you'd get anF, and if it had an error, you'd get anE. You'd still get complete tracebacks for each failure and error, so you could track down any problems.)diff --git a/dip3.css b/dip3.css index 88f7468..9941ef5 100644 --- a/dip3.css +++ b/dip3.css @@ -5,7 +5,7 @@ a:hover{border-bottom:1px solid} a:link{color:#1b67c9} a:visited{color:darkorchid} h1 a,h2 a,h3 a,#nav a{color:inherit !important} -abbr{letter-spacing:0.1em;text-transform:lowercase;font-variant:small-caps} +abbr,acronym{letter-spacing:0.1em;text-transform:lowercase;font-variant:small-caps} h1,h2,h3,p,ul,ol,#nav{margin:1.75em 0} li ol{margin:0} h1,h2,h3{font-size:medium} @@ -25,14 +25,17 @@ th{text-align:left;padding:0 0.5em;vertical-align:baseline;border:1px dotted} th,td{width:45%;vertical-align:top} td{border:1px dotted;padding:0 0.5em} th:first-child{width:10%;text-align:center} -span,.note p:first-child,tr + tr th:first-child{font-family:'Arial Unicode MS',sans-serif;font-style:normal} -table.simple th{font-family:inherit !important} -.note p:first-child{float:left;font-size:xx-large;line-height:0.875em;margin:0 0.22em 0 0} +span,tr + tr th:first-child{font-family:'Arial Unicode MS',sans-serif;font-style:normal} .q span{font-size:large} +.note{margin-left:4.94em} +.note span{display:block;float:left;font-size:xx-large;line-height:0.875em;margin:0 0.22em 0 -1.22em} +table.simple th{font-family:inherit !important} body{counter-reset:h1} h1:before{counter-increment:h1;content:counter(h1) ". "} h1{counter-reset:h2} h2:before{counter-increment:h2;content:counter(h1) "." counter(h2) ". "} h2{counter-reset:h3} h3:before{counter-increment:h3;content:counter(h1) "." counter(h2) "." counter(h3) ". "} -tr.hover,li.hover{background:#eee;color:inherit;cursor:default} \ No newline at end of file +tr.hover,li.hover{background:#eee;color:inherit;cursor:default} +.fr{width:auto;margin-top:4.308em;border:1px dotted} +.fr h4{margin-top:-1.2em;margin-left:-1em;width:8.5em;border:1px dotted;padding: 3px 3px 3px 13px;background:#fff;color:inherit;position:relative} \ No newline at end of file diff --git a/porting-code-to-python-3-with-2to3.html b/porting-code-to-python-3-with-2to3.html index 3fff815..583d260 100644 --- a/porting-code-to-python-3-with-2to3.html +++ b/porting-code-to-python-3-with-2to3.html @@ -567,8 +567,7 @@ for an_iterator in a_sequence_of_iterators: reduce(a, b, c) -☞ -
The version of
2to3that shipped with Python 3.0 would not fix thereduce()function automatically. The fix first appeared in the2to3script that shipped with Python 3.1. +☞The version of
2to3that shipped with Python 3.0 would not fix thereduce()function automatically. The fix first appeared in the2to3script that shipped with Python 3.1.
apply()global functionPython 2 had a global function called
apply(), which took a function f and a list[a, b, c]and returnedf(a, b, c). In Python 3, theapply()function no longer exists. Instead, there is a new function calling syntax that allows you to pass a list and have Python apply the list as the function's arguments. @@ -646,8 +645,7 @@ reduce(a, b, c)exec(compile(open("a_filename").read(), "a_filename", "exec"))-☞ -
The version of
2to3that shipped with Python 3.0 would not fix theexecfilestatement automatically. The fix first appeared in the2to3script that shipped with Python 3.1. +☞The version of
2to3that shipped with Python 3.0 would not fix theexecfilestatement automatically. The fix first appeared in the2to3script that shipped with Python 3.1.
reprliterals (backticks)In Python 2, there was a special syntax of wrapping any object in backticks (like
`x`) to get a representation of the object. In Python 3, this capability still exists, but you can no longer use backticks to get it. Instead, use the globalrepr()function. @@ -714,8 +712,7 @@ except:Similarly, if you use a fallback to catch all exceptions, the syntax is identical. -☞ -
You should never use a fallback to catch all exceptions when importing modules (or most other times). Doing so will catch things like
KeyboardInterrupt(if the user pressed Ctrl-C to interrupt the program) and can make it more difficult to debug errors. +☞You should never use a fallback to catch all exceptions when importing modules (or most other times). Doing so will catch things like
KeyboardInterrupt(if the user pressed Ctrl-C to interrupt the program) and can make it more difficult to debug errors.
raisestatementThe syntax for raising your own exceptions has changed slightly between Python 2 and Python 3. @@ -1067,8 +1064,7 @@ except:
isinstance(x, (int, float))-☞ -
The version of
2to3that shipped with Python 3.0 would not fix these cases ofisinstance()automatically. The fix first appeared in the2to3script that shipped with Python 3.1. +☞The version of
2to3that shipped with Python 3.0 would not fix these cases ofisinstance()automatically. The fix first appeared in the2to3script that shipped with Python 3.1.
basestringdatatypePython 2 had two string types: Unicode and non-Unicode. But there was also another type,
basestring. It was an abstract type, a superclass for both thestrandunicodetypes. It couldn't be called or instantiated directly, but you could pass it to the globalisinstance()function to check whether an object was either a Unicode or non-Unicode string. In Python 3, there is only one string type, sobasestringhas no reason to exist. @@ -1187,8 +1183,7 @@ except:
set()literals (explicit)In Python 2, the only way to define a literal set in your code was to call
set(a_sequence). This still works in Python 3, but a clearer way of doing it is to use the new set literal notation: curly braces. (Dictionaries are also defined with curly braces, which makes sense once you think about it, because dictionaries are just sets of key-value pairs.)-☞ -
The
2to3script will not fixset()literals by default. To enable this fix, specify -f set_literal on the command line when you call2to3. +☞The
2to3script will not fixset()literals by default. To enable this fix, specify -f set_literal on the command line when you call2to3.@@ -1210,8 +1205,7 @@ except:
buffer()global function (explicit)Python objects implemented in C can export a “buffer interface,” which is a block of memory that is directly readable and writeable without copying. (That is exactly as powerful and scary as it sounds.) In Python 3,
buffer()has been renamed tomemoryview(). (It's a little more complicated than that, but you can almost certainly ignore the differences.)-☞ -
The
2to3script will not fix thebuffer()function by default. To enable this fix, specify -f buffer on the command line when you call2to3. +☞The
2to3script will not fix thebuffer()function by default. To enable this fix, specify -f buffer on the command line when you call2to3.@@ -1227,8 +1221,7 @@ except:
Whitespace around commas (explicit)
Despite being draconian about whitespace for indenting and outdenting, Python is actually quite liberal about whitespace in other areas. Within lists, tuples, sets, and dictionaries, whitespace can appear before and after commas with no ill effects. However, the Python style guide states that commas should be preceded by zero spaces and followed by one. Although this is purely an aesthetic issue (the code works either way, in both Python 2 and Python 3), the
2to3script can optionally fix this for you.-☞ -
The
2to3script will not fix whitespace around commas by default. To enable this fix, specify -f wscomma on the command line when you call2to3. +☞The
2to3script will not fix whitespace around commas by default. To enable this fix, specify -f wscomma on the command line when you call2to3.@@ -1247,8 +1240,7 @@ except:
Common idioms (explicit)
There were a number of common idioms built up in the Python community. Some, like the
while 1:loop, date back to Python 1. (Python didn't have a true boolean type until version 2.3, so developers used1and0instead.) Modern Python programmers should train their brains to use modern versions of these idioms instead.-☞ -
The
2to3script will not fix common idioms by default. To enable this fix, specify -f idioms on the command line when you call2to3. +☞The
2to3script will not fix common idioms by default. To enable this fix, specify -f idioms on the command line when you call2to3.diff --git a/your-first-python-program.html b/your-first-python-program.html index 72a300c..28e0f16 100644 --- a/your-first-python-program.html +++ b/your-first-python-program.html @@ -12,30 +12,16 @@ body{counter-reset:h1 1}
+Your first Python program
-❝ FIXME ❞
— FIXME +❝ Don’t bury your burden in saintly silence. You have a problem? Great. Rejoice, dive in, and investigate. ❞
— Ven. Henepola GunararatanaDiving in
-You know how other books go on and on about programming fundamentals and finally work up to building a complete, working program? Let's skip all that. -
Here is a complete, working Python program. It probably makes absolutely no sense to you. Don't worry about that, because you're going to dissect it line by line. But read through it first and see what, if anything, you can make of it. -
"""Convert file sizes to human-readable form. - -Available functions: -approximate_size(size, a_kilobyte_is_1024_bytes) - takes a file size and returns a human-readable string - -Examples: ->>> approximate_size(1024) -'1.0 KiB' ->>> approximate_size(1000, False) -'1.0 KB' - -""" - -SUFFIXES = {1000: ('KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'), +You know how other books go on and on about programming fundamentals and finally work up to building something useful? Let's skip all that. Here is a complete, working Python program. It probably makes absolutely no sense to you. Don't worry about that, because you're going to dissect it line by line. But read through it first and see what, if anything, you can make of it. +
SUFFIXES = {1000: ('KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'), 1024: ('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')} def approximate_size(size, a_kilobyte_is_1024_bytes=True): @@ -77,13 +63,11 @@ if __name__ == "__main__":Note that the keyword
defstarts the function declaration, followed by the function name, followed by the arguments in parentheses. Multiple arguments are separated with commas.Also note that the function doesn't define a return datatype. Python functions do not specify the datatype of their return value; they don't even specify whether or not they return a value. (In fact, every Python function returns a value; if the function ever executes a
returnstatement, it will return that value, otherwise it will returnNone, the Python null value.)-☞ -
In some languages, functions (that return a value) start with
function, and subroutines (that do not return a value) start withsub. There are no subroutines in Python. Everything is a function, all functions return a value (even if it'sNone), and all functions start withdef. +☞In some languages, functions (that return a value) start with
function, and subroutines (that do not return a value) start withsub. There are no subroutines in Python. Everything is a function, all functions return a value (even if it'sNone), and all functions start withdef.The
approximate_sizefunction takes the two arguments — size and a_kilobyte_is_1024_bytes — but neither argument specifies a datatype. (As you might guess from the=Truesyntax, the second argument is a boolean. You'll learn what that syntax does in [FIXME xref].) In Python, variables are never explicitly typed. Python figures out what type a variable is and keeps track of it internally.-☞ -
In Java, C++, and other statically-typed languages, you must specify the datatype of the function return value and each function argument. In Python, you never explicitly specify the datatype of anything. Based on what value you assign, Python keeps track of the datatype internally. +
☞In Java, C++, and other statically-typed languages, you must specify the datatype of the function return value and each function argument. In Python, you never explicitly specify the datatype of anything. Based on what value you assign, Python keeps track of the datatype internally.
How Python's Datatypes Compare to Other Programming Languages
An erudite reader sent me this explanation of how Python compares to other programming languages: @@ -108,10 +92,35 @@ if __name__ == "__main__":
Weakly typed C, Objective-C JavaScript, Perl 5, PHP Strongly typed Pascal, Java Python, Ruby Documenting functions
+You can document a Python function by giving it a
docstring. In this program, theapproximate_sizefunction has adocstring: ++def approximate_size(size, a_kilobyte_is_1024_bytes=True): + """Convert a file size to human-readable form. + Keyword arguments: + size -- file size in bytes + a_kilobyte_is_1024_bytes -- if True (default), use multiples of 1024 + if False, use multiples of 1000 + Returns: string - + """Triple quotes signify a multi-line string. Everything between the start and end quotes is part of a single string, including carriage returns and other quote characters. You can use them anywhere, but you'll see them most often used when defining a
docstring. +++☞Triple quotes are also an easy way to define a string with both single and double quotes, like
qq/.../in Perl 5. +Everything between the triple quotes is the function's
docstring, which documents what the function does. Adocstring, if it exists, must be the first thing defined in a function (that is, on the next line after the function declaration). You don't technically need to give your function adocstring, but you always should. I know you've heard this in every programming class you've ever taken, but Python gives you an added incentive: thedocstringis available at runtime as an attribute of the function. +++☞Many Python IDEs use the
docstringto provide context-sensitive documentation, so that when you type a function name, itsdocstringappears as a tooltip. This can be incredibly helpful, but it's only as good as thedocstrings you write. ++Further reading
+ +© 2001-4, 2009 ℳark Pilgrim, CC-BY-3.0