【发布时间】:2015-08-02 11:24:43
【问题描述】:
我为字符范围做了一个小生成器函数:
>>> def crange(start, end):
... for i in range(ord(start), ord(end)+1):
... yield chr(i)
...
然后我可以这样做:
>>> print(*crange('a','e'))
a b c d e
耶!但这不起作用:
>>> crange('a','e')[::2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'generator' object is not subscriptable
这可行,但是是 O(n),不像 range 的 O(1):
>>> 'y' in crange('a','z')
True
这意味着从最多 110,000 个字符中搜索第 109,999 个字符大约需要 0.35 秒。 109999 in range(110000) 当然很快。
那时,我的第一个想法是简单地对范围进行子类化。不幸的是:
>>> class A(range):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'range' is not an acceptable base type
所以我想我必须以某种方式模仿它,允许我将字符作为参数传递,在内部像 range 一样工作,并产生字符。不幸的是,我不确定如何进行。我试过dir():
>>> print(*dir(range), sep='\n')
__class__
__contains__
__delattr__
__dir__
__doc__
__eq__
__format__
__ge__
__getattribute__
__getitem__
__gt__
__hash__
__init__
__iter__
__le__
__len__
__lt__
__ne__
__new__
__reduce__
__reduce_ex__
__repr__
__reversed__
__setattr__
__sizeof__
__str__
__subclasshook__
count
index
start
step
stop
这让我可以看到里面有什么功能,但我不确定它们在做什么,或者range 如何使用它们。我查找了 range 的源代码,但它是 C 语言的,我不知道在哪里可以找到它的 Python 包装器(它确实有一个,对吗?)。
我从这里去哪里,我应该去那里吗?
【问题讨论】:
-
“但它是用 C 语言编写的,我不知道在哪里可以找到它的 Python 包装器(它确实有一个,对吗?)” - 不。与
list或dict一样,range的任何部分都不是用 Python 编写的。 -
关于班级,也许是
class A(object, range): -
虽然这似乎是一个有趣的问题,但我投票决定关闭它,因为它过于宽泛。除了通过
range的整个API 并复制它之外,没有什么好的方法可以做到这一点,所以答案必须描述range所做的一切,所有用于自定义len的钩子和切片等等大概需要 10 页。我建议搜索方法名称并查看 Python data model。 -
现有版本的替代品:
def crange(start, end): return map(chr, range(ord(start), ord(end))) -
我不同意它过于宽泛。 OP已经有了一个核心方法,他需要做的是实现一个惰性列表,这本质上就是
range()的作用。一旦他这样做了,他就可以着手实现范围 API 的其余部分,并提出有关它们的具体问题。 OP 可能想先看看 PyPi 上的lazyarray模块。我强烈建议 OP 尽快将他的问题缩小到惰性列表实现,以避免被关闭。
标签: python