Is there a map without result in python?

前端 未结 15 1022
北恋
北恋 2020-12-03 04:33

Sometimes, I just want to execute a function for a list of entries -- eg.:

for x in wowList:
   installWow(x, \'installed by me\')

Sometime

相关标签:
15条回答
  • 2020-12-03 05:10

    You could use a filter and a function that doesn't return a True value. You'd get an empty return list since filter only adds the values which evaluates to true, which I suppose would save you some memory. Something like this:

    #!/usr/bin/env python
    y = 0
    def myfunction(x):
      global y
      y += x
    
    input = (1, 2, 3, 4)
    
    print "Filter output: %s" % repr(filter(myfunction, input))
    print "Side effect result: %d" % y
    

    Running it produces this output:

    Filter output: ()
    Side effect result: 10
    
    0 讨论(0)
  • 2020-12-03 05:14

    Someone needs to answer --

    The more pythonic way here is to not worry about polluting the namespace, and using __all__ to define the public variables.

    myModule/__init__.py:
         __all__ = ['func1', 'func2']
    
         for x in range(10): 
             print 'init {}'.format(x)
    
         def privateHelper1(x):
             return '{}:{}'.format(x,x)
    
         def func1(): 
             print privateHelper1('func1')
    
         def func2(): 
             print privateHelper1('func1')
    

    Then

    python -c "import myModule; help(myModule);"
    
    init 0
    init 1
    init 2
    init 3
    init 4
    init 5
    init 6
    init 7
    init 8
    init 9
    Help on package mm:
    
    NAME
        myModule
    
    FILE
        h:\myModule\__init__.py
    
    PACKAGE CONTENTS
    
    
    FUNCTIONS
        func1()
    
       func2()
    
    DATA
       __all__ = ['func1', 'func2']
    
    0 讨论(0)
  • 2020-12-03 05:16

    if it is ok to distruct wowList

    while wowList: installWow(wowList.pop(), 'installed by me')
    

    if you do want to maintain wowList

    wowListR = wowList[:]
    while wowListR: installWow(wowListR.pop(), 'installed by me')
    

    and if order matters

    wowListR = wowList[:]; wowListR.reverse()
    while wowListR: installWow(wowListR.pop(), 'installed by me')
    

    Though as the solution of the puzzle I like the first :)

    0 讨论(0)
  • 2020-12-03 05:17

    You can use the built-in any function to apply a function without return statement to any item returned by a generator without creating a list. This can be achieved like this:

    any(installWow(x, 'installed by me') for x in wowList)
    

    I found this the most concise idom for what you want to achieve.

    Internally, the installWow function does return None which evaluates to False in logical operations. any basically applies an or reduction operation to all items returned by the generator, which are all None of course, so it has to iterate over all items returned by the generator. In the end it does return False, but that doesn't need to bother you. The good thing is: no list is created as a side-effect.

    Note that this only works as long as your function returns something that evaluates to False, e.g., None or 0. If it does return something that evaluates to True at some point, e.g., 1, it will not be applied to any of the remaining elements in your iterator. To be safe, use this idiom mainly for functions without return statement.

    0 讨论(0)
  • 2020-12-03 05:17

    I tested several different variants, and here are the results I got.

    Python 2:

    >>> timeit.timeit('for x in xrange(100): L.append(x)', 'L = []')
    14.9432640076
    >>> timeit.timeit('[x for x in xrange(100) if L.append(x) and False]', 'L = []')
    16.7011508942
    >>> timeit.timeit('next((x for x in xrange(100) if L.append(x) and False), None)', 'L = []')
    15.5235641003
    >>> timeit.timeit('any(L.append(x) and False for x in xrange(100))', 'L = []')
    20.9048290253
    >>> timeit.timeit('filter(lambda x: L.append(x) and False, xrange(100))', 'L = []')
    27.8524758816
    

    Python 3:

    >>> timeit.timeit('for x in range(100): L.append(x)', 'L = []')
    13.719769178002025
    >>> timeit.timeit('[x for x in range(100) if L.append(x) and False]', 'L = []')
    15.041426660001889
    >>> timeit.timeit('next((x for x in range(100) if L.append(x) and False), None)', 'L = []')
    15.448063717998593
    >>> timeit.timeit('any(L.append(x) and False for x in range(100))', 'L = []')
    22.087335471998813
    >>> timeit.timeit('next(filter(lambda x: L.append(x) and False, range(100)), None)', 'L = []')
    36.72446593800123
    

    Note that the time values are not that precise (for example, the relative performance of the first three options varied from run to run). My conclusion is that you should just use a loop, it's more readable and performs at least as well as the alternatives. If you want to avoid polluting the namespace, just del the variable after using it.

    0 讨论(0)
  • 2020-12-03 05:17

    If you're worried about the need to control the return value (which you need to do to use filter) and prefer a simpler solution than the reduce example above, then consider using reduce directly. Your function will need to take an additional first parameter, but you can ignore it, or use a lambda to discard it:

    reduce(lambda _x: installWow(_x, 'installed by me'), wowList, None)
    
    0 讨论(0)
提交回复
热议问题