Rei*_*ica 426 python types assert list
这是我通常做的,以确定输入是list/ tuple- 而不是a str.因为很多次我偶然发现函数str错误地传递了一个对象的bug ,而目标函数确实for x in lst假设它lst实际上是一个list或者tuple.
assert isinstance(lst, (list, tuple))
Run Code Online (Sandbox Code Playgroud)
我的问题是:有没有更好的方法来实现这一目标?
Nic*_*ood 326
仅在python 2中(不是python 3):
assert not isinstance(lst, basestring)
Run Code Online (Sandbox Code Playgroud)
实际上你想要的是什么,否则你会错过很多像列表一样的东西,但不是list或者的子类tuple.
ste*_*eha 170
请记住,在Python中我们想要使用"duck typing".因此,任何像列表一样的东西都可以被视为列表.因此,不要检查列表的类型,只要查看它是否像列表一样.
但字符串也像列表一样,而且往往不是我们想要的.有时甚至是一个问题!因此,请明确检查字符串,然后使用duck typing.
这是我写的一个有趣的功能.它是一个特殊版本,repr()用于在尖括号中打印任何序列('<','>').
def srepr(arg):
if isinstance(arg, basestring): # Python 3: isinstance(arg, str)
return repr(arg)
try:
return '<' + ", ".join(srepr(x) for x in arg) + '>'
except TypeError: # catch when for loop fails
return repr(arg) # not a sequence so just return repr
Run Code Online (Sandbox Code Playgroud)
总体来说,这是干净而优雅的.但那isinstance()检查是做什么的呢?那是一种黑客攻击.但这很重要.
此函数以递归方式调用自身,就像列表一样.如果我们没有特别处理字符串,那么它将被视为一个列表,并一次拆分一个字符.但是,递归调用会尝试将每个字符视为一个列表 - 它会起作用!即使是单字符字符串也可以作为列表使用!该函数将继续递归调用自身直到堆栈溢出.
像这样的函数,依赖于每个递归调用分解要完成的工作,必须使用特殊情况字符串 - 因为你不能分解低于单字符字符串级别的字符串,甚至一个字符串-character字符串就像一个列表.
注意:try/ except是表达我们意图的最简洁方式.但是如果这段代码在某种程度上是时间关键的,我们可能想用某种测试来替换它以查看是否arg是一个序列.我们应该测试行为,而不是测试类型.如果它有一个.strip()方法,那就是一个字符串,所以不要把它当成一个序列; 否则,如果它是可索引的或可迭代的,那么它是一个序列:
def is_sequence(arg):
return (not hasattr(arg, "strip") and
hasattr(arg, "__getitem__") or
hasattr(arg, "__iter__"))
def srepr(arg):
if is_sequence(arg):
return '<' + ", ".join(srepr(x) for x in arg) + '>'
return repr(arg)
Run Code Online (Sandbox Code Playgroud)
编辑:我最初写了上面的检查,__getslice__()但我注意到在collections模块文档中,有趣的方法是__getitem__(); 这是有道理的,这就是你如何索引一个对象.这似乎比__getslice__()我改变了上述内容更为根本.
小智 120
H = "Hello"
if type(H) is list or type(H) is tuple:
## Do Something.
else
## Do Something.
Run Code Online (Sandbox Code Playgroud)
suz*_*kya 68
对于Python 2:
import collections.abc
if isinstance(obj, collections.abc.Sequence) and not isinstance(obj, str):
print("obj is a sequence (list, tuple, etc) but not a string")
Run Code Online (Sandbox Code Playgroud)
对于Python 3:
import collections
if isinstance(obj, collections.Sequence) and not isinstance(obj, basestring):
print "obj is a sequence (list, tuple, etc) but not a string or unicode"
Run Code Online (Sandbox Code Playgroud)
已在版本3.3中更改:将集合抽象基类移动到collections.abc模块.为了向后兼容,它们将继续在此模块中可见,直到3.8版本它将停止工作.
Ces*_*sar 31
PHP风格的Python:
def is_array(var):
return isinstance(var, (list, tuple))
Run Code Online (Sandbox Code Playgroud)
Rob*_*ney 10
一般来说,迭代对象的函数对字符串以及元组和列表起作用的事实比bug更具特色.你当然可以使用isinstance或打字来检查一个参数,但你为什么要这样做?
这听起来像是一个修辞问题,但事实并非如此.答案为"我为什么要检查参数的类型?" 可能会建议解决真正的问题,而不是感知问题.将字符串传递给函数时,为什么会出现错误?另外:如果将字符串传递给此函数时出现错误,如果将其他非list/tuple iterable传递给它,它是否也是一个错误?为什么或者为什么不?
我认为这个问题最常见的答案可能是编写的开发人员f("abc")期望这个函数表现得好像他们写的那样f(["abc"]).在某种情况下,保护开发人员更有意义,而不是支持迭代字符串中字符的用例.但我首先想到它很长很难.
试试这个是为了提高可读性和最佳实践:
Python2
import types
if isinstance(lst, types.ListType) or isinstance(lst, types.TupleType):
# Do something
Run Code Online (Sandbox Code Playgroud)
Python3
import typing
if isinstance(lst, typing.List) or isinstance(lst, typing.Tuple):
# Do something
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你.
该str对象没有__iter__属性
>>> hasattr('', '__iter__')
False
Run Code Online (Sandbox Code Playgroud)
所以你可以检查一下
assert hasattr(x, '__iter__')
Run Code Online (Sandbox Code Playgroud)
这也AssertionError将为任何其他非可迭代对象带来好处.
编辑: 正如蒂姆在评论中提到的,这只适用于python 2.x,而不是3.x.
这不是为了直接回答OP,但我想分享一些相关的想法.
我对上面的@steveha回答非常感兴趣,这似乎给出了一个例子,其中鸭子打字似乎打破了.关于第二个想法,但是,他的例子表明,鸭子类型是很难适应,但它并没有暗示str值得任何特殊处理.
毕竟,非str类型(例如,维护一些复杂递归结构的用户定义类型)可能导致@steveha srepr函数导致无限递归.虽然这是不太可能的,但我们不能忽视这种可能性.因此,与其特殊的壳体内str的srepr,我们应该澄清一下,我们希望srepr当一个无限递归的结果做.
似乎一种合理的方法就是在srepr当下简单地打破递归list(arg) == [arg].事实上,这将完全解决问题str,没有任何问题isinstance.
然而,一个非常复杂的递归结构可能会导致list(arg) == [arg]永远不会发生的无限循环.因此,虽然上述检查很有用,但还不够.我们需要类似递归深度的硬限制.
我的观点是,如果你打算处理任意参数类型,那么str通过鸭子打字处理比处理你可能(理论上)遇到的更一般的类型要容易得多.因此,如果您觉得需要排除str实例,则应该要求该参数是您明确指定的少数几种类型之一的实例.
我在 tensorflow 中找到了一个名为is_sequence 的函数。
def is_sequence(seq):
"""Returns a true if its input is a collections.Sequence (except strings).
Args:
seq: an input sequence.
Returns:
True if the sequence is a not a string and is a collections.Sequence.
"""
return (isinstance(seq, collections.Sequence)
and not isinstance(seq, six.string_types))
Run Code Online (Sandbox Code Playgroud)
我已经验证它满足您的需求。