什么是处理独特项、列表和生成器的最佳方法
问题的出现原因:在Python中,我们经常需要处理包含不重复元素的列表或生成器。然而,有时我们需要以不同的方式处理这些元素,这就引发了关于如何最好地处理唯一项、列表和生成器的问题。
解决方法:根据经验,Python中的一种解决方法是将列表作为参数传递给函数,并在函数调用时使用*list
的形式。具体代码如下:
myfunc(item) myfunc(*items)
实际上,myfunc(*items)
会将items列表转换为一个元组传递给函数。
这种方法可以方便地处理唯一项、列表和生成器,提供了更灵活的处理方式。这样我们可以根据需要将列表或生成器中的元素作为单独的参数传递给函数,而不需要手动拆分列表或生成器。
在Python中,使用*list
的方式可以很好地处理唯一项、列表和生成器。这种方法提供了更灵活的处理方式,使我们能够根据需要将列表或生成器中的元素作为单独的参数传递给函数。
问题的出现原因是str虽然被认为是一个序列(可迭代的,有getitem等),但通常被视为单个项目。例如,一个函数可以接受一个参数,该参数可以是文件名或文件名列表。函数如何检测第一个参数和后者之间的区别,这是最具Python风格的方式?
根据修订后的问题,听起来您想要的是类似下面这样的东西:
def to_sequence(arg): ''' determine whether an arg should be treated as a "unit" or a "sequence" if it's a unit, return a 1-tuple with the arg ''' def _multiple(x): return hasattr(x,"__iter__") if _multiple(arg): return arg else: return (arg,) >>> to_sequence("a string") ('a string',) >>> to_sequence( (1,2,3) ) (1, 2, 3) >>> to_sequence( xrange(5) ) xrange(5)
这并不能保证处理所有类型,但对于您提到的情况,它处理得很好,并且对于大多数内置类型应该能够正确处理。
在使用它时,请确保接收此输出的任何内容都可以处理可迭代对象。
正如Brissom在关于相关问题的这个答案的评论中指出的,字符串没有`__iter__`属性是一个不一致之处,这个问题在Python 3中得到了修复,这使得这种方法不兼容。
Python中处理唯一项、列表和生成器的最佳方法是使用抽象基类(abstract base classes)。抽象基类可以根据需要进行自定义,以考虑一些例外情况,例如不将字符串视为序列。下面是一个示例:
import abc import collections class Atomic(object): __metaclass__ = abc.ABCMeta def __subclasshook__(cls, other): return not issubclass(other, collections.Sequence) or NotImplemented Atomic.register(basestring)
在注册之后,可以使用`isinstance`和`issubclass`来使用`Atomic`类:
assert isinstance("hello", Atomic) == True
这比硬编码的列表要好得多,因为你只需要注册规则的例外情况,而且代码的外部用户也可以注册他们自己的例外情况。
需要注意的是,在Python 3中,指定元类的语法发生了变化,并且删除了`basestring`抽象超类。因此,需要使用以下代码代替:
class Atomic(metaclass=abc.ABCMeta): def __subclasshook__(cls, other): return not issubclass(other, collections.Sequence) or NotImplemented Atomic.register(str)
如果需要,可以编写既兼容Python 2.6+又兼容Python 3.x的代码,但是这需要使用稍微复杂一些的技术,动态创建所需的抽象基类,从而避免由于元类语法差异而导致的语法错误。这与Benjamin Peterson的`six`模块的`with_metaclass()`函数基本相同。
class _AtomicBase(object): def __subclasshook__(cls, other): return not issubclass(other, collections.Sequence) or NotImplemented class Atomic(abc.ABCMeta("NewMeta", (_AtomicBase,), {})): pass try: unicode = unicode except NameError: # 'unicode' is undefined, assume Python >= 3 Atomic.register(str) # str includes unicode in Py3, make both Atomic Atomic.register(bytes) # bytes will also be considered Atomic (optional) else: # basestring is the abstract superclass of both str and unicode types Atomic.register(basestring) # make both types of strings Atomic
在2.6版本之前,可以使用`operator`模块中的类型检查器。
import operator assert operator.isSequenceType([]) == True assert operator.isSequenceType(0) == False assert operator.isSequenceType("hello") == True
以上就是处理唯一项、列表和生成器的最佳方法以及解决方法的内容。