web-dev-qa-db-ja.com

Pythonで変数のタイプをアサートする適切な方法

関数を使用する際、変数の型が期待どおりであることを確認したいと思います。正しい方法は?

以下に、ロールを実行する前にこれを実行しようとするフェイク関数の例を示します。

def my_print(begin, text, end):
    """Print 'text' in UPPER between 'begin' and 'end' in lower

    """
    for i in (begin, text, end):
        assert isinstance(i, str), "Input variables should be strings"
    out = begin.lower() + text.upper() + end.lower()
    print out

def test():
    """Put your test cases here!

    """
    assert my_print("asdf", "fssfpoie", "fsodf")
    assert not my_print("fasdf", 33, "adfas")
    print "All tests passed"

test()

アサートは正しいアプローチですか?代わりにtry/exceptを使用する必要がありますか?

また、テストのアサートセットが正しく動作しないようです:S

おかげでpythoneers

56
Morlock

isinstance ビルトインは、本当に必要な場合に推奨される方法ですが、Pythonのモットーである「許可よりも赦しを求める方が簡単です」を覚えておくことです。実際にグレース・マレー・ホッパーのお気に入りのモットー;-)。つまり:

def my_print(text, begin, end):
    "Print 'text' in UPPER between 'begin' and 'end' in lower"
    try:
      print begin.lower() + text.upper() + end.lower()
    except (AttributeError, TypeError):
      raise AssertionError('Input variables should be strings')

BTWを使用すると、関数はUnicode文字列で問題なく動作します-余分な労力なしで!-)

52
Alex Martelli

Pythonのバージョン2.6でこの例を試してみてください。

def my_print(text, begin, end):
    "Print text in UPPER between 'begin' and 'end' in lower."
    for obj in (text, begin, end):
        assert isinstance(obj, str), 'Argument of wrong type!'
    print begin.lower() + begin.upper() + end.lower()

ただし、代わりに関数を自然に失敗させることを検討しましたか?

12
Noctis Skytower

type('')を実行することは、strおよび_types.StringType_と実質的に同等です。

type('') == str == types.StringTypeは「True」と評価されます

この方法で型をチェックすると、ASCIIのみを含むUnicode文字列が失敗することに注意してください。したがって、assert type(s) in (str, unicode)またはassert isinstance(obj, basestring))後者は007Brendanによるコメントで提案されており、おそらく好まれます。

isinstance()は、オブジェクトがクラスのインスタンスであるかどうかを確認する場合に役立ちます。例:

_class MyClass: pass

print isinstance(MyClass(), MyClass) # -> True
print isinstance(MyClass, MyClass()) # -> TypeError exception
_

しかし、基本タイプの場合、例えばstrunicodeintfloatlongなどtype(var) == TYPEを要求しても問題ありません。

7
cryo