3

いくつかのオプションのパラメーターを持つメソッドがあるとしましょう。

def foo(a, b=1, c=2, d=3)

変数が None または空の文字列の場合にデフォルトが使用されるように呼び出すにはどうすればよいですか?

次のような条件は恐ろしい解決策のようです。

if b and not c and d:
    foo(myA, b = myB, d = myD)
elif b and not c and not d:
    ...

Java では、ファクトリにジャンプしますが、この場合、デフォルトで回避する必要があるようです。

4

5 に答える 5

7

foo空の値をデフォルトの値に置き換えるように 変更します。

def foo(a, b=None, c=None, d=None):
    if not b: b = 1
    if not c: c = 2
    if not d: d = 3

これにより、すべての「false-y」値がデフォルトとして扱われることに注意してください。つまり、Noneandだけで''なく0False[]なども意味します。個人的には、インターフェイスを強化して、Noneand のみNoneをデフォルト値として使用します。

def foo(a, b=None, c=None, d=None):
    if b is None: b = 1
    if c is None: c = 2
    if d is None: d = 3
于 2013-08-26T21:49:51.347 に答える
3

メソッドを変更する方が良いという意見には同意しますが、引数の を使用して呼び出し部分を変更する代替手段をdict次に示します。これはフィルター処理されてからアンパックされます。

d = {'b': myB, 'd': myD}
foo(myA, **{k: d[k] for k in d if d[k]})

もちろん、たとえば、わずかに異なる意味を持つ (他の人が指摘したように)if d[k]に置き換えることができます。if d[k] not in {None, ''}

于 2013-08-26T22:00:33.000 に答える
2

Noneのみをキャッチしたい場合''

def foo(a, b, c, d):
    blacklist = set([None, ''])
    if b in blacklist:
        b = 1
    if c in blacklist:
        c = 2
    if d in blacklist:
        d = 3

であるようなすべての値 v をキャッチしたい場合bool(v)False、次のようにします。

def foo(a, b, c, d):
    b = b or 1
    c = c or 2
    d = d or 3

または、アサーションを実行する別の関数で関数を装飾することもできます (ユースケースに基づいて、やり過ぎである場合とそうでない場合があります)。

于 2013-08-26T21:50:21.507 に答える
1

完全にはテストされていませんが、ベースとして機能する必要があります。

import inspect
from functools import wraps

def force_default(f):
    @wraps(f)
    def func(*args, **kwargs):
        ca = inspect.getcallargs(f, *args, **kwargs)
        da = inspect.getargspec(f)
        dv = dict(zip(reversed(da.args), reversed(da.defaults)))
        for k, v in ca.iteritems():
            if v is None or v == '':
                ca[k] = dv[k]
        return f(**ca)
    return func

@force_default
def foo(a, b=1, c=2, d=3):
    print a, b, c, d

foo(6, '', None, 'rabbit!')
# 6 1 2 rabbit!
于 2013-08-26T22:27:22.317 に答える