2011-11-01 13 views
5

何年も前から、私はさまざまなビットとPythonの断片で「ワイルドカード」変数に気付きました。私はそれがHaskellのように機能していると仮定しました。仮パラメータに変数が必要な場所に変数を置くことができますが、バインドすることはできません。Pythonのワイルドカード?

私はこれを、変数のいずれかが必要でないときにタプルアンパックの代入の左側に使用しました。例えば

_, extension = os.path.splitext(filename) 

だから私は今日、これに類似した何かを書いた:

(lambda (x,_,_): x)((1,2,3)) 

すなわち、アンダースコアを2回バインドしようとしましたが、構文エラーが発生しました。

(lambda (x,_,z): _)((1,2,3)) 
> 2 

_ように見える他と同様に、単に変数名れる:私は_本当の変数が実際にあることを見て驚きました。

最初の例のように、私が好きなように使える真のワイルドカード変数がありますか(つまり、タプルのアンパック割り当てに複数の変数を使用できますか)?

答えて

4

Pythonにはワイルドカード変数はありません。

私は今やかなりの期間、人々が_を変数名として使用することを断念しようとしています。最初の人は_を特殊な構文の一部として誤解しているわけではないので、この種の混乱を避けるためには変数名として_を使用しない方が良いでしょう。 _をスローアウェイ変数名として使用する「慣習」があった場合、この規則は誤っていました。

混乱の原因となる以上の問題があります。たとえば、_は、インタラクティブなインタプリタと共通のgettextエイリアスで_と衝突します。

lambdaの式に関しては、lambda x, *args: ...を使用して、最初の引数を除くすべての引数を無視します。他のケースでは、私はdummyのような名前を使用したくないという明示的な名前を使用します。 range()のループの場合は、通常for i in range(n)を使用し、単にiを使用しないでください。

編集:私はちょうどあなたが注目引数リストに開梱タプルを使用します(他の回答を見て)、そのlambda x, *args: ...はあなたの問題を解決していません。パラメタリストのタプル展開は、Python 3.xでは削除されました。機能があまりにも不明瞭だと考えられたからです。代わりにmipadi's answerで行ってください。

3

いいえ、PythonにはHaskellの_と同等のものはありません。 Pythonの規約では、 "throwaway"変数に_を使用していますが、実際の変数名であり、見つかったように同じコンテキスト(lambdaパラメータリストなど)で2回使用することはできません。あなたが与えた例では

は、私はインデックスを使用したい:

lambda tup: tup[0] 

または

lambda tup: tup[1] 

としてきれいではありません

が、それを行うには良い方法の一つ。

1

短い答えはいいえ。あなたの既存の大会にちょうど従うことができます。つまり、

(lambda (x, _1, _2): x)((1,2,3)) 
3

実際はありません。 PythonはHaskellではありません。 map、apply、reduce、lambdaは第二級市民の一種ですが、itertoolsには面白いことがいくつかあります。あなたは1行のラムダを使用するためにいくつかの必要性がない限り

は、正しい方法はこれです:

def f(x, *args, **kwargs): 
    return x 

*args引数はあなたがargsと呼ばれるタプルとして利用できるようになります無名の任意の数の引数を(使用することができます)。追加の名前付き引数はkwargsという辞書にあります。

ラムダでこれを行う方法はありませんが、通常は必要ありません。関数宣言はどこにでも置くことができます。注意、あなたは別の関数(またはループ)内の関数定義を置けば面白い/悪なものを行う:

def make_func(s): 
    def f(*trash, **more_trash): 
     print s 
    return f 

f1 = make_func('hello') 
f2 = make_func('world') 
f1(1,2,'ham','spam') 
f2(1,2,a=1,b=2) 

意志出力:@rplntが指摘したように

>>> hello 
>>> world 

、これはできません

funcs = [] 
for s in ('hello','world'): 
    def f(): 
     print s 
    funcs.append(f) 

for f in funcs: 
    f() 

意志出力:

>>> world 
>>> world 
ループに対して同じループには名前空間が1つしかないため、

です。

+1

これはアンパック時にも機能します: '(a、* rest、b)= [1,2,3,4]' – rplnt

+1

また、ループには問題がありません彼ら自身の名前空間。 – rplnt

+0

また、ラムダで '*'と '**'を使うこともできます。 – kindall

2

それはちょっとしたトリックで、可能である:それはコードをよりエレガントになりので、

class _: 
    def __eq__(x,y): return true 
_=_() #always create a new _ instance if used, the class name itself is not needed anymore 

[(a,b) for (a,_,_,b) in [(1,2,3,4),(5,6,7,8)]] 

[(1, 4), (5, 8)] 

を与え、私は多くの場合、それを使用しています、 PythonでHaskellsの美しさの一部。