5

Rubyで面白い表現に出くわしました。

a ||= "new"

これは、aが定義されていない場合、「新しい」値がaに割り当てられることを意味します。それ以外の場合、aはそのままになります。DBクエリを実行するときに便利です。値が設定されている場合、別のDBクエリを実行したくありません。

そこで、Pythonで同様の考え方を試しました。

a = a if a is not None else "new"

失敗しました。aが定義されていないとPythonで「a=a」ができないからだと思います。

したがって、私が出てくる解決策は、locals()とglobals()をチェックするか、try...を使用することです。

myVar = myVar if 'myVar' in locals() and 'myVar' in globals() else "new"

また

try:
    myVar
except NameError:
    myVar = None

myVar = myVar if myVar else "new"

ご覧のとおり、ソリューションはそれほどエレガントではありません。質問したいのですが、これを行うためのより良い方法はありますか?

4

6 に答える 6

5

未定義の変数を「デフォルト」として使用するのは、ちょっとしたコードの臭いです。あなたが発見したように、それはあなたがまだ存在していないならあなたがすることができないので失敗しますa = a。変数をデフォルト値(Noneなど)で初期化してから、それを確認することをお勧めします。だからあなたはほとんど解決策を見つけました。唯一のことは、変数を初期化せずに「存在しない」を「欠落」値として使用しようとするのではなく、明示的に初期化する必要があるということです。したがって、これを行う代わりに:

 # code with no initialization. . .
 a ||= blah

これを行う:

a = None
# code
if a is None:
    a = blah
于 2012-07-20T07:15:23.063 に答える
3

どうですか?

try:
    a = a
except NameError:
    a = "new"

それほど短くはありませんが、コードの意図を明確に(少なくとも私には)説明しています。

于 2012-07-20T07:40:19.523 に答える
1

この動作が本当に必要な場合は、Pythonでdict、例:を使用するのが最適ですd.get('a', 'new')globals()つまり、 /をいじくり回すことができますlocals()get('a', 'new')、しかし、それは一般的にPythonで物事を行う方法ではありません-ある種の番兵値(などNone)であっても、各名前バインディングには初期値が必要です。

globals()とsetdefault()を使用した恐ろしい例

>>> a
Traceback (most recent call last):
  File "<pyshell#66>", line 1, in <module>
    a
NameError: name 'a' is not defined
>>> globals().setdefault('a', 'new')
'new'
>>> a
'new'
>>> a = 'old'
>>> globals().setdefault('a', 'new')
'old'
>>> a
'old'
于 2012-07-20T07:22:35.827 に答える
1

Pythonicは、それがどこにあるかを推測するのではなく、特にローカル/グローバル変数で使用する前に知っておく必要があるということです。このコードを書くことはできますが、pythonicではありません

a = None
# other codes
a = a or 'new'

大丈夫です

于 2012-07-20T09:08:27.857 に答える
1

かなりPythonicなメモ化の使用を検討してください。Python2のコードは次のとおりです。

# Backport of Python 3's lru_cache
# pip install functools32
from functools32 import lru_cache

@lru_cache()
def expensive_db_query(arg):
    print "Running expensive db query for", arg
    return arg[::-1]

expensive_db_query("spam") # prints "Running expensive db query for spam"
expensive_db_query("spam") # No output
expensive_db_query("eggs") # prints "Running expensive db query for eggs"

十分な時間が経過した後にキャッシュに値を忘れさせ、データベースに再度クエリを実行する場合は、Ilialukのlruキャッシュを確認してください。

于 2014-03-17T16:28:41.613 に答える
0

変数が定義されているかどうかを確認する方法について、この回答に触発されたバリアントを次に示します。

a = a if "a" in vars() or "a" in globals() else "new"

それほど短くはありませんが、少なくとも1行です。

In [1]: a
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-60b725f10c9c> in <module>()
----> 1 a

NameError: name 'a' is not defined

In [2]: a = a if "a" in vars() or "a" in globals() else "new"

In [3]: a
Out[3]: 'new'

In [4]: a = "A exists!"

In [5]: a = a if "a" in vars() or "a" in globals() else "new"

In [6]: a
Out[6]: 'A exists!'

とは言うものの、私はBrenBarnに同意します。未定義の変数の問題は、a=None設定できない可能性のあるブロックの前で宣言するだけで回避できるはずです。

于 2017-11-30T10:01:15.280 に答える