0

私はpython noobであり、「pythonic」の方法で問題を解決しようとしています。__init__メソッドが6つのパラメーターを取るクラスがあります。各パラメーターを検証し、検証に失敗した場合は例外をスロー/発生させる必要があります。

これは正しい方法ですか?

class DefinitionRunner:
    def __init__(self, canvasSize, flightId, domain, definitionPath, harPath):
        self.canvasSize = canvasSize
        self.flightId   = flightId
        self.domain     = domain
        self.harPath    = harPath
        self.definitionPath = definitionPath

        ... bunch of validation checks...
        ... if fails, raise ValueError ...
4

5 に答える 5

3

変数を とは別に設定できるようにする場合は、プロパティ__init__を使用して別のメソッドで検証を実装できます。

ただし、これらは新しいスタイル クラスに対してのみ機能するため、クラスを次のように定義する必要があります。class DefinitionRunner(object)

たとえば、

    @property
    def canvasSize(self):
        return self._canvasSize

    @canvasSize.setter
    def canvasSize(self, value):
        # some validation here
        self._canvasSize = value
于 2013-01-23T20:12:21.633 に答える
1

これが正確に「Pythonic」であるかどうかはわかりませんが、require_typeという関数デコレータを定義しました。(正直なところ、オンラインのどこかで見つけたと思います。)

def require_type(my_arg, *valid_types):
'''
    A simple decorator that performs type checking.

    @param my_arg: string indicating argument name
    @param valid_types: list of valid types
'''
def make_wrapper(func):
    if hasattr(func, 'wrapped_args'):
        wrapped = getattr(func, 'wrapped_args')
    else:
        body = func.func_code
        wrapped = list(body.co_varnames[:body.co_argcount])

    try:
        idx = wrapped.index(my_arg)
    except ValueError:
        raise(NameError, my_arg)

    def wrapper(*args, **kwargs):

        def fail():
            all_types = ', '.join(str(typ) for typ in valid_types)
            raise(TypeError, '\'%s\' was type %s, expected to be in following list: %s' % (my_arg, all_types, type(arg)))

        if len(args) > idx:
            arg = args[idx]
            if not isinstance(arg, valid_types):
                fail()
        else:
            if my_arg in kwargs:
                arg = kwargs[my_arg]
                if not isinstance(arg, valid_types):
                    fail()

        return func(*args, **kwargs)

    wrapper.wrapped_args = wrapped
    return wrapper
return make_wrapper

次に、それを使用するには:

class SomeObject(object):

    @require_type("prop1", str)
    @require_type("prop2", numpy.complex128)
    def __init__(self, prop1, prop2):
        pass
于 2013-01-23T22:25:03.860 に答える
1

私はあなたがしたようにそれをします。検証のものを除いて。セッター メソッドで検証し、それを使用して属性を設定します。

于 2013-01-23T20:11:30.790 に答える
1

大まかに言えば、それはあなたのやり方のように見えます。厳密に言えば、特に割り当てが時間やリソースを大量に消費する可能性がある場合は、割り当ての後ではなく、割り当ての前に検証を行った方がよいでしょう。また、スタイルの規則では、あなたのように割り当てブロックを整列させないように言っています。

于 2013-01-23T20:09:20.550 に答える
1

このようなことができます。入力の種類ごとにバリデーターを作成します。検証を実行するヘルパー関数を作成します。

def validate_and_assign(obj, items_d, validators):
    #validate all entries
    for key, validator in validators.items():
        if not validator[key](items_d[key]):
            raise ValueError("Validation for %s failed" % (key,))

    #set all entries
    for key, val in items_d.items():
        setattr(obj, key, val)

次のように使用します。

class DefinitionRunner:
    validators = {
        'canvasSize': canvasSize_validator,
        'flightId': flightId_validator,
        'domain': domain_validator,
        'definitionPath': definitionPath_validator,
        'harPath': harPath_validator,
    }

    def __init__(self, canvasSize, flightId, domain, definitionPath, harPath):
        validate_and_assign(self, {
            'canvasSize': canvasSize,
            'flightId': flightId,
            'domain': domain,
            'definitionPath': definitionPath,
            'harPath': harPath,
        }, DefinitionRunner.validators) 

もちろん、データ型が同じであれば、バリデーターは同じ関数である可能性があります。

于 2013-01-23T20:26:18.913 に答える