web-dev-qa-db-ja.com

IF条件で変数を割り当てて、それを返す方法は?

def isBig(x):
   if x > 4: 
       return 'Apple'
   else: 
       return 'orange'

これは機能します:

if isBig(y): return isBig(y)

これは動作しません:

if fruit = isBig(y): return fruit

2つ目が機能しないのはなぜですか!? 1ライナーが欲しいです。ただし、最初の関数はTWICEを呼び出します。

関数を2回呼び出さずに、1つのライナーにする方法は?

16
TIMEX

他の誰かが私の古い「割り当てと設定」クックブックレシピをすでに指摘しているのがわかります。これは、最も単純なバージョンでは次のように要約されます。

class Holder(object):
   def set(self, value):
     self.value = value
     return value
   def get(self):
     return self.value

h = Holder()

...

if h.set(isBig(y)): return h.get()

ただし、これは主に、Pythonと割り当てがifまたはwhileで直接サポートされている言語との間の音訳を容易にすることを目的としていました。カスケードでのチェックアンドリターン、それははるかに完全に異なることをする方が良いです:

hundreds = isBig, isSmall, isJuicy, isBlah, ...

for predicate in hundreds:
  result = predicate(y)
  if result: return result

またはのようなもの

return next(x for x in (f(y) for f in hundreds) if x)

述語が満たされない場合にStopIteration例外を取得しても問題がない場合、または

return next((x for x in (f(y) for f in hundreds) if x)), None)

Noneが、述語が満たされない場合の適切な戻り値である場合など。

ほとんどの場合、Holderトリック/非イディオムを使用する(または希望する)ことは、別のよりPythonicなアプローチを探すことを示唆する「デザインの匂い」です-Holderが正当化されるのは、まさに私が設計した特殊なケースです。つまり、PythonコードとPython以外のコード(音訳している)の間で密接な対応を維持したい場合です。 Pythonの参照アルゴリズムで、よりPythonの形式にリファクタリングする前に最初に動作させたい、またはPythonに音訳されるプロトタイプとして記述している) C++、C#、Javaなど、効果的に機能するようになったら)。

16
Alex Martelli

_Python 3.8_から始まり、 代入式(PEP 572) (_:=_演算子)の導入により、条件値(isBig(y))をキャプチャできるようになりました。条件の本体内で再利用するための変数(x)として:

_if x := isBig(y): return x
_
29
Xavier Guihot

Pythonでは、代入(fruit = isBig(y))は式ではなくステートメントであるため、ワンライナーは機能しません。 C、C++、Perl、およびその他の無数の言語では、これは式であり、ifまたはwhileなど、好きなものに入れることができますが、Pythonではできません。 of Pythonこれは(あなたがしようとしているように)「賢い」コードを書くにはあまりにも簡単に誤用(または悪用)されたと考えました。

また、あなたの例はかなりばかげています。 isBig()は常にtrueと評価されます。これは、falseの文字列は空の文字列("")なので、この場合、ifステートメントは役に立ちません。私はそれがあなたがやろうとしていることの単なる単純化だと思います。これを行うだけです:

tmp = isBig(y)
if tmp: return tmp

それは本当にもっと悪いですか?

9
Chris Lutz

PHP(またはC)でコーディングする場合は、コーディングします。メソッドを別の言語に強制しようとしないでください。

Python(私の意見では)の背後にある基本的な信条の1つは、その読みやすさです。次を使用する必要があります。

_fruit = isBig(y)
if fruit: return fruit
_

また、isXXX()の使用は非常に奇妙です。通常、ブール値を返すために使用されます。特に、IFステートメントで使用しているこの場合。

2
paxdiablo

これは意図的な言語設計のために機能しませんが、 このトリック を使用してこの決定を回避することができます

0
Boris Gorelik

問題は、割り当て操作がブール値を持っていると評価できないことです。 ifステートメントは、ブール値を評価できることに依存しています。例えば、

>>> fruit = 'Apple'
>>> bool(fruit = 'Apple')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/Users/jem/<ipython console> in <module>()

TypeError: 'fruit' is an invalid keyword argument for this function
>>> bool('a')
True
0
Peter

ジェネレーターを使用できます。

def ensure(x):
    if x: yield x

for fruit in ensure(isBig(y)):
    return fruit
0
max