From 86aecc360f8fd635a91c5b7ffe63b1b9a3e17a31 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Mon, 20 May 2013 08:12:32 +0300 Subject: [PATCH] #14097: improve the "introduction" page of the tutorial. --- Doc/tutorial/introduction.rst | 609 +++++++++++++++------------------- Misc/NEWS | 2 + 2 files changed, 263 insertions(+), 348 deletions(-) diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index 4b7f60d7321..1cd7e0a7166 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -5,7 +5,7 @@ An Informal Introduction to Python ********************************** In the following examples, input and output are distinguished by the presence or -absence of prompts (``>>>`` and ``...``): to repeat the example, you must type +absence of prompts (:term:`>>>` and :term:`...`): to repeat the example, you must type everything after the prompt, when the prompt appears; lines that do not begin with a prompt are output from the interpreter. Note that a secondary prompt on a line by itself in an example means you must type a blank line; this is used to @@ -22,9 +22,9 @@ be omitted when typing in examples. Some examples:: # this is the first comment - SPAM = 1 # and this is the second comment - # ... and now a third! - STRING = "# This is not a comment." + spam = 1 # and this is the second comment + # ... and now a third! + text = "# This is not a comment because it's inside quotes." .. _tut-calculator: @@ -44,55 +44,53 @@ Numbers The interpreter acts as a simple calculator: you can type an expression at it and it will write the value. Expression syntax is straightforward: the operators ``+``, ``-``, ``*`` and ``/`` work just like in most other languages -(for example, Pascal or C); parentheses can be used for grouping. For example:: +(for example, Pascal or C); parentheses (``()``) can be used for grouping. +For example:: - >>> 2+2 + >>> 2 + 2 4 - >>> # This is a comment - ... 2+2 - 4 - >>> 2+2 # and a comment on the same line as code - 4 - >>> (50-5*6)/4 + >>> 50 - 5*6 + 20 + >>> (50 - 5*6) / 4 5.0 - >>> 8/5 # Fractions aren't lost when dividing integers + >>> 8 / 5 # division always returns a floating point number 1.6 -Note: You might not see exactly the same result; floating point results can -differ from one machine to another. We will say more later about controlling -the appearance of floating point output. See also :ref:`tut-fp-issues` for a -full discussion of some of the subtleties of floating point numbers and their -representations. +The integer numbers (e.g. ``2``, ``4``, ``20``) have type :class:`int`, +the ones with a fractional part (e.g. ``5.0``, ``1.6``) have type +:class:`float`. We will see more about numberic types later in the tutorial. -To do integer division and get an integer result, -discarding any fractional result, there is another operator, ``//``:: +Division (``/``) always returns a float. To do :term:`floor division` and +get an integer result (discarding any fractional result) you can use the ``//`` +operator; to calculate the remainder you can use ``%``:: - >>> # Integer division returns the floor: - ... 7//3 + >>> 17 / 3 # classic division returns a float + 5.666666666666667 + >>> + >>> 17 // 3 # floor division discards the fractional part + 5 + >>> 17 % 3 # the % operator returns the remainder of the division 2 - >>> 7//-3 - -3 + >>> 5 * 3 + 2 # result * divisor + remainder + 17 -The equal sign (``'='``) is used to assign a value to a variable. Afterwards, no +With Python is possible to use the ``**`` operator to calculate powers [#]_:: + + >>> 5 ** 2 # 5 squared + 25 + >>> 2 ** 7 # 2 to the power of 7 + 128 + +The equal sign (``=``) is used to assign a value to a variable. Afterwards, no result is displayed before the next interactive prompt:: >>> width = 20 - >>> height = 5*9 + >>> height = 5 * 9 >>> width * height 900 -A value can be assigned to several variables simultaneously:: - - >>> x = y = z = 0 # Zero x, y and z - >>> x - 0 - >>> y - 0 - >>> z - 0 - -Variables must be "defined" (assigned a value) before they can be used, or an -error will occur:: +If a variable is not "defined" (assigned a value), trying to use it will +give you an error:: >>> n # try to access an undefined variable Traceback (most recent call last): @@ -107,49 +105,6 @@ convert the integer operand to floating point:: >>> 7.0 / 2 3.5 -Complex numbers are also supported; imaginary numbers are written with a suffix -of ``j`` or ``J``. Complex numbers with a nonzero real component are written as -``(real+imagj)``, or can be created with the ``complex(real, imag)`` function. -:: - - >>> 1j * 1J - (-1+0j) - >>> 1j * complex(0, 1) - (-1+0j) - >>> 3+1j*3 - (3+3j) - >>> (3+1j)*3 - (9+3j) - >>> (1+2j)/(1+1j) - (1.5+0.5j) - -Complex numbers are always represented as two floating point numbers, the real -and imaginary part. To extract these parts from a complex number *z*, use -``z.real`` and ``z.imag``. :: - - >>> a=1.5+0.5j - >>> a.real - 1.5 - >>> a.imag - 0.5 - -The conversion functions to floating point and integer (:func:`float`, -:func:`int`) don't work for complex numbers --- there is not one correct way to -convert a complex number to a real number. Use ``abs(z)`` to get its magnitude -(as a float) or ``z.real`` to get its real part:: - - >>> a=3.0+4.0j - >>> float(a) - Traceback (most recent call last): - File "", line 1, in ? - TypeError: can't convert complex to float; use abs(z) - >>> a.real - 3.0 - >>> a.imag - 4.0 - >>> abs(a) # sqrt(a.real**2 + a.imag**2) - 5.0 - In interactive mode, the last printed expression is assigned to the variable ``_``. This means that when you are using Python as a desk calculator, it is somewhat easier to continue calculations, for example:: @@ -167,20 +122,28 @@ This variable should be treated as read-only by the user. Don't explicitly assign a value to it --- you would create an independent local variable with the same name masking the built-in variable with its magic behavior. +In addition to :class:`int` and :class:`float`, Python supports other types of +numbers, such as :class:`~decimal.Decimal` and :class:`~fractions.Fraction`. +Python also has built-in support for :ref:`complex numbers `, +and uses the ``j`` or ``J`` suffix to indicate the imaginary part +(e.g. ``3+5j``). + .. _tut-strings: Strings ------- -Besides numbers, Python can also manipulate strings, which can be expressed in -several ways. They can be enclosed in single quotes or double quotes:: +Besides numbers, Python can also manipulate strings, which can be expressed +in several ways. They can be enclosed in single quotes (``'...'``) or +double quotes (``"..."``) with the same result [#]_. ``\`` can be used +to escape quotes:: - >>> 'spam eggs' + >>> 'spam eggs' # single quotes 'spam eggs' - >>> 'doesn\'t' + >>> 'doesn\'t' # use \' to escape the single quote... "doesn't" - >>> "doesn't" + >>> "doesn't" # ...or use double quotes instead "doesn't" >>> '"Yes," he said.' '"Yes," he said.' @@ -189,38 +152,40 @@ several ways. They can be enclosed in single quotes or double quotes:: >>> '"Isn\'t," she said.' '"Isn\'t," she said.' -The interpreter prints the result of string operations in the same way as they -are typed for input: inside quotes, and with quotes and other funny characters -escaped by backslashes, to show the precise value. The string is enclosed in -double quotes if the string contains a single quote and no double quotes, else -it's enclosed in single quotes. The :func:`print` function produces a more -readable output for such input strings. +In the interactive interpreter, the output string is enclosed in quotes and +special characters are escaped with backslashes. While this might sometimes +look different from the input (the enclosing quotes could change), the two +strings are equivalent. The string is enclosed in double quotes if +the string contains a single quote and no double quotes, otherwise it is +enclosed in single quotes. The :func:`print` function produces a more +readable output, by omitting the enclosing quotes and by printing escaped +and special characters:: -String literals can span multiple lines in several ways. Continuation lines can -be used, with a backslash as the last character on the line indicating that the -next line is a logical continuation of the line:: + >>> '"Isn\'t," she said.' + '"Isn\'t," she said.' + >>> print('"Isn\'t," she said.') + "Isn't," she said. + >>> s = 'First line.\nSecond line.' # \n means newline + >>> s # without print(), \n is included in the output + 'First line.\nSecond line.' + >>> print(s) # with print(), \n produces a new line + First line. + Second line. - hello = "This is a rather long string containing\n\ - several lines of text just as you would do in C.\n\ - Note that whitespace at the beginning of the line is\ - significant." +If you don't want characters prefaced by ``\`` to be interpreted as +special characters, you can use *raw strings* by adding an ``r`` before +the first quote:: - print(hello) + >>> print('C:\some\name') # here \n means newline! + C:\some + ame + >>> print(r'C:\some\name') # note the r before the quote + C:\some\name -Note that newlines still need to be embedded in the string using ``\n`` -- the -newline following the trailing backslash is discarded. This example would print -the following: - -.. code-block:: text - - This is a rather long string containing - several lines of text just as you would do in C. - Note that whitespace at the beginning of the line is significant. - -Or, strings can be surrounded in a pair of matching triple-quotes: ``"""`` or -``'''``. End of lines do not need to be escaped when using triple-quotes, but -they will be included in the string. So the following uses one escape to -avoid an unwanted initial blank line. :: +String literals can span multiple lines. One way is using triple-quotes: +``"""..."""`` or ``'''...'''``. End of lines are automatically +included in the string, but it's possible to prevent this by adding a ``\`` at +the end of the line. The following example:: print("""\ Usage: thingy [OPTIONS] @@ -228,7 +193,7 @@ avoid an unwanted initial blank line. :: -H hostname Hostname to connect to """) -produces the following output: +produces the following output (note that the initial newline is not included): .. code-block:: text @@ -236,143 +201,100 @@ produces the following output: -h Display this usage message -H hostname Hostname to connect to -If we make the string literal a "raw" string, ``\n`` sequences are not converted -to newlines, but the backslash at the end of the line, and the newline character -in the source, are both included in the string as data. Thus, the example:: - - hello = r"This is a rather long string containing\n\ - several lines of text much as you would do in C." - - print(hello) - -would print: - -.. code-block:: text - - This is a rather long string containing\n\ - several lines of text much as you would do in C. - Strings can be concatenated (glued together) with the ``+`` operator, and repeated with ``*``:: - >>> word = 'Help' + 'A' - >>> word - 'HelpA' - >>> '<' + word*5 + '>' - '' + >>> # 3 times 'un', followed by 'ium' + >>> 3 * 'un' + 'ium' + 'unununium' -Two string literals next to each other are automatically concatenated; the first -line above could also have been written ``word = 'Help' 'A'``; this only works -with two literals, not with arbitrary string expressions:: +Two or more *string literals* (i.e. the ones enclosed between quotes) next +to each other are automatically concatenated. :: - >>> 'str' 'ing' # <- This is ok - 'string' - >>> 'str'.strip() + 'ing' # <- This is ok - 'string' - >>> 'str'.strip() 'ing' # <- This is invalid - File "", line 1, in ? - 'str'.strip() 'ing' - ^ + >>> 'Py' 'thon' + 'Python' + +This only works with two literals though, not with variables or expressions:: + + >>> prefix = 'Py' + >>> prefix 'thon' # can't concatenate a variable and a string literal + ... + SyntaxError: invalid syntax + >>> ('un' * 3) 'ium' + ... SyntaxError: invalid syntax -Strings can be subscripted (indexed); like in C, the first character of a string -has subscript (index) 0. There is no separate character type; a character is -simply a string of size one. As in the Icon programming language, substrings -can be specified with the *slice notation*: two indices separated by a colon. -:: +If you want to concatenate variables or a variable and a literal, use ``+``:: - >>> word[4] - 'A' - >>> word[0:2] - 'He' - >>> word[2:4] - 'lp' + >>> prefix + 'thon' + 'Python' + +This feature is particularly useful when you want to break long strings:: + + >>> text = ('Put several strings within parentheses ' + 'to have them joined together.') + >>> text + 'Put several strings within parentheses to have them joined together.' + +Strings can be *indexed* (subscripted), with the first character having index 0. +There is no separate character type; a character is simply a string of size +one:: + + >>> word = 'Python' + >>> word[0] # character in position 0 + 'P' + >>> word[5] # character in position 5 + 'n' + +Indices may also be negative numbers, to start counting from the right:: + + >>> word[-1] # last character + 'n' + >>> word[-2] # second-last character + 'o' + >>> word[-6] + 'P' + +Note that since -0 is the same as 0, negative indices start from -1. + +In addition to indexing, *slicing* is also supported. While indexing is used +to obtain individual characters, *slicing* allows you to obtain substring:: + + >>> word[0:2] # characters from position 0 (included) to 2 (excluded) + 'Py' + >>> word[2:5] # characters from position 2 (included) to 4 (excluded) + 'tho' + +Note how the start is always included, and the end always excluded. This +makes sure that ``s[:i] + s[i:]`` is always equal to ``s``:: + + >>> word[:2] + word[2:] + 'Python' + >>> word[:4] + word[4:] + 'Python' Slice indices have useful defaults; an omitted first index defaults to zero, an omitted second index defaults to the size of the string being sliced. :: - >>> word[:2] # The first two characters - 'He' - >>> word[2:] # Everything except the first two characters - 'lpA' - -Unlike a C string, Python strings cannot be changed. Assigning to an indexed -position in the string results in an error:: - - >>> word[0] = 'x' - Traceback (most recent call last): - File "", line 1, in ? - TypeError: 'str' object does not support item assignment - >>> word[:1] = 'Splat' - Traceback (most recent call last): - File "", line 1, in ? - TypeError: 'str' object does not support slice assignment - -However, creating a new string with the combined content is easy and efficient:: - - >>> 'x' + word[1:] - 'xelpA' - >>> 'Splat' + word[4] - 'SplatA' - -Here's a useful invariant of slice operations: ``s[:i] + s[i:]`` equals ``s``. -:: - - >>> word[:2] + word[2:] - 'HelpA' - >>> word[:3] + word[3:] - 'HelpA' - -Degenerate slice indices are handled gracefully: an index that is too large is -replaced by the string size, an upper bound smaller than the lower bound returns -an empty string. :: - - >>> word[1:100] - 'elpA' - >>> word[10:] - '' - >>> word[2:1] - '' - -Indices may be negative numbers, to start counting from the right. For example:: - - >>> word[-1] # The last character - 'A' - >>> word[-2] # The last-but-one character - 'p' - >>> word[-2:] # The last two characters - 'pA' - >>> word[:-2] # Everything except the last two characters - 'Hel' - -But note that -0 is really the same as 0, so it does not count from the right! -:: - - >>> word[-0] # (since -0 equals 0) - 'H' - -Out-of-range negative slice indices are truncated, but don't try this for -single-element (non-slice) indices:: - - >>> word[-100:] - 'HelpA' - >>> word[-10] # error - Traceback (most recent call last): - File "", line 1, in ? - IndexError: string index out of range + >>> word[:2] # character from the beginning to position 2 (excluded) + 'Py' + >>> word[4:] # characters from position 4 (included) to the end + 'on' + >>> word[-2:] # characters from the second-last (included) to the end + 'on' One way to remember how slices work is to think of the indices as pointing *between* characters, with the left edge of the first character numbered 0. Then the right edge of the last character of a string of *n* characters has index *n*, for example:: - +---+---+---+---+---+ - | H | e | l | p | A | - +---+---+---+---+---+ - 0 1 2 3 4 5 - -5 -4 -3 -2 -1 + +---+---+---+---+---+---+ + | P | y | t | h | o | n | + +---+---+---+---+---+---+ + 0 1 2 3 4 5 6 + -6 -5 -4 -3 -2 -1 -The first row of numbers gives the position of the indices 0...5 in the string; +The first row of numbers gives the position of the indices 0...6 in the string; the second row gives the corresponding negative indices. The slice from *i* to *j* consists of all characters between the edges labeled *i* and *j*, respectively. @@ -381,6 +303,38 @@ For non-negative indices, the length of a slice is the difference of the indices, if both are within bounds. For example, the length of ``word[1:3]`` is 2. +Attempting to use a index that is too large will result in an error:: + + >>> word[42] # the word only has 7 characters + Traceback (most recent call last): + File "", line 1, in + IndexError: string index out of range + +However, out of range slice indexes are handled gracefully when used for +slicing:: + + >>> word[4:42] + 'on' + >>> word[42:] + '' + +Python strings cannot be changed --- they are :term:`immutable`. +Therefore, assigning to an indexed position in the string results in an error:: + + >>> word[0] = 'J' + ... + TypeError: 'str' object does not support item assignment + >>> word[2:] = 'py' + ... + TypeError: 'str' object does not support item assignment + +If you need a different string, you should create a new one:: + + >>> 'J' + word[1:] + 'Jython' + >>> word[:2] + 'py' + 'Pypy' + The built-in function :func:`len` returns the length of a string:: >>> s = 'supercalifragilisticexpialidocious' @@ -407,51 +361,6 @@ The built-in function :func:`len` returns the length of a string:: the left operand of the ``%`` operator are described in more detail here. -.. _tut-unicodestrings: - -About Unicode -------------- - -.. sectionauthor:: Marc-André Lemburg - - -Starting with Python 3.0 all strings support Unicode (see -http://www.unicode.org/). - -Unicode has the advantage of providing one ordinal for every character in every -script used in modern and ancient texts. Previously, there were only 256 -possible ordinals for script characters. Texts were typically bound to a code -page which mapped the ordinals to script characters. This lead to very much -confusion especially with respect to internationalization (usually written as -``i18n`` --- ``'i'`` + 18 characters + ``'n'``) of software. Unicode solves -these problems by defining one code page for all scripts. - -If you want to include special characters in a string, -you can do so by using the Python *Unicode-Escape* encoding. The following -example shows how:: - - >>> 'Hello\u0020World !' - 'Hello World !' - -The escape sequence ``\u0020`` indicates to insert the Unicode character with -the ordinal value 0x0020 (the space character) at the given position. - -Other characters are interpreted by using their respective ordinal values -directly as Unicode ordinals. If you have literal strings in the standard -Latin-1 encoding that is used in many Western countries, you will find it -convenient that the lower 256 characters of Unicode are the same as the 256 -characters of Latin-1. - -Apart from these standard encodings, Python provides a whole set of other ways -of creating Unicode strings on the basis of a known encoding. - -To convert a string into a sequence of bytes using a specific encoding, -string objects provide an :func:`encode` method that takes one argument, the -name of the encoding. Lowercase names for encodings are preferred. :: - - >>> "Äpfel".encode('utf-8') - b'\xc3\x84pfel' - .. _tut-lists: Lists @@ -459,97 +368,89 @@ Lists Python knows a number of *compound* data types, used to group together other values. The most versatile is the *list*, which can be written as a list of -comma-separated values (items) between square brackets. List items need not all -have the same type. :: +comma-separated values (items) between square brackets. Lists might contain +items of different types, but usually the items all have the same type. :: - >>> a = ['spam', 'eggs', 100, 1234] - >>> a - ['spam', 'eggs', 100, 1234] + >>> squares = [1, 2, 4, 9, 16, 25] + >>> squares + [1, 2, 4, 9, 16, 25] -Like string indices, list indices start at 0, and lists can be sliced, -concatenated and so on:: +Like strings (and all other built-in :term:`sequence` type), lists can be +indexed and sliced:: - >>> a[0] - 'spam' - >>> a[3] - 1234 - >>> a[-2] - 100 - >>> a[1:-1] - ['eggs', 100] - >>> a[:2] + ['bacon', 2*2] - ['spam', 'eggs', 'bacon', 4] - >>> 3*a[:3] + ['Boo!'] - ['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boo!'] + >>> squares[0] # indexing returns the item + 1 + >>> squares[-1] + 25 + >>> squares[-3:] # slicing returns a new list + [9, 16, 25] All slice operations return a new list containing the requested elements. This -means that the following slice returns a shallow copy of the list *a*:: +means that the following slice returns a new (shallow) copy of the list:: - >>> a[:] - ['spam', 'eggs', 100, 1234] + >>> squares[:] + [1, 2, 4, 9, 16, 25] -Unlike strings, which are *immutable*, it is possible to change individual -elements of a list:: +Lists also supports operations like concatenation:: - >>> a - ['spam', 'eggs', 100, 1234] - >>> a[2] = a[2] + 23 - >>> a - ['spam', 'eggs', 123, 1234] + >>> squares + [36, 49, 64, 81, 100] + [1, 2, 4, 9, 16, 25, 36, 49, 64, 81, 100] + +Unlike strings, which are :term:`immutable`, lists are a :term:`mutable` +type, i.e. it is possible to change their content:: + + >>> cubes = [1, 8, 27, 65, 125] # something's wrong here + >>> 4 ** 3 # the cube of 4 is 64, not 65! + 64 + >>> cubes[3] = 64 # replace the wrong value + >>> cubes + [1, 8, 27, 64, 125] + +You can also add new items at the end of the list, by using +the :meth:`~list.append` *method* (we will see more about methods later):: + + >>> cubes.append(216) # add the cube of 6 + >>> cubes.append(7 ** 3) # and the cube of 7 + >>> cubes + [1, 8, 27, 64, 125, 216, 343] Assignment to slices is also possible, and this can even change the size of the list or clear it entirely:: - >>> # Replace some items: - ... a[0:2] = [1, 12] - >>> a - [1, 12, 123, 1234] - >>> # Remove some: - ... a[0:2] = [] - >>> a - [123, 1234] - >>> # Insert some: - ... a[1:1] = ['bletch', 'xyzzy'] - >>> a - [123, 'bletch', 'xyzzy', 1234] - >>> # Insert (a copy of) itself at the beginning - >>> a[:0] = a - >>> a - [123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234] - >>> # Clear the list: replace all items with an empty list - >>> a[:] = [] - >>> a + >>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] + >>> letters + ['a', 'b', 'c', 'd', 'e', 'f', 'g'] + >>> # replace some values + >>> letters[2:5] = ['C', 'D', 'E'] + >>> letters + ['a', 'b', 'C', 'D', 'E', 'f', 'g'] + >>> # now remove them + >>> letters[2:5] = [] + >>> letters + ['a', 'b', 'f', 'g'] + >>> # clear the list by replacing all the elements with an empty list + >>> letters[:] = [] + >>> letters [] The built-in function :func:`len` also applies to lists:: - >>> a = ['a', 'b', 'c', 'd'] - >>> len(a) + >>> letters = ['a', 'b', 'c', 'd'] + >>> len(letters) 4 It is possible to nest lists (create lists containing other lists), for example:: - >>> q = [2, 3] - >>> p = [1, q, 4] - >>> len(p) - 3 - >>> p[1] - [2, 3] - >>> p[1][0] - 2 - -You can add something to the end of the list:: - - >>> p[1].append('xtra') - >>> p - [1, [2, 3, 'xtra'], 4] - >>> q - [2, 3, 'xtra'] - -Note that in the last example, ``p[1]`` and ``q`` really refer to the same -object! We'll come back to *object semantics* later. - + >>> a = ['a', 'b', 'c'] + >>> n = [1, 2, 3] + >>> x = [a, n] + >>> x + [['a', 'b', 'c'], [1, 2, 3]] + >>> p[0] + ['a', 'b', 'c'] + >>> p[0][1] + 'b' .. _tut-firststeps: @@ -620,3 +521,15 @@ This example introduces several new features. ... a, b = b, a+b ... 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987, + + +.. rubric:: Footnotes + +.. [#] Since ``**`` has higher precedence than ``-``, ``-3**2`` will be + interpreted as ``-(3**2)`` and thus result in ``-9``. To avoid this + and get ``9``, you can use ``(-3)**2``. + +.. [#] Unlike other languages, special characters such as ``\n`` have the + same meaning with both single (``'...'``) and double (``"..."``) quotes. + The only difference between the two is that within single quotes you don't + need to escape ``"`` (but you have to escape ``\'``) and vice versa. diff --git a/Misc/NEWS b/Misc/NEWS index a9ce97aec44..5d9494781fe 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,8 @@ Tests Documentation ------------- +- Issue #14097: improve the "introduction" page of the tutorial. + - Issue #17977: The documentation for the cadefault argument's default value in urllib.request.urlopen() is fixed to match the code.