104

オプションのパラメータの値がデフォルト値から来ているのか、それともユーザーが関数呼び出しで明示的に設定したのかを確認する簡単な方法はありますか?

4

10 に答える 10

64

あまり。標準的な方法は、ユーザーが渡すことを期待されないデフォルト値を使用することです。object例:インスタンス:

DEFAULT = object()
def foo(param=DEFAULT):
    if param is DEFAULT:
        ...

通常None、ユーザーが渡したい値として意味がない場合は、デフォルト値として使用できます。

別の方法は、以下を使用することkwargsです。

def foo(**kwargs):
    if 'param' in kwargs:
        param = kwargs['param']
    else:
        ...

ただし、これは非常に冗長であり、ドキュメントにパラメータが自動的に含まれないため、関数の使用がより困難になりparamます。

于 2013-02-07T10:54:58.347 に答える
16

次の関数デコレータ はexplicit_checker、明示的に指定されたすべてのパラメータのパラメータ名のセットを作成します。結果を追加パラメーター ( explicit_params) として関数に追加します。'a' in explicit_paramsパラメータaが明示的に指定されているかどうかを確認するだけです。

def explicit_checker(f):
    varnames = f.func_code.co_varnames
    def wrapper(*a, **kw):
        kw['explicit_params'] = set(list(varnames[:len(a)]) + kw.keys())
        return f(*a, **kw)
    return wrapper

@explicit_checker
def my_function(a, b=0, c=1, explicit_params=None):
    print a, b, c, explicit_params
    if 'b' in explicit_params:
        pass # Do whatever you want


my_function(1)
my_function(1, 0)
my_function(1, c=1)
于 2013-02-07T11:23:29.883 に答える
5

普遍的に一意の文字列 (UUID など) を使用することがあります。

import uuid
DEFAULT = uuid.uuid4()
def foo(arg=DEFAULT):
  if arg is DEFAULT:
    # it was not passed in
  else:
    # it was passed in

このように、ユーザーが試みたとしてもデフォルトを推測することさえできなかったので、 のその値を見るとarg、それが渡されなかったと確信できます。

于 2015-10-15T21:54:08.187 に答える
5

私はこのパターンを数回見ました (例: library unittestpy-flagsjinja):

class Default:
    def __repr__( self ):
        return "DEFAULT"

DEFAULT = Default()

...または同等のワンライナー...:

DEFAULT = type( 'Default', (), { '__repr__': lambda x: 'DEFAULT' } )()

とは異なりDEFAULT = object()、これは型チェックを支援し、エラーが発生したときに情報を提供します。多くの場合、文字列表現 ( "DEFAULT") またはクラス名 ( "Default") がエラー メッセージで使用されます。

于 2017-12-08T11:20:05.253 に答える
4

ボラティリティのコメントに同意します。ただし、次の方法で確認できます。

def function(arg1,...,**optional):
    if 'optional_arg' in optional:
        # user has set 'optional_arg'
    else:
        # user has not set 'optional_arg'
        optional['optional_arg'] = optional_arg_default_value # set default
于 2013-02-07T10:56:42.287 に答える
1

少し変わったアプローチは次のとおりです。

class CheckerFunction(object):
    def __init__(self, function, **defaults):
        self.function = function
        self.defaults = defaults

    def __call__(self, **kwargs):
        for key in self.defaults:
            if(key in kwargs):
                if(kwargs[key] == self.defaults[key]):
                    print 'passed default'
                else:
                    print 'passed different'
            else:
                print 'not passed'
                kwargs[key] = self.defaults[key]

        return self.function(**kwargs)

def f(a):
    print a

check_f = CheckerFunction(f, a='z')
check_f(a='z')
check_f(a='b')
check_f()

どの出力:

passed default
z
passed different
b
not passed
z

前述したように、これは非常に奇妙ですが、うまく機能します。ただし、これは非常に読みにくく、 ecatmur提案と同様に、自動的に文書化されません。

于 2013-02-07T11:14:36.673 に答える