我有一个函数接受一个参数,可以是单个项目或双项目:
def iterable(arg)
if #arg is an iterable:
print "yes"
else:
print "no"
Run Code Online (Sandbox Code Playgroud)
以便:
>>> iterable( ("f","f") )
yes
>>> iterable( ["f","f"] )
yes
>>> iterable("ff")
no
问题是字符串在技术上是可迭代的,所以我不能在尝试时捕获ValueError arg[1].我不想使用isinstance(),因为这不是很好的做法(或者我被告知).
scv*_*lex 44
使用isinstance(我不明白为什么这是不好的做法)
import types
if not isinstance(arg, types.StringTypes):
Run Code Online (Sandbox Code Playgroud)
请注意StringTypes的使用.它确保我们不会忘记一些不起眼的字符串.
从好的方面来说,这也适用于派生的字符串类.
class MyString(str):
pass
isinstance(MyString(" "), types.StringTypes) # true
Run Code Online (Sandbox Code Playgroud)
此外,您可能想看看上一个问题.
干杯.
注:行为在Python 3的改变StringTypes和basestring不再定义.根据您的需求,您可以取代他们isinstance的str,或子集元组(str, bytes, unicode),例如用于用Cython用户.正如@Theron Luhn所提到的,你也可以使用six.
sor*_*rin 19
截至2017年,这是一个适用于所有Python版本的可移植解决方案:
#!/usr/bin/env python
import collections
import six
def iterable(arg):
return (
isinstance(arg, collections.Iterable)
and not isinstance(arg, six.string_types)
)
# non-string iterables
assert iterable(("f", "f")) # tuple
assert iterable(["f", "f"]) # list
assert iterable(iter("ff")) # iterator
assert iterable(range(44)) # generator
assert iterable(b"ff") # bytes (Python 2 calls this a string)
# strings or non-iterables
assert not iterable(u"ff") # string
assert not iterable(44) # integer
assert not iterable(iterable) # function
Run Code Online (Sandbox Code Playgroud)
Ale*_*lli 16
从Python 2.6开始,引入抽象基类isinstance(用于ABCs,而不是具体类)现在被认为是完全可以接受的.特别:
from abc import ABCMeta, abstractmethod
class NonStringIterable:
__metaclass__ = ABCMeta
@abstractmethod
def __iter__(self):
while False:
yield None
@classmethod
def __subclasshook__(cls, C):
if cls is NonStringIterable:
if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
Run Code Online (Sandbox Code Playgroud)
这是完全相同的副本(只改变类名)Iterable中定义_abcoll.py(的实现细节collections.py)...的原因,这可以作为你想,虽然collections.Iterable不,是,后者更是不辞辛劳,以确保字符串通过Iterable.register(str)在此class语句之后显式调用,可以认为是可迭代的.
当然,__subclasshook__通过False在any调用其他类之前返回来扩展很容易,这些类要从定义中明确排除.
在任何情况下,导入这个新模块之后myiter,isinstance('ciao', myiter.NonStringIterable)将会False,并且isinstance([1,2,3], myiter.NonStringIterable)将会True像您要求的那样 - 在Python 2.6及更高版本中,这被认为是体现此类检查的正确方法...定义一个抽象基类并检查isinstance它.
通过结合以前的回复,我正在使用:
import types
import collections
#[...]
if isinstance(var, types.StringTypes ) \
or not isinstance(var, collections.Iterable):
#[Do stuff...]
Run Code Online (Sandbox Code Playgroud)
不是 100% 傻瓜证明,但如果一个对象不是可迭代的,你仍然可以让它通过并退回到鸭子类型。
编辑:Python3
types.StringTypes == (str, unicode)。Phython3 的等效项是:
if isinstance(var, str ) \
or not isinstance(var, collections.Iterable):
Run Code Online (Sandbox Code Playgroud)
编辑:Python3.3
types.StringTypes == (str, unicode)。Phython3 的等效项是:
if isinstance(var, str ) \
or not isinstance(var, collections.abc.Iterable):
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22930 次 |
| 最近记录: |