diff options
author | Georg Brandl <georg@python.org> | 2010-03-21 19:06:51 (GMT) |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2010-03-21 19:06:51 (GMT) |
commit | 953fe5f7e7b07b52458ce98b061bdf717732e6b6 (patch) | |
tree | 8dc678675e3d527093fc2885471154b755f139b6 /Doc/faq | |
parent | 46d441e0c246021e51d231349f556712ab779479 (diff) | |
download | cpython-953fe5f7e7b07b52458ce98b061bdf717732e6b6.zip cpython-953fe5f7e7b07b52458ce98b061bdf717732e6b6.tar.gz cpython-953fe5f7e7b07b52458ce98b061bdf717732e6b6.tar.bz2 |
Merged revisions 76538,76559,76882-76883,76886,76891-76892,76920,76924-76925,77081,77084,77086,77092 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r76538 | georg.brandl | 2009-11-26 21:48:25 +0100 (Do, 26 Nov 2009) | 1 line
#7400: typo.
........
r76559 | georg.brandl | 2009-11-28 12:11:50 +0100 (Sa, 28 Nov 2009) | 1 line
Fix versions and spacing.
........
r76882 | georg.brandl | 2009-12-19 18:30:28 +0100 (Sa, 19 Dez 2009) | 1 line
#7527: use standard versionadded tags.
........
r76883 | georg.brandl | 2009-12-19 18:34:32 +0100 (Sa, 19 Dez 2009) | 1 line
#7521: remove Py_GetBuildNumber(), which was removed in favor of Py_GetBuildInfo().
........
r76886 | georg.brandl | 2009-12-19 18:43:33 +0100 (Sa, 19 Dez 2009) | 1 line
#7493: review of Design FAQ by Florent Xicluna.
........
r76891 | georg.brandl | 2009-12-19 19:16:31 +0100 (Sa, 19 Dez 2009) | 1 line
#7479: add note about function availability on Unices.
........
r76892 | georg.brandl | 2009-12-19 19:20:18 +0100 (Sa, 19 Dez 2009) | 1 line
#7480: remove tautology.
........
r76920 | georg.brandl | 2009-12-20 15:20:16 +0100 (So, 20 Dez 2009) | 1 line
#7495: backport Programming FAQ review to trunk.
........
r76924 | georg.brandl | 2009-12-20 15:28:05 +0100 (So, 20 Dez 2009) | 1 line
Small indentation fix.
........
r76925 | georg.brandl | 2009-12-20 15:33:20 +0100 (So, 20 Dez 2009) | 1 line
#7381: subprocess documentation and library docstring consistency fixes.
........
r77081 | georg.brandl | 2009-12-28 08:59:05 +0100 (Mo, 28 Dez 2009) | 1 line
#7577: fix signature of PyBuffer_FillInfo().
........
r77084 | georg.brandl | 2009-12-28 09:01:59 +0100 (Mo, 28 Dez 2009) | 1 line
#7586: fix typo.
........
r77086 | georg.brandl | 2009-12-28 09:09:32 +0100 (Mo, 28 Dez 2009) | 1 line
#7381: consistency update, and backport avoiding ``None >= 0`` check from py3k.
........
r77092 | georg.brandl | 2009-12-28 09:48:24 +0100 (Mo, 28 Dez 2009) | 1 line
#7404: remove reference to non-existing example files.
........
Diffstat (limited to 'Doc/faq')
-rw-r--r-- | Doc/faq/design.rst | 146 | ||||
-rw-r--r-- | Doc/faq/programming.rst | 155 |
2 files changed, 146 insertions, 155 deletions
diff --git a/Doc/faq/design.rst b/Doc/faq/design.rst index a2a1b6a..2e2ce2e 100644 --- a/Doc/faq/design.rst +++ b/Doc/faq/design.rst @@ -7,7 +7,7 @@ Why does Python use indentation for grouping of statements? Guido van Rossum believes that using indentation for grouping is extremely elegant and contributes a lot to the clarity of the average Python program. -Most people learn to love this feature after awhile. +Most people learn to love this feature after a while. Since there are no begin/end brackets there cannot be a disagreement between grouping perceived by the parser and the human reader. Occasionally C @@ -48,7 +48,7 @@ Why are floating point calculations so inaccurate? People are often very surprised by results like this:: - >>> 1.2-1.0 + >>> 1.2 - 1.0 0.199999999999999996 and think it is a bug in Python. It's not. This has nothing to do with Python, @@ -85,7 +85,7 @@ of some computation to a float with ``==``. Tiny inaccuracies may mean that ``==`` fails. Instead, you have to check that the difference between the two numbers is less than a certain threshold:: - epsilon = 0.0000000000001 # Tiny allowed error + epsilon = 0.0000000000001 # Tiny allowed error expected_result = 0.4 if expected_result-epsilon <= computation() <= expected_result+epsilon: @@ -131,24 +131,25 @@ still useful in those languages, too. Second, it means that no special syntax is necessary if you want to explicitly reference or call the method from a particular class. In C++, if you want to use a method from a base class which is overridden in a derived class, you have -to use the ``::`` operator -- in Python you can write baseclass.methodname(self, -<argument list>). This is particularly useful for :meth:`__init__` methods, and -in general in cases where a derived class method wants to extend the base class -method of the same name and thus has to call the base class method somehow. +to use the ``::`` operator -- in Python you can write +``baseclass.methodname(self, <argument list>)``. This is particularly useful +for :meth:`__init__` methods, and in general in cases where a derived class +method wants to extend the base class method of the same name and thus has to +call the base class method somehow. Finally, for instance variables it solves a syntactic problem with assignment: since local variables in Python are (by definition!) those variables to which a -value assigned in a function body (and that aren't explicitly declared global), -there has to be some way to tell the interpreter that an assignment was meant to -assign to an instance variable instead of to a local variable, and it should -preferably be syntactic (for efficiency reasons). C++ does this through +value is assigned in a function body (and that aren't explicitly declared +global), there has to be some way to tell the interpreter that an assignment was +meant to assign to an instance variable instead of to a local variable, and it +should preferably be syntactic (for efficiency reasons). C++ does this through declarations, but Python doesn't have declarations and it would be a pity having -to introduce them just for this purpose. Using the explicit "self.var" solves +to introduce them just for this purpose. Using the explicit ``self.var`` solves this nicely. Similarly, for using instance variables, having to write -"self.var" means that references to unqualified names inside a method don't have -to search the instance's directories. To put it another way, local variables -and instance variables live in two different namespaces, and you need to tell -Python which namespace to use. +``self.var`` means that references to unqualified names inside a method don't +have to search the instance's directories. To put it another way, local +variables and instance variables live in two different namespaces, and you need +to tell Python which namespace to use. Why can't I use an assignment in an expression? @@ -234,8 +235,10 @@ code breakage. .. XXX talk about protocols? -Note that for string operations Python has moved from external functions (the -``string`` module) to methods. However, ``len()`` is still a function. +.. note:: + + For string operations, Python has moved from external functions (the + ``string`` module) to methods. However, ``len()`` is still a function. Why is join() a string method instead of a list or tuple method? @@ -298,22 +301,24 @@ A try/except block is extremely efficient. Actually catching an exception is expensive. In versions of Python prior to 2.0 it was common to use this idiom:: try: - value = dict[key] + value = mydict[key] except KeyError: - dict[key] = getvalue(key) - value = dict[key] + mydict[key] = getvalue(key) + value = mydict[key] This only made sense when you expected the dict to have the key almost all the time. If that wasn't the case, you coded it like this:: - if dict.has_key(key): - value = dict[key] + if mydict.has_key(key): + value = mydict[key] else: - dict[key] = getvalue(key) - value = dict[key] + mydict[key] = getvalue(key) + value = mydict[key] + +.. note:: -(In Python 2.0 and higher, you can code this as ``value = dict.setdefault(key, -getvalue(key))``.) + In Python 2.0 and higher, you can code this as ``value = + mydict.setdefault(key, getvalue(key))``. Why isn't there a switch or case statement in Python? @@ -432,7 +437,7 @@ code in various ways to increase performance. See, for example, `Psyco <http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/>`_, `PyInline <http://pyinline.sourceforge.net/>`_, `Py2Cmod <http://sourceforge.net/projects/py2cmod/>`_, and `Weave -<http://www.scipy.org/site_content/weave>`_. +<http://www.scipy.org/Weave>`_. How does Python manage memory? @@ -450,6 +455,8 @@ Jython relies on the Java runtime so the JVM's garbage collector is used. This difference can cause some subtle porting problems if your Python code depends on the behavior of the reference counting implementation. +.. XXX relevant for Python 2.6? + Sometimes objects get stuck in tracebacks temporarily and hence are not deallocated when you might expect. Clear the tracebacks with:: @@ -461,8 +468,8 @@ Tracebacks are used for reporting errors, implementing debuggers and related things. They contain a portion of the program state extracted during the handling of an exception (usually the most recent exception). -In the absence of circularities and tracebacks, Python programs need not -explicitly manage memory. +In the absence of circularities and tracebacks, Python programs do not need to +manage memory explicitly. Why doesn't Python use a more traditional garbage collection scheme? For one thing, this is not a C standard feature and hence it's not portable. (Yes, we @@ -481,19 +488,19 @@ implements malloc() and free() properly. In Jython, the following code (which is fine in CPython) will probably run out of file descriptors long before it runs out of memory:: - for file in <very long list of files>: + for file in very_long_list_of_files: f = open(file) c = f.read(1) Using the current reference counting and destructor scheme, each new assignment to f closes the previous file. Using GC, this is not guaranteed. If you want to write code that will work with any Python implementation, you should -explicitly close the file; this will work regardless of GC:: +explicitly close the file or use the :keyword:`with` statement; this will work +regardless of GC:: - for file in <very long list of files>: - f = open(file) - c = f.read(1) - f.close() + for file in very_long_list_of_files: + with open(file) as f: + c = f.read(1) Why isn't all memory freed when Python exits? @@ -589,10 +596,10 @@ Some unacceptable solutions that have been proposed: - Hash lists by their address (object ID). This doesn't work because if you construct a new list with the same value it won't be found; e.g.:: - d = {[1,2]: '12'} - print d[[1,2]] + mydict = {[1, 2]: '12'} + print mydict[[1, 2]] - would raise a KeyError exception because the id of the ``[1,2]`` used in the + would raise a KeyError exception because the id of the ``[1, 2]`` used in the second line differs from that in the first line. In other words, dictionary keys should be compared using ``==``, not using :keyword:`is`. @@ -613,7 +620,7 @@ Some unacceptable solutions that have been proposed: There is a trick to get around this if you need to, but use it at your own risk: You can wrap a mutable structure inside a class instance which has both a -:meth:`__cmp_` and a :meth:`__hash__` method. You must then make sure that the +:meth:`__eq__` and a :meth:`__hash__` method. You must then make sure that the hash value for all such wrapper objects that reside in a dictionary (or other hash based structure), remain fixed while the object is in the dictionary (or other structure). :: @@ -621,15 +628,15 @@ other structure). :: class ListWrapper: def __init__(self, the_list): self.the_list = the_list - def __cmp__(self, other): + def __eq__(self, other): return self.the_list == other.the_list def __hash__(self): l = self.the_list result = 98767 - len(l)*555 - for i in range(len(l)): + for i, el in enumerate(l): try: - result = result + (hash(l[i]) % 9999999) * 1001 + i - except: + result = result + (hash(el) % 9999999) * 1001 + i + except Exception: result = (result % 7777777) + i * 333 return result @@ -637,8 +644,8 @@ Note that the hash computation is complicated by the possibility that some members of the list may be unhashable and also by the possibility of arithmetic overflow. -Furthermore it must always be the case that if ``o1 == o2`` (ie ``o1.__cmp__(o2) -== 0``) then ``hash(o1) == hash(o2)`` (ie, ``o1.__hash__() == o2.__hash__()``), +Furthermore it must always be the case that if ``o1 == o2`` (ie ``o1.__eq__(o2) +is True``) then ``hash(o1) == hash(o2)`` (ie, ``o1.__hash__() == o2.__hash__()``), regardless of whether the object is in a dictionary or not. If you fail to meet these restrictions dictionaries and other hash based structures will misbehave. @@ -662,8 +669,8 @@ This function creates a new list from a provided iterable, sorts it and returns it. For example, here's how to iterate over the keys of a dictionary in sorted order:: - for key in sorted(dict.iterkeys()): - ... # do whatever with dict[key]... + for key in sorted(mydict): + ... # do whatever with mydict[key]... How do you specify and enforce an interface spec in Python? @@ -712,14 +719,14 @@ Why are default values shared between objects? This type of bug commonly bites neophyte programmers. Consider this function:: - def foo(D={}): # Danger: shared reference to one dict for all calls + def foo(mydict={}): # Danger: shared reference to one dict for all calls ... compute something ... - D[key] = value - return D + mydict[key] = value + return mydict -The first time you call this function, ``D`` contains a single item. The second -time, ``D`` contains two items because when ``foo()`` begins executing, ``D`` -starts out with an item already in it. +The first time you call this function, ``mydict`` contains a single item. The +second time, ``mydict`` contains two items because when ``foo()`` begins +executing, ``mydict`` starts out with an item already in it. It is often expected that a function call creates new objects for default values. This is not what happens. Default values are created exactly once, when @@ -735,14 +742,14 @@ objects as default values. Instead, use ``None`` as the default value and inside the function, check if the parameter is ``None`` and create a new list/dictionary/whatever if it is. For example, don't write:: - def foo(dict={}): + def foo(mydict={}): ... but:: - def foo(dict=None): - if dict is None: - dict = {} # create a new dict for local namespace + def foo(mydict=None): + if mydict is None: + mydict = {} # create a new dict for local namespace This feature can be useful. When you have a function that's time-consuming to compute, a common technique is to cache the parameters and the resulting value @@ -751,7 +758,7 @@ requested again. This is called "memoizing", and can be implemented like this:: # Callers will never provide a third parameter for this function. def expensive (arg1, arg2, _cache={}): - if _cache.has_key((arg1, arg2)): + if (arg1, arg2) in _cache: return _cache[(arg1, arg2)] # Calculate the value @@ -771,13 +778,13 @@ function calls. Many feel that exceptions can conveniently emulate all reasonable uses of the "go" or "goto" constructs of C, Fortran, and other languages. For example:: - class label: pass # declare a label + class label: pass # declare a label try: ... - if (condition): raise label() # goto label + if (condition): raise label() # goto label ... - except label: # where to goto + except label: # where to goto pass ... @@ -802,7 +809,7 @@ r-strings are used for their intended purpose. If you're trying to build Windows pathnames, note that all Windows system calls accept forward slashes too:: - f = open("/mydir/file.txt") # works fine! + f = open("/mydir/file.txt") # works fine! If you're trying to build a pathname for a DOS command, try e.g. one of :: @@ -819,7 +826,7 @@ on the entrance and exit from the block. Some language have a construct that looks like this:: with obj: - a = 1 # equivalent to obj.a = 1 + a = 1 # equivalent to obj.a = 1 total = total + 1 # obj.total = obj.total + 1 In Python, such a construct would be ambiguous. @@ -850,21 +857,20 @@ makes such choices much harder. The primary benefit of "with" and similar language features (reduction of code volume) can, however, easily be achieved in Python by assignment. Instead of:: - function(args).dict[index][index].a = 21 - function(args).dict[index][index].b = 42 - function(args).dict[index][index].c = 63 + function(args).mydict[index][index].a = 21 + function(args).mydict[index][index].b = 42 + function(args).mydict[index][index].c = 63 write this:: - ref = function(args).dict[index][index] + ref = function(args).mydict[index][index] ref.a = 21 ref.b = 42 ref.c = 63 This also has the side-effect of increasing execution speed because name bindings are resolved at run-time in Python, and the second version only needs -to perform the resolution once. If the referenced object does not have a, b and -c attributes, of course, the end result is still a run-time exception. +to perform the resolution once. Why are colons required for the if/while/def/class statements? diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index e72ee2a..c54bb28 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -176,32 +176,33 @@ Thus to get the same effect as:: it is much shorter and far faster to use :: - L2 = list(L1[:3]) # "list" is redundant if L1 is a list. + L2 = list(L1[:3]) # "list" is redundant if L1 is a list. Note that the functionally-oriented built-in functions such as :func:`map`, :func:`zip`, and friends can be a convenient accelerator for loops that perform a single task. For example to pair the elements of two lists together:: - >>> zip([1,2,3], [4,5,6]) + >>> zip([1, 2, 3], [4, 5, 6]) [(1, 4), (2, 5), (3, 6)] or to compute a number of sines:: - >>> map( math.sin, (1,2,3,4)) - [0.841470984808, 0.909297426826, 0.14112000806, -0.756802495308] + >>> map(math.sin, (1, 2, 3, 4)) + [0.841470984808, 0.909297426826, 0.14112000806, -0.756802495308] The operation completes very quickly in such cases. -Other examples include the ``join()`` and ``split()`` methods of string objects. +Other examples include the ``join()`` and ``split()`` :ref:`methods +of string objects <string-methods>`. For example if s1..s7 are large (10K+) strings then ``"".join([s1,s2,s3,s4,s5,s6,s7])`` may be far faster than the more obvious ``s1+s2+s3+s4+s5+s6+s7``, since the "summation" will compute many subexpressions, whereas ``join()`` does all the copying in one pass. For -manipulating strings, use the ``replace()`` method on string objects. Use -regular expressions only when you're not dealing with constant string patterns. -Consider using the string formatting operations ``string % tuple`` and ``string -% dictionary``. +manipulating strings, use the ``replace()`` and the ``format()`` :ref:`methods +on string objects <string-methods>`. Use regular expressions only when you're +not dealing with constant string patterns. You may still use :ref:`the old % +operations <string-formatting>` ``string % tuple`` and ``string % dictionary``. Be sure to use the :meth:`list.sort` built-in method to do sorting, and see the `sorting mini-HOWTO <http://wiki.python.org/moin/HowTo/Sorting>`_ for examples @@ -211,7 +212,7 @@ sorting in all but the most extreme circumstances. Another common trick is to "push loops into functions or methods." For example suppose you have a program that runs slowly and you use the profiler to determine that a Python function ``ff()`` is being called lots of times. If you -notice that ``ff ()``:: +notice that ``ff()``:: def ff(x): ... # do something with x computing result... @@ -332,24 +333,6 @@ actually modifying the value of the variable in the outer scope: >>> print x 11 -In Python3, you can do a similar thing in a nested scope using the -:keyword:`nonlocal` keyword: - -.. doctest:: - :options: +SKIP - - >>> def foo(): - ... x = 10 - ... def bar(): - ... nonlocal x - ... print x - ... x += 1 - ... bar() - ... print x - >>> foo() - 10 - 11 - What are the rules for local and global variables in Python? ------------------------------------------------------------ @@ -412,7 +395,7 @@ using multiple imports per line uses less screen space. It's good practice if you import modules in the following order: -1. standard library modules -- e.g. ``sys``, ``os``, ``getopt``, ``re``) +1. standard library modules -- e.g. ``sys``, ``os``, ``getopt``, ``re`` 2. third-party library modules (anything installed in Python's site-packages directory) -- e.g. mx.DateTime, ZODB, PIL.Image, etc. 3. locally-developed modules @@ -421,7 +404,7 @@ Never use relative package imports. If you're writing code that's in the ``package.sub.m1`` module and want to import ``package.sub.m2``, do not just write ``import m2``, even though it's legal. Write ``from package.sub import m2`` instead. Relative imports can lead to a module being initialized twice, -leading to confusing bugs. +leading to confusing bugs. See :pep:`328` for details. It is sometimes necessary to move imports to a function or class to avoid problems with circular imports. Gordon McMillan says: @@ -649,9 +632,9 @@ callable. Consider the following code:: a = B() b = a print b - <__main__.A instance at 016D07CC> + <__main__.A instance at 0x16D07CC> print a - <__main__.A instance at 016D07CC> + <__main__.A instance at 0x16D07CC> Arguably the class has a name: even though it is bound to two names and invoked through the name B the created instance is still reported as an instance of @@ -681,7 +664,7 @@ What's up with the comma operator's precedence? Comma is not an operator in Python. Consider this session:: >>> "a" in "b", "a" - (False, '1') + (False, 'a') Since the comma is not an operator, but a separator between expressions the above is evaluated as if you had entered:: @@ -690,7 +673,7 @@ above is evaluated as if you had entered:: not:: - >>> "a" in ("5", "a") + >>> "a" in ("b", "a") The same is true of the various assignment operators (``=``, ``+=`` etc). They are not truly operators but syntactic delimiters in assignment statements. @@ -732,12 +715,12 @@ solution is to implement the ``?:`` operator as a function:: if not isfunction(on_true): return on_true else: - return apply(on_true) + return on_true() else: if not isfunction(on_false): return on_false else: - return apply(on_false) + return on_false() In most cases you'll pass b and c directly: ``q(a, b, c)``. To avoid evaluating b or c when they shouldn't be, encapsulate them within a lambda function, e.g.: @@ -767,7 +750,7 @@ Yes. Usually this is done by nesting :keyword:`lambda` within map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000))) # First 10 Fibonacci numbers - print map(lambda x,f=lambda x,f:(x<=1) or (f(x-1,f)+f(x-2,f)): f(x,f), + print map(lambda x,f=lambda x,f:(f(x-1,f)+f(x-2,f)) if x>1 else 1: f(x,f), range(10)) # Mandelbrot set @@ -793,10 +776,11 @@ Numbers and strings How do I specify hexadecimal and octal integers? ------------------------------------------------ -To specify an octal digit, precede the octal value with a zero. For example, to -set the variable "a" to the octal value "10" (8 in decimal), type:: +To specify an octal digit, precede the octal value with a zero, and then a lower +or uppercase "o". For example, to set the variable "a" to the octal value "10" +(8 in decimal), type:: - >>> a = 010 + >>> a = 0o10 >>> a 8 @@ -812,17 +796,17 @@ or uppercase. For example, in the Python interpreter:: 178 -Why does -22 / 10 return -3? ----------------------------- +Why does -22 // 10 return -3? +----------------------------- It's primarily driven by the desire that ``i % j`` have the same sign as ``j``. If you want that, and also want:: - i == (i / j) * j + (i % j) + i == (i // j) * j + (i % j) then integer division has to return the floor. C also requires that identity to -hold, and then compilers that truncate ``i / j`` need to make ``i % j`` have the -same sign as ``i``. +hold, and then compilers that truncate ``i // j`` need to make ``i % j`` have +the same sign as ``i``. There are few real use cases for ``i % j`` when ``j`` is negative. When ``j`` is positive, there are many, and in virtually all of them it's more useful for @@ -830,6 +814,12 @@ is positive, there are many, and in virtually all of them it's more useful for ago? ``-190 % 12 == 2`` is useful; ``-190 % 12 == -10`` is a bug waiting to bite. +.. note:: + + On Python 2, ``a / b`` returns the same as ``a // b`` if + ``__future__.division`` is not in effect. This is also known as "classic" + division. + How do I convert a string to a number? -------------------------------------- @@ -861,10 +851,11 @@ How do I convert a number to a string? To convert, e.g., the number 144 to the string '144', use the built-in type constructor :func:`str`. If you want a hexadecimal or octal representation, use -the built-in functions ``hex()`` or ``oct()``. For fancy formatting, use -:ref:`the % operator <string-formatting>` on strings, e.g. ``"%04d" % 144`` -yields ``'0144'`` and ``"%.3f" % (1/3.0)`` yields ``'0.333'``. See the library -reference manual for details. +the built-in functions :func:`hex` or :func:`oct`. For fancy formatting, see +the :ref:`formatstrings` section, e.g. ``"{:04d}".format(144)`` yields +``'0144'`` and ``"{:.3f}".format(1/3)`` yields ``'0.333'``. You may also use +:ref:`the % operator <string-formatting>` on strings. See the library reference +manual for details. How do I modify a string in place? @@ -962,12 +953,12 @@ blank lines will be removed:: ... "\r\n" ... "\r\n") >>> lines.rstrip("\n\r") - "line 1 " + 'line 1 ' Since this is typically only desired when reading text one line at a time, using ``S.rstrip()`` this way works well. -For older versions of Python, There are two partial substitutes: +For older versions of Python, there are two partial substitutes: - If you want to remove all trailing whitespace, use the ``rstrip()`` method of string objects. This removes all trailing whitespace, not just a single @@ -1093,26 +1084,26 @@ See the Python Cookbook for a long discussion of many ways to do this: If you don't mind reordering the list, sort it and then scan from the end of the list, deleting duplicates as you go:: - if List: - List.sort() - last = List[-1] - for i in range(len(List)-2, -1, -1): - if last == List[i]: - del List[i] + if mylist: + mylist.sort() + last = mylist[-1] + for i in range(len(mylist)-2, -1, -1): + if last == mylist[i]: + del mylist[i] else: - last = List[i] + last = mylist[i] If all elements of the list may be used as dictionary keys (i.e. they are all hashable) this is often faster :: d = {} - for x in List: - d[x] = x - List = d.values() + for x in mylist: + d[x] = 1 + mylist = list(d.keys()) In Python 2.5 and later, the following is possible instead:: - List = list(set(List)) + mylist = list(set(mylist)) This converts the list into a set, thereby removing duplicates, and then back into a list. @@ -1188,7 +1179,7 @@ How do I apply a method to a sequence of objects? Use a list comprehension:: - result = [obj.method() for obj in List] + result = [obj.method() for obj in mylist] More generically, you can try the following function:: @@ -1213,23 +1204,17 @@ some changes and then compare it with some other printed dictionary. In this case, use the ``pprint`` module to pretty-print the dictionary; the items will be presented in order sorted by the key. -A more complicated solution is to subclass ``UserDict.UserDict`` to create a +A more complicated solution is to subclass ``dict`` to create a ``SortedDict`` class that prints itself in a predictable order. Here's one simpleminded implementation of such a class:: - import UserDict, string - - class SortedDict(UserDict.UserDict): + class SortedDict(dict): def __repr__(self): - result = [] - append = result.append - keys = self.data.keys() - keys.sort() - for k in keys: - append("%s: %s" % (`k`, `self.data[k]`)) - return "{%s}" % string.join(result, ", ") + keys = sorted(self.keys()) + result = ("{!r}: {!r}".format(k, self[k]) for k in keys) + return "{{{}}}".format(", ".join(result)) - __str__ = __repr__ + __str__ = __repr__ This will work for many common situations you might encounter, though it's far from a perfect solution. The largest flaw is that if some values in the @@ -1251,14 +1236,14 @@ The ``key`` argument is new in Python 2.4, for older versions this kind of sorting is quite simple to do with list comprehensions. To sort a list of strings by their uppercase values:: - tmp1 = [(x.upper(), x) for x in L] # Schwartzian transform + tmp1 = [(x.upper(), x) for x in L] # Schwartzian transform tmp1.sort() Usorted = [x[1] for x in tmp1] To sort by the integer value of a subfield extending from positions 10-15 in each string:: - tmp2 = [(int(s[10:15]), s) for s in L] # Schwartzian transform + tmp2 = [(int(s[10:15]), s) for s in L] # Schwartzian transform tmp2.sort() Isorted = [x[1] for x in tmp2] @@ -1295,8 +1280,8 @@ out the element you want. :: An alternative for the last step is:: - result = [] - for p in pairs: result.append(p[1]) + >>> result = [] + >>> for p in pairs: result.append(p[1]) If you find this more legible, you might prefer to use this instead of the final list comprehension. However, it is almost twice as slow for long lists. Why? @@ -1364,7 +1349,7 @@ particular behaviour, instead of checking the object's class and doing a different thing based on what class it is. For example, if you have a function that does something:: - def search (obj): + def search(obj): if isinstance(obj, Mailbox): # ... code to search a mailbox elif isinstance(obj, Document): @@ -1467,8 +1452,8 @@ of resources) which base class to use. Example:: How do I create static class data and static class methods? ----------------------------------------------------------- -Static data (in the sense of C++ or Java) is easy; static methods (again in the -sense of C++ or Java) are not supported directly. +Both static data and static methods (in the sense of C++ or Java) are supported +in Python. For static data, simply define a class attribute. To assign a new value to the attribute, you have to explicitly use the class name in the assignment:: @@ -1487,9 +1472,9 @@ C)`` holds, unless overridden by ``c`` itself or by some class on the base-class search path from ``c.__class__`` back to ``C``. Caution: within a method of C, an assignment like ``self.count = 42`` creates a -new and unrelated instance vrbl named "count" in ``self``'s own dict. Rebinding -of a class-static data name must always specify the class whether inside a -method or not:: +new and unrelated instance named "count" in ``self``'s own dict. Rebinding of a +class-static data name must always specify the class whether inside a method or +not:: C.count = 314 |