问题:在Python中检查类型的规范方法是什么?
检查给定对象是否为给定类型的最佳方法是什么?如何检查对象是否从给定类型继承?
假设我有一个对象o
。如何检查是否是str
?
What is the best way to check whether a given object is of a given type? How about checking whether the object inherits from a given type?
Let’s say I have an object o
. How do I check whether it’s a str
?
回答 0
要检查o
是的实例str
还是的任何子类str
,请使用isinstance(这是“规范”的方式):
if isinstance(o, str):
要检查的类型o
是否准确str
(排除子类):
if type(o) is str:
以下内容也可以使用,并且在某些情况下可能有用:
if issubclass(type(o), str):
有关相关信息,请参见Python库参考中的内置函数。
还有一点要注意:在这种情况下,如果您使用的是Python 2,则实际上可能要使用:
if isinstance(o, basestring):
因为这也将赶上Unicode字符串(unicode
不是的子类str
,这两个str
和unicode
是的子类basestring
)。请注意,basestring
在Python 3中不再存在,在Python 3中,字符串()和二进制数据()严格分开。str
bytes
或者,isinstance
接受一个类的元组。True
如果o
是以下任何一个的任何子类的实例,则将返回(str, unicode)
:
if isinstance(o, (str, unicode)):
To check if o
is an instance of str
or any subclass of str
, use isinstance (this would be the “canonical” way):
if isinstance(o, str):
To check if the type of o
is exactly str
(exclude subclasses):
if type(o) is str:
The following also works, and can be useful in some cases:
if issubclass(type(o), str):
See Built-in Functions in the Python Library Reference for relevant information.
One more note: in this case, if you’re using Python 2, you may actually want to use:
if isinstance(o, basestring):
because this will also catch Unicode strings (unicode
is not a subclass of str
; both str
and unicode
are subclasses of basestring
). Note that basestring
no longer exists in Python 3, where there’s a strict separation of strings (str
) and binary data (bytes
).
Alternatively, isinstance
accepts a tuple of classes. This will return True
if o
is an instance of any subclass of any of (str, unicode)
:
if isinstance(o, (str, unicode)):
回答 1
检查对象类型的最 Pythonic方法是…不检查它。
由于Python鼓励使用Duck Typing,因此您应该只try...except
使用对象的方法来使用它们。因此,如果您的函数正在寻找可写文件对象,则不要检查它是否是的子类file
,只需尝试使用其.write()
方法即可!
当然,有时这些漂亮的抽象会分解,isinstance(obj, cls)
这正是您所需要的。但是要谨慎使用。
The most Pythonic way to check the type of an object is… not to check it.
Since Python encourages Duck Typing, you should just try...except
to use the object’s methods the way you want to use them. So if your function is looking for a writable file object, don’t check that it’s a subclass of file
, just try to use its .write()
method!
Of course, sometimes these nice abstractions break down and isinstance(obj, cls)
is what you need. But use sparingly.
回答 2
isinstance(o, str)
True
如果o
是str
或继承自的类型,则将返回str
。
type(o) is str
True
当且仅当o
是str时将返回。False
如果o
是继承自的类型,它将返回str
。
isinstance(o, str)
will return True
if o
is an str
or is of a type that inherits from str
.
type(o) is str
will return True
if and only if o
is a str. It will return False
if o
is of a type that inherits from str
.
回答 3
在询问并回答问题之后,将类型提示添加到Python中。Python中的类型提示允许检查类型,但与静态类型的语言完全不同。Python中的类型提示将期望的参数类型与函数关联,作为与函数关联的运行时可访问的数据,这允许检查类型。类型提示语法的示例:
def foo(i: int):
return i
foo(5)
foo('oops')
在这种情况下,我们希望触发错误,foo('oops')
因为参数的带注释类型为int
。正常运行脚本时,添加的类型提示不会导致发生错误。但是,它向函数添加了属性,这些属性描述了其他程序可以查询并用于检查类型错误的预期类型。
可以用来查找类型错误的其他程序之一是mypy
:
mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
(您可能需要mypy
从软件包管理器进行安装。我不认为CPython附带了该软件包,但似乎具有一定的“正式性”。)
这种方式的类型检查不同于静态类型的编译语言中的类型检查。由于类型在Python中是动态的,因此类型检查必须在运行时完成,如果我们坚持要千方百计地进行,则即使在正确的程序上也要付出代价。显式类型检查也可能比需要的限制更严格,并且会导致不必要的错误(例如,参数是否确实需要精确地list
类型或可迭代的内容是否足够?)。
显式类型检查的好处在于,与鸭子输入相比,它可以更早地捕获错误并给出更清晰的错误消息。鸭子类型的确切要求只能用外部文档来表达(希望它是彻底而准确的),并且不兼容类型的错误可能发生在它们起源的地方。
Python的类型提示旨在提供一种折衷方案,可以在其中指定和检查类型,但在常规代码执行过程中不会增加任何成本。
本typing
可以在类型提示使用配套优惠类型变量来表达需要的行为,而不需要特定类型。例如,它包含诸如Iterable
和的变量,Callable
用于提示是否需要具有这些行为的任何类型。
尽管类型提示是检查类型的最Pythonic方式,但通常甚至根本不检查类型并依赖于鸭子类型甚至更像Pythonic。类型提示是相对较新的,并且在它们是最Pythonic的解决方案时还没有定论。相对无争议的但非常笼统的比较:类型提示提供了一种可以强制执行的文档形式,允许代码生成更早且更容易理解的错误,可以捕获鸭子输入不能的错误,并且可以静态检查(在不寻常的情况下)感觉,但它仍在运行时之外)。另一方面,鸭子类型很长一段时间以来一直是Python的方式,不会增加静态类型的认知开销,不那么冗长,并且会接受所有可行的类型,然后接受某些类型。
After the question was asked and answered, type hints were added to Python. Type hints in Python allow types to be checked but in a very different way from statically typed languages. Type hints in Python associate the expected types of arguments with functions as runtime accessible data associated with functions and this allows for types to be checked. Example of type hint syntax:
def foo(i: int):
return i
foo(5)
foo('oops')
In this case we want an error to be triggered for foo('oops')
since the annotated type of the argument is int
. The added type hint does not cause an error to occur when the script is run normally. However, it adds attributes to the function describing the expected types that other programs can query and use to check for type errors.
One of these other programs that can be used to find the type error is mypy
:
mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
(You might need to install mypy
from your package manager. I don’t think it comes with CPython but seems to have some level of “officialness”.)
Type checking this way is different from type checking in statically typed compiled languages. Because types are dynamic in Python, type checking must be done at runtime, which imposes a cost — even on correct programs — if we insist that it happen at every chance. Explicit type checks may also be more restrictive than needed and cause unnecessary errors (e.g. does the argument really need to be of exactly list
type or is anything iterable sufficient?).
The upside of explicit type checking is that it can catch errors earlier and give clearer error messages than duck typing. The exact requirements of a duck type can only be expressed with external documentation (hopefully it’s thorough and accurate) and errors from incompatible types can occur far from where they originate.
Python’s type hints are meant to offer a compromise where types can be specified and checked but there is no additional cost during usual code execution.
The typing
package offers type variables that can be used in type hints to express needed behaviors without requiring particular types. For example, it includes variables such as Iterable
and Callable
for hints to specify the need for any type with those behaviors.
While type hints are the most Pythonic way to check types, it’s often even more Pythonic to not check types at all and rely on duck typing. Type hints are relatively new and the jury is still out on when they’re the most Pythonic solution. A relatively uncontroversial but very general comparison: Type hints provide a form of documentation that can be enforced, allow code to generate earlier and easier to understand errors, can catch errors that duck typing can’t, and can be checked statically (in an unusual sense but it’s still outside of runtime). On the other hand, duck typing has been the Pythonic way for a long time, doesn’t impose the cognitive overhead of static typing, is less verbose, and will accept all viable types and then some.
回答 4
这是一个为什么鸭式打字是邪恶的却不知道什么时候是危险的例子。例如:这是Python代码(可能省略适当的缩进),请注意,可以通过注意isinstance和issubclassof函数来避免这种情况,以确保当您真正需要鸭子时,不会炸弹。
class Bomb:
def __init__(self):
""
def talk(self):
self.explode()
def explode(self):
print "BOOM!, The bomb explodes."
class Duck:
def __init__(self):
""
def talk(self):
print "I am a duck, I will not blow up if you ask me to talk."
class Kid:
kids_duck = None
def __init__(self):
print "Kid comes around a corner and asks you for money so he could buy a duck."
def takeDuck(self, duck):
self.kids_duck = duck
print "The kid accepts the duck, and happily skips along"
def doYourThing(self):
print "The kid tries to get the duck to talk"
self.kids_duck.talk()
myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()
Here is an example why duck typing is evil without knowing when it is dangerous.
For instance: Here is the Python code (possibly omitting proper indenting), note that this
situation is avoidable by taking care of isinstance and issubclassof functions to make sure that when you really need a duck, you don’t get a bomb.
class Bomb:
def __init__(self):
""
def talk(self):
self.explode()
def explode(self):
print "BOOM!, The bomb explodes."
class Duck:
def __init__(self):
""
def talk(self):
print "I am a duck, I will not blow up if you ask me to talk."
class Kid:
kids_duck = None
def __init__(self):
print "Kid comes around a corner and asks you for money so he could buy a duck."
def takeDuck(self, duck):
self.kids_duck = duck
print "The kid accepts the duck, and happily skips along"
def doYourThing(self):
print "The kid tries to get the duck to talk"
self.kids_duck.talk()
myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()
回答 5
回答 6
我认为使用像Python这样的动态语言的很酷的事情是,您实际上不必检查类似的东西。
我只会在您的对象上调用所需的方法并捕获一个AttributeError
。稍后,这将允许您与其他(看似无关)对象一起调用您的方法以完成不同的任务,例如模拟对象进行测试。
当从网络上获取数据urllib2.urlopen()
并返回类似对象的文件时,我已经使用了很多。这又可以传递给几乎所有从文件读取的方法,因为它实现了相同的方法。read()
方法与真实文件。
但我确定会有时间和地点使用isinstance()
,否则可能不会存在:)
I think the cool thing about using a dynamic language like Python is you really shouldn’t have to check something like that.
I would just call the required methods on your object and catch an AttributeError
. Later on this will allow you to call your methods with other (seemingly unrelated) objects to accomplish different tasks, such as mocking an object for testing.
I’ve used this a lot when getting data off the web with urllib2.urlopen()
which returns a file like object. This can in turn can be passed to almost any method that reads from a file, because it implements the same read()
method as a real file.
But I’m sure there is a time and place for using isinstance()
, otherwise it probably wouldn’t be there :)
回答 7
对于更复杂的类型验证,我喜欢typeguard基于python类型提示注释的验证方法:
from typeguard import check_type
from typing import List
try:
check_type('mylist', [1, 2], List[int])
except TypeError as e:
print(e)
您可以以非常清晰易读的方式执行非常复杂的验证。
check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo)
For more complex type validations I like typeguard‘s approach of validating based on python type hint annotations:
from typeguard import check_type
from typing import List
try:
check_type('mylist', [1, 2], List[int])
except TypeError as e:
print(e)
You can perform very complex validations in very clean and readable fashion.
check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo)
回答 8
您可以使用类型的__name__检查变量的类型。
例如:
>>> a = [1,2,3,4]
>>> b = 1
>>> type(a).__name__
'list'
>>> type(a).__name__ == 'list'
True
>>> type(b).__name__ == 'list'
False
>>> type(b).__name__
'int'
You can check for type of a variable using __name__ of a type.
Ex:
>>> a = [1,2,3,4]
>>> b = 1
>>> type(a).__name__
'list'
>>> type(a).__name__ == 'list'
True
>>> type(b).__name__ == 'list'
False
>>> type(b).__name__
'int'
回答 9
前往雨果:
你可能是说list
而不是array
,但这指向类型检查的整个问题-您不想知道所讨论的对象是否是列表,您不想知道它是某种序列还是单个对象。因此,请尝试像序列一样使用它。
假设您要将对象添加到现有序列中,或者如果它是对象序列,则将它们全部添加
try:
my_sequence.extend(o)
except TypeError:
my_sequence.append(o)
一个技巧是,如果您正在处理字符串和/或字符串序列-这很棘手,因为字符串通常被认为是单个对象,但是它也是一个字符序列。更糟糕的是,因为它实际上是单长度字符串的序列。
我通常选择设计API,使其只接受一个值或一个序列-这样会使事情变得更容易。[ ]
如果需要,在传递单个值时并不难。
(尽管这可能会导致字符串错误,因为它们看起来确实像是序列)。
To Hugo:
You probably mean list
rather than array
, but that points to the whole problem with type checking – you don’t want to know if the object in question is a list, you want to know if it’s some kind of sequence or if it’s a single object. So try to use it like a sequence.
Say you want to add the object to an existing sequence, or if it’s a sequence of objects, add them all
try:
my_sequence.extend(o)
except TypeError:
my_sequence.append(o)
One trick with this is if you are working with strings and/or sequences of strings – that’s tricky, as a string is often thought of as a single object, but it’s also a sequence of characters. Worse than that, as it’s really a sequence of single-length strings.
I usually choose to design my API so that it only accepts either a single value or a sequence – it makes things easier. It’s not hard to put a [ ]
around your single value when you pass it in if need be.
(Though this can cause errors with strings, as they do look like (are) sequences.)
回答 10
一种检查类型的简单方法是将其与您知道类型的对象进行比较。
>>> a = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True
A simple way to check type is to compare it with something whose type you know.
>>> a = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True
回答 11
I think the best way is to typing well your variables. You can do this by using the “typing” library.
Example:
from typing import NewType
UserId = NewType ('UserId', int)
some_id = UserId (524313
)`
See https://docs.python.org/3/library/typing.html
回答 12
您可以检查以下行,以检查给定值是哪种字符类型:
def chr_type(chrx):
if chrx.isalpha()==True:
return 'alpha'
elif chrx.isdigit()==True:
return 'numeric'
else:
return 'nothing'
chr_type("12)
You can check with the below line to check which character type the given value is:
def chr_type(chrx):
if chrx.isalpha()==True:
return 'alpha'
elif chrx.isdigit()==True:
return 'numeric'
else:
return 'nothing'
chr_type("12)