代码之家  ›  专栏  ›  技术社区  ›  Juergen

python中是否有无结果的映射?

  •  24
  • Juergen  · 技术社区  · 16 年前

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

    map(lambda x: installWow(x, 'installed by me'), wowList)
    

    但这当然会创建一个很好的列表[None,None,…],所以我的问题是,如果有一个类似的函数没有返回列表——因为我不需要它。

    (当然,我也可以使用x,因此不会留下可见的足迹——但地图解决方案看起来非常整洁…)

    14 回复  |  直到 16 年前
        1
  •  29
  •   John Montgomery    16 年前

    
    def each(fn, items):
        for item in items:
            fn(item)
    
    
    # called thus
    each(lambda x: installWow(x, 'installed by me'), wowList)
    
    

    基本上它只是映射,但没有返回结果。通过使用函数,您将确保“item”变量不会泄漏到当前范围中。

        2
  •  14
  •   RichieHindle    16 年前

    for x in wowList:
        installWow(x, 'installed by me')
    del x
    
        3
  •  9
  •   f0xdx    8 年前

    您可以使用内置的 any 函数来应用函数 无返回语句

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

    我发现这是你想要实现的最简洁的idom。

    installWow 函数确实返回 None 评估结果是 False 在逻辑运算中。 任何 or 对生成器返回的所有项目执行还原操作,这些项目都是 没有一个 当然,它必须迭代生成器返回的所有项。最终它还是回来了 错误的 ,但你不必为此烦恼。好的一面是:没有列表会产生副作用。

    错误的 ,例如:。, 没有一个 或0。如果它确实返回计算结果为 True 在某个时刻,例如。, 1 ,它将不会应用于迭代器中的任何剩余元素。为了安全起见,这个习惯用法主要用于没有返回语句的函数。

        4
  •  6
  •   balpha    16 年前

    每一个表达式的计算结果都是某个东西,所以无论采用何种方式,都会得到一个结果。任何这样返回的对象(就像您的列表)都将在之后被丢弃,因为不再有对它的引用。

    澄清一下:python中很少有语句不返回任何内容。甚至像这样的函数调用

    doSomething()
    

        5
  •  6
  •   Mark Rushakoff    16 年前

    你可以试试这个:

    filter(lambda x: installWow(x, 'installed by me') and False, wowList)
    

    或者你也可以直接放下枪 and False installWow() False (或0或 None

        6
  •  3
  •   Alexander Ljungberg    16 年前

    您可以使用一个过滤器和一个不返回真值的函数。您将得到一个空的返回列表,因为filter只添加计算结果为true的值,我想这将为您节省一些内存。大概是这样的:

    #!/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
    

    Filter output: ()
    Side effect result: 10
    
        7
  •  3
  •   Anurag Uniyal    16 年前

    我忍不住把它作为单独的答案贴出来

    reduce(lambda x,y: x(y, 'installed by me') , wowList, installWow)
    

    只有twist是installWow应该返回自身,例如。

    def installWow(*args):
        print args
        return installWow
    
        8
  •  3
  •   Anurag Uniyal    5 年前

    如果可以分发wowList

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

    如果您确实想维护wowList

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

    如果秩序重要呢

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

    虽然作为谜题的答案,我喜欢第一个:)

        9
  •  2
  •   Nick    13 年前

    我测试了几种不同的变体,下面是我得到的结果。

    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
    

    请注意,时间值没有那么精确(例如,前三个选项的相对性能因运行而异)。我的结论是,您应该只使用一个循环,它更具可读性,并且至少与其他方法一样好。如果要避免污染名称空间,只需 del 在使用变量后,将其删除。

        10
  •  1
  •   SingleNegationElimination    16 年前

    首先将for循环重写为生成器表达式,该表达式不分配任何内存。

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

    但是,如果没有找到某种方法来使用它,这个表达式实际上不会做任何事情。所以我们可以重写它来产生一些确定的结果,而不是依赖于可能的结果 None 结果 installWow .

    ( [1, installWow(x,  'installed by me')][0] for x in wowList )
    

    reduce

    reduce(sum, ( [1, installWow(x,  'installed by me')][0] for x in wowList ))
    

    它方便地返回wowList中受影响的项目数。

        11
  •  1
  •   freegnu    16 年前

    只需将installWow设置为return None或将最后一条语句设置为pass,如下所示:

    
    def installWow(item, phrase='installed by me'):
      print phrase
      pass
    

    并使用以下命令:

    
    list(x for x in wowList if installWow(x))
    

        12
  •  1
  •   benlast    12 年前

    如果您担心需要控制返回值(您需要这样做才能使用 滤器 )并且更喜欢一个比 减少 直接地您的函数将需要额外的第一个参数,但您可以忽略它,或使用lambda放弃它:

    reduce(lambda _x: installWow(_x, 'installed by me'), wowList, None)
    
        13
  •  1
  •   parity3    10 年前

    让我先说一句,原来的海报似乎更关注名称空间的混乱,而不是其他任何东西。在这种情况下,您可以将工作变量包装在单独的函数名称空间中,并在声明后调用它,或者在将它们与“del”内置命令一起使用后,只需将它们从名称空间中删除即可。或者,如果有多个变量需要清理,则使用其中的所有临时变量定义函数,运行它,然后删除它。

    如果主要问题是优化,请继续阅读:

    还有三种方式,可能比这里描述的其他方式更快:

    1. 对于Python>=2.7,使用collections.deque((wowList中x的installWow(x,'installed by me')),0)#在迭代整个生成器时保存0个条目,但仍然有最终对象的副产品以及内部的每项长度检查
    2. 如果担心这种开销,请安装 cytoolz . 你可以用 count 它仍然有一个增加计数器的副产品,但它可能比deque的每项检查的周期数少,不确定。您可以在下一种方式中使用它而不是任何()

    但这里真正的问题是函数返回某些内容,而您不希望它返回任何内容。。所以要解决这个问题,你有两个选择。一种是重构代码,以便installWow接收wowList并在内部对其进行迭代。另一种方法相当令人兴奋,但您可以将installWow()函数加载到编译的ast中,如下所示:

    lines,lineno=inspect.getsourcelines(func) # func here is installWow without the parens
    return ast.parse(join(l[4:] for l in lines if l)) # assumes the installWow function is part of a class in a module file.. For a module-level function you would not need the l[4:]
    

    exec on the ast 并提供一个包含正确变量的名称空间字典。为了确保树修改是正确的,您可以通过运行 astunparse .

        14
  •  1
  •   Michael Ekoka    6 年前

    一个简单的DIY,其唯一目的是通过生成器表达式循环:

    def do(genexpr):
        for _ in genexpr:
            pass
    

    然后使用:

    do(installWow(x, 'installed by me') for x in wowList)
    
        15
  •  0
  •   gbtimmon    7 年前

    有人需要回答--

    这里更具python风格的方法是不用担心污染名称空间,并使用 __all__ 定义公共变量。

    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')
    

    然后

    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']
    
    推荐文章