30

時々、エントリのリストに対して関数を実行したいだけです-例えば:

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

モジュールの初期化のためにこのようなものが必要になることがあるので、グローバル名前空間に x のようなフットプリントを持ちたくありません。1 つの解決策は、ラムダと一緒に map を使用することです。

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

しかし、これはもちろん素敵なリスト [None、None、...] を作成するので、私の質問は、return-list のない同様の関数があるかどうかです-私はそれを必要としないからです。

(もちろん、_x を使用することもできるので、フットプリントを目に見える形で残すことはできませんが、マップ ソリューションはとてもきれいに見えます ...)

4

16 に答える 16

29

独自の「各」関数を作成できます。


def each(fn, items):
    for item in items:
        fn(item)


# called thus
each(lambda x: installWow(x, 'installed by me'), wowList)

基本的にはマップですが、結果は返されません。関数を使用することで、「item」変数が現在のスコープにリークしないようにします。

于 2009-07-03T17:45:30.493 に答える
6

あなたはこれを試すかもしれません:

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

そうすれば、返される結果は何があっても空のリストになります。

または、常に返すようにand False強制できる場合(または 0 またはfalse と評価される別の式) を削除することもできます。installWow()FalseNone

于 2009-07-03T16:30:22.527 に答える
6

すべての式は何かに評価されるため、どの方法で実行しても常に結果が得られます。そして、そのような返されたオブジェクト (リストと同じように) は、参照がなくなったため、後で破棄されます。

明確にするために: Python では、何も返さないステートメントはほとんどありません。のような関数呼び出しでも

doSomething()

すぐに破棄されても、値を返します。python には Pascal の関数/手続きの区別のようなものはありません。

于 2009-07-03T16:30:39.360 に答える
3

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

パズルの解決策としては、最初のが好きですが:)

于 2009-07-03T17:32:31.437 に答える
3

別の回答として投稿することに抵抗できません

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

ツイストのみ installWow はそれ自体を返す必要があります。

def installWow(*args):
    print args
    return installWow
于 2009-07-03T17:41:16.283 に答える
3

True 値を返さないフィルターと関数を使用できます。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
于 2009-07-03T16:32:07.020 に答える
1

installWow が None を返すようにするか、最後のステートメントを次のように渡すだけです。


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

これを使用します:


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

x はグローバル名前空間に設定されず、返されるリストは [] シングルトンです

于 2009-07-04T02:06:00.193 に答える
1

最初に、元の投稿者は名前空間の乱雑さを何よりも懸念していたようだと言っておきましょう。その場合、作業変数を別の関数名前空間にラップし、宣言後に呼び出すか、「del」組み込みコマンドで使用した後に名前空間から単純に削除できます。または、クリーンアップする変数が複数ある場合は、すべての一時変数を使用して関数を定義し、実行してから削除します。

主な関心事が最適化である場合は、読み進めてください。

さらに 3 つの方法があり、ここで説明する他の方法よりも高速になる可能性があります。

  1. Python >= 2.7 の場合、 collections.deque((installWow(x, 'installed by me') for x in wowList),0) # ジェネレーター全体を反復しながら 0 エントリを保存しますが、そうです、まだ最終的な副産物があります内部で項目ごとの長さチェックを伴うオブジェクト
  2. このようなオーバーヘッドが気になる場合は、cytoolzをインストールしてください。カウンターをインクリメントする副産物がまだあるcountを使用できますが、dequeのアイテムごとのチェックよりもサイクル数が少ない可能性があります。次の方法で any() の代わりに使用できます。
  3. ジェネレータ式を itertools.imap に置き換えます (installWow が True を返さない場合。それ以外の場合は、 itertools.ifilter および itertools.ifilterfalse を述語として None と見なすことができます): any(itertools.imap(installWow,wowList,itertools.repeat('installed by自分')))

しかし、ここでの本当の問題は、関数が何かを返し、何も返したくないという事実です。したがって、これを解決するには、2 つのオプションがあります。1 つはコードをリファクタリングして、installWow が wowList を取り込んで内部で繰り返すようにすることです。もう 1 つはかなり衝撃的ですが、次のように 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:]

次に、外側の関数に対して同じことを行い、ast をトラバースして for ループを見つけることができます。次に for ループの本体に、instalWow() 関数 ast の関数定義本体を挿入し、変数名を一致させます。次に、単にast 自体で exec を呼び出し、適切な変数が入力された名前空間ディクショナリを提供します。ツリーの変更が正しいことを確認するには、astunparseを実行して最終的なソース コードがどのようになるかを確認できます。

それだけでは不十分な場合は、cython に移動して .pyx ファイルを作成できます。これにより、.c ファイルが生成され、Python バインディングを使用してライブラリにコンパイルされます。そうすれば、少なくとも失われたサイクルは、Python オブジェクトとの間の変換や、繰り返しすべての型チェックに費やされることはありません。

于 2016-05-23T19:42:50.627 に答える
1

最初に for ループをメモリを割り当てないジェネレーター式として書き直します。

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

しかし、この表現は、それを消費する何らかの方法を見つけなければ、実際には何もしません。Noneしたがって、可能性のあるの結果に頼るのではなく、これを書き直して何か決定的なものを生成することができinstallWowます。

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

これはリストを作成しますが、定数 1 のみを返します。これは次のように便利に消費できますreduce

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

これは、影響を受けた wowList 内のアイテムの数を便利に返します。

于 2009-07-03T18:00:03.337 に答える
0

誰かが答える必要があります --

ここでのよりpythonicな方法は、名前空間を汚染することを心配せず__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']
于 2018-12-19T15:39:04.937 に答える