评论PEP-0322:反向迭代方法 [英] Comment on PEP-0322: Reverse Iteration Methods

查看:51
本文介绍了评论PEP-0322:反向迭代方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请评论新PEP的反向迭代方法。

基本上,这个想法是这样的:

$ x $ b for x in xrange(10)。 iter_backwards():#9,8,7,6,5,4,3,2,1,0

<用i做某事>


HTML版本比ReST版本更易读。

请参阅:
http://www.python.org/peps/pep-0322.html

在pre-pep线程中出现了几个有趣的想法:


*称之为ireverse()而不是iter_backwards()。


好​​主意。这是非常精辟的。

*使用对象属性而不是方法。


我还不能声称理解作者真的是什么/>
提议。它有一些事情可以提供

访问一个响应iter,getitem和

每个反转索引的物品的对象。

*使用单个函数,查找__riter__ magic

方法,如果没有找到,使用__getitem__和__len__

来构建反向迭代器。


发布了一个可行的版本。

它保存了实现一些对象方法的

添加新的内置函数和

创建一个新的魔术方法名称。

它比直接访问底层对象要慢。

应用于无限迭代器时崩溃。

应用于映射时会产生奇怪的结果。

*无限迭代器的特殊标记


这个想法很有意思,但并没有很好的延伸

当对象被另一个迭代器包裹时。

另外,没有自动的方法来确定

哪个基因rators可以是无限的。

Raymond Hettinger

Please comment on the new PEP for reverse iteration methods.
Basically, the idea looks like this:

for i in xrange(10).iter_backwards(): # 9,8,7,6,5,4,3,2,1,0
<do something with i>

The HTML version is much more readable than the ReST version.
See:
http://www.python.org/peps/pep-0322.html
Several interesting ideas surfaced in the pre-pep thread:

* Call it ireverse() instead of iter_backwards().

Good idea. This is much more pithy.
* Use object properties instead of methods.

I can''t yet claim to understand what the author is really
proposing. It has something to do which providing
access to an object that responds to iter, getitem, and
getslice with reversed indices.
* using a single function that looks for an __riter__ magic
method and, if not found, use __getitem__ and __len__
to build a reverse iterator.

A workable version of this was posted.
It saves implementing some object methods at the
expense of adding a new builtin function and of
creating a new magic method name.
It is slower than direct access to the underlying object.
It crashes when applied to an infinite iterator.
It produces bizarre results when applied to mappings.
* special markers for infinite iterators

This idea is interesting but doesn''t extend well
when the object is wrapped by another iterator.
Also, there is no automatic way to determine
which generators can be infinite.
Raymond Hettinger

推荐答案

" Raymond Hettinger" < VZ ****** @ verizon.net>在消息中写道

新闻:95 ***************** @nwrdny01.gnilink.net ...
"Raymond Hettinger" <vz******@verizon.net> wrote in message
news:95*****************@nwrdny01.gnilink.net...
请评论关于反向迭代方法的新PEP。
Please comment on the new PEP for reverse iteration methods.



来自PEP 322的


"""

拒绝替代想法

[snip]

添加内置函数,reverse()......

"""


你的意思是将函数reverse()(或ireverse())添加到itertools

库中,或添加到__builtins__?



# from PEP 322
"""
Rejected Alternative Ideas
[snip]
Add a builtin function, reverse() ...
"""

Do you mean add a function reverse() (or ireverse()) to the itertools
library, or to __builtins__?


我认为它说了需要说些什么。


+1


John Roth


" Raymond Hettinger" < VZ ****** @ verizon.net>在消息中写道

新闻:95 ***************** @nwrdny01.gnilink.net ...
I think it says what needs to be said.

+1

John Roth

"Raymond Hettinger" <vz******@verizon.net> wrote in message
news:95*****************@nwrdny01.gnilink.net...
请评论关于反向迭代方法的新PEP。
基本上,这个想法是这样的:

我在xrange(10).iter_backwards():#9,8,7,6, 5,4,3,2,1,0
<对我做点什么>

HTML版本比ReST版本更具可读性。
请参阅:
http://www.python.org/peps/pep- 0322.html

在前期线程中出现了几个有趣的想法:

*称之为ireverse()而不是iter_backwards()。

好主意。这是非常精辟的。

*使用对象属性而不是方法。

我还不能理解作者真正提出的建议。它有一些事情可以提供对一个对象的访问,该对象响应iter,getitem和
使用反向索引。

*使用单个函数查找__riter__魔法
方法,如果没有找到,可以使用__getitem__和__len__
构建一个反向迭代器。

这是一个可行的版本。
它节省了实现一些添加新内置函数和创建一个新的魔术方法名称的对象方法。
它比直接访问底层对象要慢。
它崩溃时应用于无限迭代器。
应用于映射时会产生奇怪的结果。

*无限迭代器的特殊标记

这个想法很有意思但不是当对象被另一个迭代器包裹时,延伸得很好。
此外,没有自动的方法来确定哪些发生器可以是无限的。

Raymond Hettinger
Please comment on the new PEP for reverse iteration methods.
Basically, the idea looks like this:

for i in xrange(10).iter_backwards(): # 9,8,7,6,5,4,3,2,1,0
<do something with i>

The HTML version is much more readable than the ReST version.
See:
http://www.python.org/peps/pep-0322.html
Several interesting ideas surfaced in the pre-pep thread:

* Call it ireverse() instead of iter_backwards().

Good idea. This is much more pithy.
* Use object properties instead of methods.

I can''t yet claim to understand what the author is really
proposing. It has something to do which providing
access to an object that responds to iter, getitem, and
getslice with reversed indices.
* using a single function that looks for an __riter__ magic
method and, if not found, use __getitem__ and __len__
to build a reverse iterator.

A workable version of this was posted.
It saves implementing some object methods at the
expense of adding a new builtin function and of
creating a new magic method name.
It is slower than direct access to the underlying object.
It crashes when applied to an infinite iterator.
It produces bizarre results when applied to mappings.
* special markers for infinite iterators

This idea is interesting but doesn''t extend well
when the object is wrapped by another iterator.
Also, there is no automatic way to determine
which generators can be infinite.
Raymond Hettinger



2003年9月25日星期四00:58:45 GMT,Raymond Hettinger

< vz ****** @ verizon.net>写道:
On Thu, 25 Sep 2003 00:58:45 GMT, "Raymond Hettinger"
<vz******@verizon.net> wrote:
*使用对象属性而不是方法。

我还不能理解作者真正提出的建议。它有一些事情可以提供对一个对象的访问,该对象响应iter,getitem和
使用反向索引。
* Use object properties instead of methods.

I can''t yet claim to understand what the author is really
proposing. It has something to do which providing
access to an object that responds to iter, getitem, and
getslice with reversed indices.




这个想法基本上有一种方法可以获得一个序列的代理,这个序列与原始序列的行为类似,但索引相反。有

是没有理由为什么成员函数不能返回那些代理

而不是使用属性,除非结果被切成它

看起来不那么难看。


我只为列表演示了它(在帖子末尾列出)。它有

三个属性...


向后:反转,切片返回一个列表

ibackward:反转,切片返回一个迭代器

iforward:forward,切片返回迭代器


目前所有属性都支持__getitem __,__ setitem__,

__delitem __,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ,__iter__和__len__(它们都返回

一个相同代理类的实例,但设置了不同的选项)。


对于简单的迭代迭代,我将使用与PEP284

线程相同的原则。

object-acting-as-sliceable-set-of-all-integers idea。

我在切片翻译工作时遇到了一些问题 - 有一些带有负面步骤的小恶作剧。你可以写...


x [:: - 1]


....但是试图让它明确......


x [len(x)-1:-1:-1]


....因为-ve stop bound而打破它。不是一个数字用户,

切片步骤对我来说是一个很新的事情 - 而那个小陷阱只是

让我感到惊讶。但是,解决它并不困难。

下面的代码并不是很好,但据我所知它可行。

$ b假设$ b Python 2.3。


问题是 - 练习是值得的。我不确定即使这是我自己的想法。我认为它的方式很好,并且比'iter_backward''方法提案更灵活,但是这非常可靠,因为它可能是一件坏事对于这个问题来说可能是一次性的过度杀伤

正在解决 - 特别是额外的灵活性有成本。


但是到底怎么样 - 玩起来很有趣有点!


无论如何,这是一个快速测试会议......



The idea is basically to have a way to get a proxy to a sequence which
behaves like the original sequence, but with indexes reversed. There
is no reason why member functions couldn''t return those proxies
instead of using properties, except that when the result is sliced it
looks less ugly.

I have a demo of it for lists only (listing at end of post). It has
three properties...

backward : reversed, slicing returns a list
ibackward : reversed, slicing returns an iterator
iforward : forward, slicing returns an iterator

All properties currently support __getitem__, __setitem__,
__delitem__, __str__, __repr__, __iter__ and __len__ (they all return
an instance of the same proxy class but with different options set).

For simple iterating-over-ints, I''d use the same principles with that
object-acting-as-sliceable-set-of-all-integers idea from the PEP284
thread.
I had some problems getting the slice translation to work - there are
some little nasties with negative steps. You can write...

x [::-1]

....but trying to make it explicit...

x [len(x)-1:-1:-1]

....breaks it because of that -ve stop bound. Not being a Numeric user,
slice steps are quite a new thing to me - and that little trap just
caught me by surprise. It isn''t too hard to work around it, though.
The code following isn''t pretty but so far as I can tell it works.

Python 2.3 is assumed.

The question is - is the exercise worthwhile. I''m not sure even though
it''s my own idea. I think it is nice in its way, and a lot more
flexible than the ''iter_backward'' method proposal, but that is quite
likely a bad thing as it is probably massive overkill for the problem
being solved - and in particular the extra flexibility has costs.

What the hell, though - it was fun to play with for a bit!

Anyway, here is a quick test session...

来自rilist import rilist
x = rilist(范围(20))
x.backward
[19,18,17,16,15,14 ,13,12,11,10,9,8,7,6,5,4,3,2,1,0] x.backward [:10]
[19,18,17,16,15 ,14,13,12,11,10] x.backward [:: 2]
[19,17,15,13,​​11,9,7,5,3,1] del x.backward [: :2]
x.backward
[18,16,14,12,10,8,6,4,2,0] x
[0,2,4,6,8 ,10,12,14,16,18]我在x.backward:
....打印我

....

18 < br / >
16

14

12

10

8

6

4

2

0 for x in x.backward [5:]:
.... print i

....

8

6

4

2
0 for x in x [5:]:
from rilist import rilist
x=rilist(range(20))
x.backward [19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] x.backward[:10] [19, 18, 17, 16, 15, 14, 13, 12, 11, 10] x.backward[::2] [19, 17, 15, 13, 11, 9, 7, 5, 3, 1] del x.backward[::2]
x.backward [18, 16, 14, 12, 10, 8, 6, 4, 2, 0] x [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] for i in x.backward : .... print i
....
18
16
14
12
10
8
6
4
2
0 for i in x.backward [5:]: .... print i
....
8
6
4
2
0 for i in x [5:]:



....打印我

。 ...

10

12

14

16

18

我也做了一些'ibackward''测试,这似乎有用 - 但是

我没有被''iforward''烦恼。

这是源 - 警告,它不是非常自我记录的ATM ......

class c_List_Proxy(object):

" ;"

代理列出类,它支持具有

修改行为的方法子集,主要是......


- 切片可能会创建一个迭代器而不是列表。

- 下标和范围可能会颠倒。

"""

def __init__(self,p_List,p_Reverse = False,p_Iter_Slice = False):

self.List = p_List

self.Reverse = p_Reverse

self.Iter_Slice = p_Iter_Slice


#需要一些支持的东西


def __SliceIter__(self,p_Slice):

如果p_Slice.step> 0:

i = p_Slice.start

而i< p_Slice.stop:

收益self.List [i]

i + = p_Slice.step

else:

i = p_Slice.start

而我> p_Slice.stop:

产生self.List [i]

i + = p_Slice.step


def __FullIter__(self):

i = len(self.List) - 1

而i> = 0:

产生self.List [i]

i - = 1

def __KeyTransformed__(self,p_Key):

if self.Reverse:

if p_Key< 0:

返回(-1) - p_Key


else:

return(len(self.List) - 1) - p_Key


else:

返回p_Key


def __Bound__(self,p_Given,p_Default):

返回p_Default

elif p_Given< 0:

返回len(self.List)+ p_Given

否则:

返回p_Given


def __SliceFixed __(self,p_Slice):

l_Step = p_Slice.step或1


如果l_Step == 0:

提高IndexError,步骤必须为非零


elif l_Step> 0:

l_Start = self .__ Bound __(p_Slice.start,0)

l_Stop = self .__ Bound __(p_Slice.stop,len(self.List))


else:

l_Start = self .__ Bound __(p_Slice.start,len(self.List) - 1)

l_Stop = self。 __Bound __(p_Slice.stop,-1)


l_Count =(((l_Stop - 1) - l_Start)// l_Step)+ 1

l_Stop = l_Start + l_Count * l_Step


返回切片(l_Start,l_Stop,l_Step)

def __SliceTransformed__(self,p_Slice):

l_Slice = self .__ SliceFixed __(p_Slice)


if self.Reverse:

l_End = len(self.List) - 1

返回切片(l_End - l_Slice.start,l_End - l_Slice.stop,

-l_Slice.step)


else:

返回p_Slice


#有些成员很琐碎


def __len__(个体经营):

返回len(self.List)


def __iter __(自我):

返回自我.__ FullIter __()


#一些成员需要多做一些工作...


def __str __(自我):

if self.Reverse:

return str(self.List [:: - 1])

else:

return str(self.List)


def __repr__(self):

if self.Reverse:

return repr(self.List [:: - 1])

else:

返回repr(self.List)


def __getitem __(self,p_Item):

if isinstance(p_Item,slice) :

如果self.Iter_Slice:

返回self .__ SliceIter__(self .__ SliceTransformed__(p_Item))


else:

l_Slice = self .__ SliceTransformed__(p_Item)


如果l_Slice.stop == -1:#烦人的特殊情况

返回自我。列表[l_Slice.start :: l_Slice.step]


返回self.List [l_Slice.start:l_Slice.stop:l_Slice.step]


else:

返回self.List [self .__ KeyTransformed__(p_Item)]


def __setitem __(self,p_Item,p_Value):

if isinstance(p_Item,slice):

l_Slice = self .__ SliceTransformed__(p_Item)


if l_Slice.stop == -1:#anboying特例

self.List [l_Slice.start :: l_Slice.step] = p_Value

else:

self.List [l_Slice.start :l_Slice.stop:l_Slice.step] = p_Value


else:

self.List [self .__ KeyTransformed__(p_Item)] = p_Value


def __delitem __(self,p_Item):

if isinstance(p_Item,slice):

l_Slice = self .__ SliceTransformed__(p_Item)


如果l_Slice.stop == -1:#烦人的特殊情况

del self.List [l_Slice.start :: l_Slice.step]

else:

del self.List [l_Slice.start:l_Slice.stop:l_Slice.step]


else:

del self.List [self .__ KeyTransformed__(p_Item)]


class rilist(list):

"""

扩展正常列表以提供给出正常变体的属性

索引行为 - 具体来说......


索引切片返回

-------- -------- -------

iforward forward iterator

ibackward落后迭代器

后退列表

" "

def __IFwd__(自我):

返回c_List_Proxy(self,False,True)


def __IBack __(自我):

返回c_List_Proxy(self,True,True)


def __Back__(自我):

返回c_List_Proxy(self ,正确,错误)


iforward = property(__ IFwd__)

ibackward = property(__ IBack__)

落后=财产(__ Back__ )

-

史蒂夫·霍恩


史蒂夫在九点点fsnet dot co uk


.... print i
....
10
12
14
16
18
I''ve done some ''ibackward'' tests as well, and that seems to work - but
I haven''t bothered with ''iforward''.
Here is the source - warning, it isn''t very self-documenting ATM...
class c_List_Proxy (object) :
"""
Proxy to list class which supports a subset of methods with
modified behaviours, mainly...

- Slicing may create an iterator rather than a list.
- Subscripts and ranges may be reversed.
"""

def __init__ (self, p_List, p_Reverse=False, p_Iter_Slice=False) :
self.List = p_List
self.Reverse = p_Reverse
self.Iter_Slice = p_Iter_Slice

# need some support stuff

def __SliceIter__ (self, p_Slice) :
if p_Slice.step > 0 :
i = p_Slice.start
while i < p_Slice.stop :
yield self.List [i]
i += p_Slice.step
else :
i = p_Slice.start
while i > p_Slice.stop :
yield self.List [i]
i += p_Slice.step

def __FullIter__ (self) :
i = len (self.List) - 1
while i >= 0 :
yield self.List [i]
i -= 1

def __KeyTransformed__ (self, p_Key) :
if self.Reverse :
if p_Key < 0 :
return (-1) - p_Key

else :
return (len (self.List) - 1) - p_Key

else :
return p_Key

def __Bound__ (self, p_Given, p_Default) :
if p_Given is None :
return p_Default
elif p_Given < 0 :
return len (self.List) + p_Given
else :
return p_Given

def __SliceFixed__ (self, p_Slice) :
l_Step = p_Slice.step or 1

if l_Step == 0 :
raise IndexError, "Step must be non-zero"

elif l_Step > 0 :
l_Start = self.__Bound__ (p_Slice.start, 0)
l_Stop = self.__Bound__ (p_Slice.stop, len (self.List))

else :
l_Start = self.__Bound__ (p_Slice.start, len (self.List) - 1)
l_Stop = self.__Bound__ (p_Slice.stop, -1)

l_Count = (((l_Stop - 1) - l_Start) // l_Step) + 1
l_Stop = l_Start + l_Count * l_Step

return slice(l_Start,l_Stop,l_Step)

def __SliceTransformed__ (self, p_Slice) :
l_Slice = self.__SliceFixed__ (p_Slice)

if self.Reverse :
l_End = len(self.List) - 1
return slice (l_End - l_Slice.start, l_End - l_Slice.stop,
-l_Slice.step)

else :
return p_Slice

# some members are trivial

def __len__ (self) :
return len (self.List)

def __iter__ (self) :
return self.__FullIter__ ()

# some members need a bit more work...

def __str__ (self) :
if self.Reverse :
return str(self.List [::-1])
else :
return str(self.List)

def __repr__ (self) :
if self.Reverse :
return repr(self.List [::-1])
else :
return repr(self.List)

def __getitem__ (self, p_Item) :
if isinstance (p_Item, slice) :
if self.Iter_Slice :
return self.__SliceIter__ (self.__SliceTransformed__ (p_Item))

else :
l_Slice = self.__SliceTransformed__ (p_Item)

if l_Slice.stop == -1 : # annoying special case
return self.List [l_Slice.start::l_Slice.step]

return self.List [l_Slice.start:l_Slice.stop:l_Slice.step]

else :
return self.List [self.__KeyTransformed__ (p_Item)]

def __setitem__ (self, p_Item, p_Value) :
if isinstance (p_Item, slice) :
l_Slice = self.__SliceTransformed__ (p_Item)

if l_Slice.stop == -1 : # annoying special case
self.List [l_Slice.start::l_Slice.step] = p_Value
else :
self.List [l_Slice.start:l_Slice.stop:l_Slice.step] = p_Value

else :
self.List [self.__KeyTransformed__ (p_Item)] = p_Value

def __delitem__ (self, p_Item) :
if isinstance (p_Item, slice) :
l_Slice = self.__SliceTransformed__ (p_Item)

if l_Slice.stop == -1 : # annoying special case
del self.List [l_Slice.start::l_Slice.step]
else :
del self.List [l_Slice.start:l_Slice.stop:l_Slice.step]

else :
del self.List [self.__KeyTransformed__ (p_Item)]

class rilist (list) :
"""
Extend normal list to provide properties giving variants of normal
indexing behaviour - specifically...

indexing slicing returns
-------- ---------------
iforward forward iterator
ibackward backward iterator
backward backward list
"""
def __IFwd__ (self) :
return c_List_Proxy (self, False, True)

def __IBack__ (self) :
return c_List_Proxy (self, True, True)

def __Back__ (self) :
return c_List_Proxy (self, True, False)

iforward = property(__IFwd__ )
ibackward = property(__IBack__)
backward = property(__Back__ )
--
Steve Horne

steve at ninereeds dot fsnet dot co dot uk


这篇关于评论PEP-0322:反向迭代方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆