在Python中断言变量类型的正确方法

Mor*_*ock 57 python testing assert

在使用函数时,我希望确保变量的类型符合预期.怎么做对了?

这是一个假冒函数的示例,在继续其角色之前尝试执行此操作:

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()
Run Code Online (Sandbox Code Playgroud)

断言是正确的方法吗?我应该使用try/except吗?

此外,我的断言测试集似乎不能正常工作:S

谢谢pythoneers

Ale*_*lli 52

isinstance内置的是,如果你真的必须的首选方式,但更重要的是要记住Python的座右铭:"它更容易请求原谅比许可" - )(它实际上是格雷斯穆雷Hopper的喜欢的格言;-)!即:

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')
Run Code Online (Sandbox Code Playgroud)

这个,BTW,让函数在Unicode字符串上运行得很好 - 无需任何额外的努力! - )

  • `assert`有时对于你在开发阶段只需要的健全性检查很有用(不是在优化的生产代码中,它会被优化掉) - 所以,不要检查有效的输入(你必须这样做),但是健全性检查你自己的逻辑(循环变量,类不变量等) - 当然不是类型相关的.第三方测试框架py.test使用`assert`标准`unittest`使用`assertEqual`&c等方法. (6认同)
  • 如果参数是str或unicode类型,my_print函数应该不在乎; 它只关心参数有`lower()`,`upper()`和`__add __()`方法.这被称为鸭子打字(它看起来像一只鸭子,像鸭子一样说话(即相同的方法),即使它根本不是一个鸭子),它是python的首选方法.如果你要引发Exception,因为传入的参数类型错误,你应该引发一个`TypeError`. (5认同)
  • @ 007brendan,http://en.wikipedia.org/wiki/Duck_typing在历史上称我最早可追溯使用术语"鸭子打字"(10年前,当我是Python的原始初学者时)虽然如果你阅读他们指出的帖子,我实际上并没有_use_该帖子中的短语(我编写了许多鸭子类比,但大多使用更传统的术语,如"typeswitching") - 无论如何,我认为这让我合情合理熟悉这个概念;-).我同意类型错误是一个很好的匹配(try/except可以将属性错误,总是混合的东西,转换为类型错误). (3认同)

Noc*_*wer 12

您可能想要在2.6版本的Python中尝试此示例.

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()
Run Code Online (Sandbox Code Playgroud)

但是,您是否考虑过让这个功能自然失败?


Tim*_*mmm 12

isinstance(x, str) is best if you can use it, but it does not work with generics. For example you cannot do:

isinstance(x, dict[str, int])
Run Code Online (Sandbox Code Playgroud)

It will give a runtime error:

TypeError: isinstance() argument 2 cannot be a parameterized generic
Run Code Online (Sandbox Code Playgroud)

If you are only interested in asserting a type for a static type checker you can use cast:

TypeError: isinstance() argument 2 cannot be a parameterized generic
Run Code Online (Sandbox Code Playgroud)

Unlike isinstance() it doesn't actually do the type check so you have to check all of the keys and values yourself if necessary.

(我意识到这并不完全是您所要求的,但“类型断言”也用于指代类似的事物cast(),因此我避免了另一个会因重复而关闭的问题。)


cry*_*ryo 7

type('')有效地等同于strtypes.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
Run Code Online (Sandbox Code Playgroud)

但对于基本类型,例如str,unicode,int,float,long等询问,type(var) == TYPE将工作确定.

  • 你可以这样做 - assert isinstance(obj,basestring) - str和unicode都继承自basestring,所以这对两者都有效. (2认同)