有没有一种简单的方法来确定变量是列表、字典还是其他什么?
当前回答
在许多实际情况下,您也可以使用@functools.singledispatch来定义泛型函数(由多个函数组成的函数,对不同类型执行相同的操作),而不是使用类型或isinstance。
换句话说,当您有如下代码时,您可能希望使用它:
def do_something(arg):
if isinstance(arg, int):
... # some code specific to processing integers
if isinstance(arg, str):
... # some code specific to processing strings
if isinstance(arg, list):
... # some code specific to processing lists
... # etc
下面是一个工作原理的小示例:
from functools import singledispatch
@singledispatch
def say_type(arg):
raise NotImplementedError(f"I don't work with {type(arg)}")
@say_type.register
def _(arg: int):
print(f"{arg} is an integer")
@say_type.register
def _(arg: bool):
print(f"{arg} is a boolean")
>>> say_type(0)
0 is an integer
>>> say_type(False)
False is a boolean
>>> say_type(dict())
# long error traceback ending with:
NotImplementedError: I don't work with <class 'dict'>
此外,我们可以使用抽象类同时覆盖几种类型:
from collections.abc import Sequence
@say_type.register
def _(arg: Sequence):
print(f"{arg} is a sequence!")
>>> say_type([0, 1, 2])
[0, 1, 2] is a sequence!
>>> say_type((1, 2, 3))
(1, 2, 3) is a sequence!
其他回答
在许多实际情况下,您也可以使用@functools.singledispatch来定义泛型函数(由多个函数组成的函数,对不同类型执行相同的操作),而不是使用类型或isinstance。
换句话说,当您有如下代码时,您可能希望使用它:
def do_something(arg):
if isinstance(arg, int):
... # some code specific to processing integers
if isinstance(arg, str):
... # some code specific to processing strings
if isinstance(arg, list):
... # some code specific to processing lists
... # etc
下面是一个工作原理的小示例:
from functools import singledispatch
@singledispatch
def say_type(arg):
raise NotImplementedError(f"I don't work with {type(arg)}")
@say_type.register
def _(arg: int):
print(f"{arg} is an integer")
@say_type.register
def _(arg: bool):
print(f"{arg} is a boolean")
>>> say_type(0)
0 is an integer
>>> say_type(False)
False is a boolean
>>> say_type(dict())
# long error traceback ending with:
NotImplementedError: I don't work with <class 'dict'>
此外,我们可以使用抽象类同时覆盖几种类型:
from collections.abc import Sequence
@say_type.register
def _(arg: Sequence):
print(f"{arg} is a sequence!")
>>> say_type([0, 1, 2])
[0, 1, 2] is a sequence!
>>> say_type((1, 2, 3))
(1, 2, 3) is a sequence!
通常,您可以从具有类名的对象中提取字符串,
str_class = object.__class__.__name__
并将其用于比较,
if str_class == 'dict':
# blablabla..
elif str_class == 'customclass':
# blebleble..
type()是比isinstance()更好的解决方案,尤其是对于布尔值:
True和False只是python中表示1和0的关键字。因此
isinstance(True, int)
and
isinstance(False, int)
两者都返回True。两个布尔值都是整数的实例。然而,type()更聪明:
type(True) == int
返回False。
小心使用isinstance
isinstance(True, bool)
True
>>> isinstance(True, int)
True
但类型
type(True) == bool
True
>>> type(True) == int
False
确定Python对象的类型
使用类型确定对象的类型
>>> obj = object()
>>> type(obj)
<class 'object'>
虽然它有效,但避免使用__class__之类的双下划线属性-它们在语义上不是公共的,虽然在这种情况下可能不是,但内置函数通常具有更好的行为。
>>> obj.__class__ # avoid this!
<class 'object'>
类型检查
有没有一种简单的方法来确定变量是列表、字典还是其他什么?我得到了一个可能是这两种类型的对象,我需要能够分辨出其中的区别。
好吧,这是另一个问题,不要使用类型-用法:
def foo(obj):
"""given a string with items separated by spaces,
or a list or tuple,
do something sensible
"""
if isinstance(obj, str):
obj = str.split()
return _foo_handles_only_lists_or_tuples(obj)
这涵盖了这样一种情况,即您的用户可能正在通过子类化str来做一些聪明或明智的事情-根据Liskov Substitution的原理,您希望能够在不破坏代码的情况下使用子类实例-而isinstance支持这一点。
使用摘要
更好的是,您可以从集合或数字中查找特定的抽象基类:
from collections import Iterable
from numbers import Number
def bar(obj):
"""does something sensible with an iterable of numbers,
or just one number
"""
if isinstance(obj, Number): # make it a 1-tuple
obj = (obj,)
if not isinstance(obj, Iterable):
raise TypeError('obj must be either a number or iterable of numbers')
return _bar_sensible_with_iterable(obj)
或只是不显式键入检查
或者,也许最棒的是,使用duck类型,不要显式地检查代码类型。Duck类型支持Liskov替换,更优雅,更少冗长。
def baz(obj):
"""given an obj, a dict (or anything with an .items method)
do something sensible with each key-value pair
"""
for key, value in obj.items():
_baz_something_sensible(key, value)
结论
使用类型实际获取实例的类。使用isinstance显式检查实际的子类或注册的抽象。只要在有意义的地方避免类型检查。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录