~ubuntu-branches/ubuntu/karmic/python3.0/karmic

« back to all changes in this revision

Viewing changes to Doc/howto/functional.rst

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-16 17:18:23 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090216171823-1d5cm5qnnjvmnzzm
Tags: 3.0.1-0ubuntu1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
145
145
functions are also easier to read and to check for errors.
146
146
 
147
147
 
148
 
Ease of debugging and testing 
 
148
Ease of debugging and testing
149
149
-----------------------------
150
150
 
151
151
Testing and debugging a functional-style program is easier.
213
213
    Traceback (most recent call last):
214
214
      File "<stdin>", line 1, in ?
215
215
    StopIteration
216
 
    >>>      
 
216
    >>>
217
217
 
218
218
Python expects iterable objects in several different contexts, the most
219
219
important being the ``for`` statement.  In the statement ``for X in Y``, Y must
363
363
comprehensions are surrounded by square brackets ("[]").  Generator expressions
364
364
have the form::
365
365
 
366
 
    ( expression for expr in sequence1 
 
366
    ( expression for expr in sequence1
367
367
                 if condition1
368
368
                 for expr2 in sequence2
369
369
                 if condition2
405
405
                 if not (conditionN):
406
406
                     continue   # Skip this element
407
407
 
408
 
                 # Output the value of 
 
408
                 # Output the value of
409
409
                 # the expression.
410
410
 
411
411
This means that when there are multiple ``for...in`` clauses but no ``if``
419
419
    >>> seq1 = 'abc'
420
420
    >>> seq2 = (1,2,3)
421
421
    >>> [(x,y) for x in seq1 for y in seq2]
422
 
    [('a', 1), ('a', 2), ('a', 3), 
423
 
     ('b', 1), ('b', 2), ('b', 3), 
 
422
    [('a', 1), ('a', 2), ('a', 3),
 
423
     ('b', 1), ('b', 2), ('b', 3),
424
424
     ('c', 1), ('c', 2), ('c', 3)]
425
425
 
426
426
To avoid introducing an ambiguity into Python's grammar, if ``expression`` is
586
586
    9
587
587
    >>> next(it)
588
588
    Traceback (most recent call last):
589
 
      File ``t.py'', line 15, in ?
 
589
      File "t.py", line 15, in ?
590
590
        it.next()
591
591
    StopIteration
592
592
 
627
627
Two of Python's built-in functions, :func:`map` and :func:`filter` duplicate the
628
628
features of generator expressions:
629
629
 
630
 
``map(f, iterA, iterB, ...)`` returns an iterator over the sequence 
 
630
``map(f, iterA, iterB, ...)`` returns an iterator over the sequence
631
631
 ``f(iterA[0], iterB[0]), f(iterA[1], iterB[1]), f(iterA[2], iterB[2]), ...``.
632
632
 
633
633
    >>> def upper(s):
634
634
    ...     return s.upper()
635
635
 
636
636
 
637
 
    >>> map(upper, ['sentence', 'fragment'])
 
637
    >>> list(map(upper, ['sentence', 'fragment']))
638
638
    ['SENTENCE', 'FRAGMENT']
639
639
    >>> [upper(s) for s in ['sentence', 'fragment']]
640
640
    ['SENTENCE', 'FRAGMENT']
641
641
 
642
 
You can of course achieve the same effect with a list comprehension. 
 
642
You can of course achieve the same effect with a list comprehension.
643
643
 
644
644
``filter(predicate, iter)`` returns an iterator over all the sequence elements
645
645
that meet a certain condition, and is similarly duplicated by list
650
650
    >>> def is_even(x):
651
651
    ...     return (x % 2) == 0
652
652
 
653
 
    >>> filter(is_even, range(10))
 
653
    >>> list(filter(is_even, range(10)))
654
654
    [0, 2, 4, 6, 8]
655
655
 
656
656
 
677
677
        if line.strip() == '':
678
678
            print('Blank line at line #%i' % i)
679
679
 
680
 
 
681
 
``sorted(iterable, [cmp=None], [key=None], [reverse=False)`` collects all the
682
 
elements of the iterable into a list, sorts the list, and returns the sorted
683
 
result.  The ``cmp``, ``key``, and ``reverse`` arguments are passed through to
684
 
the constructed list's ``.sort()`` method. ::
 
680
``sorted(iterable, [key=None], [reverse=False])`` collects all the elements of
 
681
the iterable into a list, sorts the list, and returns the sorted result.  The
 
682
``key``, and ``reverse`` arguments are passed through to the constructed list's
 
683
``.sort()`` method. ::
685
684
 
686
685
    >>> import random
687
686
    >>> # Generate 8 random numbers between [0, 10000)
710
709
    True
711
710
    >>> all([0,1,0])
712
711
    False
713
 
    >>> all([0,0,0]) 
 
712
    >>> all([0,0,0])
714
713
    False
715
714
    >>> all([1,1,1])
716
715
    True
828
827
``itertools.starmap(func, iter)`` assumes that the iterable will return a stream
829
828
of tuples, and calls ``f()`` using these tuples as the arguments::
830
829
 
831
 
    itertools.starmap(os.path.join, 
 
830
    itertools.starmap(os.path.join,
832
831
                      [('/usr', 'bin', 'java'), ('/bin', 'python'),
833
832
                       ('/usr', 'bin', 'perl'),('/usr', 'bin', 'ruby')])
834
833
    =>
888
887
 
889
888
::
890
889
 
891
 
    city_list = [('Decatur', 'AL'), ('Huntsville', 'AL'), ('Selma', 'AL'), 
 
890
    city_list = [('Decatur', 'AL'), ('Huntsville', 'AL'), ('Selma', 'AL'),
892
891
                 ('Anchorage', 'AK'), ('Nome', 'AK'),
893
 
                 ('Flagstaff', 'AZ'), ('Phoenix', 'AZ'), ('Tucson', 'AZ'), 
 
892
                 ('Flagstaff', 'AZ'), ('Phoenix', 'AZ'), ('Tucson', 'AZ'),
894
893
                 ...
895
894
                ]
896
895
 
905
904
    where
906
905
    iterator-1 =>
907
906
      ('Decatur', 'AL'), ('Huntsville', 'AL'), ('Selma', 'AL')
908
 
    iterator-2 => 
 
907
    iterator-2 =>
909
908
      ('Anchorage', 'AK'), ('Nome', 'AK')
910
909
    iterator-3 =>
911
910
      ('Flagstaff', 'AZ'), ('Phoenix', 'AZ'), ('Tucson', 'AZ')
1046
1045
 
1047
1046
    >>> double(add(5, 6))
1048
1047
    22
1049
 
                    
 
1048
 
1050
1049
The ``unpack`` keyword is provided to work around the fact that Python functions
1051
1050
are not always `fully curried <http://en.wikipedia.org/wiki/Currying>`__.  By
1052
1051
default, it is expected that the ``inner`` function will return a single object
1055
1054
will be expanded before being passed to ``outer``. Put simply, ::
1056
1055
 
1057
1056
    compose(f, g)(5, 6)
1058
 
                    
 
1057
 
1059
1058
is equivalent to::
1060
1059
 
1061
1060
    f(g(5, 6))
1062
 
                    
 
1061
 
1063
1062
while ::
1064
1063
 
1065
1064
    compose(f, g, unpack=True)(5, 6)
1066
 
                    
 
1065
 
1067
1066
is equivalent to::
1068
1067
 
1069
1068
    f(*g(5, 6))
1075
1074
 
1076
1075
    from functional import compose, partial
1077
1076
    import functools
1078
 
        
 
1077
 
1079
1078
 
1080
1079
    multi_compose = partial(functools.reduce, compose)
1081
 
        
1082
 
    
 
1080
 
 
1081
 
1083
1082
We can also use ``map()``, ``compose()`` and ``partial()`` to craft a version of
1084
1083
``"".join(...)`` that converts its arguments to string::
1085
1084
 
1086
1085
    from functional import compose, partial
1087
 
        
 
1086
 
1088
1087
    join = compose("".join, partial(map, str))
1089
1088
 
1090
1089
 
1091
1090
``flip(func)``
1092
 
                    
 
1091
 
1093
1092
``flip()`` wraps the callable in ``func`` and causes it to receive its
1094
1093
non-keyword arguments in reverse order. ::
1095
1094
 
1104
1103
    (7, 6, 5)
1105
1104
 
1106
1105
``foldl(func, start, iterable)``
1107
 
                    
 
1106
 
1108
1107
``foldl()`` takes a binary function, a starting value (usually some kind of
1109
1108
'zero'), and an iterable.  The function is applied to the starting value and the
1110
1109
first element of the list, then the result of that and the second element of the
1118
1117
 
1119
1118
    f(f(f(0, 1), 2), 3)
1120
1119
 
1121
 
    
 
1120
 
1122
1121
``foldl()`` is roughly equivalent to the following recursive function::
1123
1122
 
1124
1123
    def foldl(func, start, seq):
1225
1224
4) Convert the lambda to a def statement, using that name.
1226
1225
5) Remove the comment.
1227
1226
 
1228
 
I really like these rules, but you're free to disagree 
 
1227
I really like these rules, but you're free to disagree
1229
1228
about whether this lambda-free style is better.
1230
1229
 
1231
1230
 
1283
1282
Text Processing".
1284
1283
 
1285
1284
Mertz also wrote a 3-part series of articles on functional programming
1286
 
for IBM's DeveloperWorks site; see 
 
1285
for IBM's DeveloperWorks site; see
1287
1286
`part 1 <http://www-128.ibm.com/developerworks/library/l-prog.html>`__,
1288
1287
`part 2 <http://www-128.ibm.com/developerworks/library/l-prog2.html>`__, and
1289
1288
`part 3 <http://www-128.ibm.com/developerworks/linux/library/l-prog3.html>`__,