关于递归发生器的样式问题 [英] Style question on recursive generators

查看:78
本文介绍了关于递归发生器的样式问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,


这里我使用了一些深层嵌套的树状数据结构。在一些

情况下,我需要遍历树;旧式的方法是在节点类上写一个递归方法,如下所示:


def walk(self):

"""'old-style recursive tree traversal""

child.do_something

for childs in childs:

child.walk()


当然,do_something可以是节点上的可配置方法或动作,其实际实现与此讨论无关。递归解决方案干净且易读,并且这是为什么它经常优于迭代解决方案,其中(a)

需要手动内务管理(使用堆栈)上班;并且(b)不是真正的'面向对象'',因为它没有将节点

遍历行为委托给被遍历的节点。


在我的上一个项目中,我一直在倾向于更多地使用

发电机。但是,当在上面描述的情况下使用发电机时,最终结果并不是自然地读取:


def walk(self ):

""基于生成器的递归树遍历"

收益子女

适用于孩子的孩子:

表示child.walk中的节点()

yield节点


问题是我需要''链'''从子树到

的收益率会将结果反馈给调用者。它看起来并不像简单的递归版本那样优雅

;这是令人困惑的阅读,因为一个

必须弄清楚在内循环中产生了什么,而且它的b / b
也容易出错 - 很容易忘记在

内循环中包含''yield'。


我现在想知道哪个更好:继续使用旧式递归

树遍历代码,或者链式收益生成器解决方案。这是一个风格决定的更多

- 我不关心这一点上的原始性能,但设计的清晰度和优雅性更为重要。


-

Carlos Ribeiro

Consultoria em Projetos

博客: http://rascunhosrotos.blogspot.com

博客: http://pythonnotes.blogspot.com

mail: ca ******** @ gmail.com

邮件: ca ******** @ yahoo.com

解决方案

< blockquote> Carlos Ribeiro写道:

大家好,

这里我使用了一些深层嵌套的树状数据结构。在某些情况下,我需要穿越树;旧式的方法是在节点类上编写一个递归方法,如:

def walk(self):
"""对于孩子的孩子,旧式递归树遍历"
child.do_something

child.walk()

[...]
def walk(self):
""基于生成器的递归树遍历"
为孩子生孩子

for child.walk中的节点()
yield节点

[...]我现在想知道哪个更好:继续使用旧式递归
树遍历代码,或链式收益发电机解决方案。这是一个风格决定的更多 - 我不关心这一点的原始性能,但设计的清晰度和优雅性更重要。




您还必须考虑使用迭代的代码,至少如果您想要为多种目的使用该结构


#在递归的情况下

def nodeHandler(节点):

node.do_something()

root.walk(nodeHandler )


#在生成器的情况下

for root.walk()中的节点:

node.do_something()


后者也可以用于期望迭代器的例程。


将os.path.walk与os.walk进行比较。 />

Daniel


2004年10月18日星期一14:11:53 +0200,Daniel Dittmar

<哒************ @ sap.corp>写道:

您还必须考虑使用迭代的代码,至少如果您想要将结构用于多种目的

< snip>

将os.path.walk与os.walk进行比较。

Daniel
-
http://mail.python.org/mailman/listinfo/python-list



是的,这是一个很好的观点,这也是我倾向于现在更喜欢发电机的原因之一。但无论如何,这只是我,或者'链式的'/ b $ b'收益率'看起来对别人来说难看吗?这可能只是一个问题,即用它来赚取b $ b,但不过它却让我烦恼......

-

Carlos Ribeiro

Consultoria em Projetos

博客: http: //rascunhosrotos.blogspot.com

博客: http:/ /pythonnotes.blogspot.com

邮件: ca ******* *@gmail.com

邮件: ca ******** @ yahoo.com


Carlos Ribeiro< ca ******** @ gmail.com>写道:

...

是的,这是一个很好的观点,这也是我倾向于选择现在的发电机的原因之一。但无论如何,它只是我,或者链式的产量看起来对别人来说难看吗?这可能只是一个习惯了它的问题,但它仍然困扰着我......




我不知道为什么它应该看起来很难看。什么替代方案

你认为普通(在任何发电机中)非丑陋的成语:

for x in y:yield x




也许有些语法破解,例如新的语句关键字''yieldall''

其中上面的成语可以表示为

yieldall y

?或者其他一些语法黑客,比如''yield<< y'',或''从y'收益',

同上?就个人而言,在我看来,这样的特殊语法只需要学习一点Python,没有实质性的好处,

但这是因为我看到了在今天的成语中没有任何丑陋的东西 - 它只是说明了它的内容,简单而朴素......

Alex


Hello all,

Here I am using some deeply nested, tree-like data structures. In some
situations I need to traverse the tree; the old-style way to do it is
to write a recursive method on the node class, as in:

def walk(self):
"""old-style recursive tree traversal"""
child.do_something
for child in childs:
child.walk()

Of course, "do_something" can be a configurable method or action on
the node, whose actual implementation doesn''t matter for this
discussion. The recursive solution is clean and readable, and that''s
why its frequently preferred over the iterative solution, which (a)
requires manual housekeeping (using a stack) to work; and (b) is not
truly ''object oriented'', in the sense that it does not delegate node
traversal behavior to the node being traversed.

In my last projects I''ve been tending towards a greater use of
generators. However, when a generator is used in the situation
described above, the end result does not ''read'' as naturally:

def walk(self):
"""generator-based recursive tree traversal"""
yield child
for child in childs:
for node in child.walk()
yield node

The problem is that I need to ''chain'' the yields from the subtrees to
yield back the result to the caller. It does not seem to be as elegant
as the simple recursive version; it''s confusing to read, because one
has to figure out what is being yielded in the inner loop, and it''s
also error-prone -- it''s easy to forget to include the ''yield'' in the
inner loop.

I''m now wondering which is better: to keep using old-style recursive
tree traversal code, or to chained-yield generator solution. It''s more
of a stylistic decision -- I''m not concerned about raw performance at
this point, but clarity and elegancy of design are more important.

--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: ca********@gmail.com
mail: ca********@yahoo.com

解决方案

Carlos Ribeiro wrote:

Hello all,

Here I am using some deeply nested, tree-like data structures. In some
situations I need to traverse the tree; the old-style way to do it is
to write a recursive method on the node class, as in:

def walk(self):
"""old-style recursive tree traversal"""
child.do_something
for child in childs:
child.walk()
[...]
def walk(self):
"""generator-based recursive tree traversal"""
yield child
for child in childs:
for node in child.walk()
yield node
[...] I''m now wondering which is better: to keep using old-style recursive
tree traversal code, or to chained-yield generator solution. It''s more
of a stylistic decision -- I''m not concerned about raw performance at
this point, but clarity and elegancy of design are more important.



You must also consider the code that uses the iteration, at least if you
want to walk the structure for multiple purposes

# In the recursive case
def nodeHandler (node):
node.do_something ()

root.walk (nodeHandler)

# in the generator case
for node in root.walk ():
node.do_something ()

And the latter can also be fed into routines that expect an iterator.

Compare also os.path.walk with os.walk.

Daniel


On Mon, 18 Oct 2004 14:11:53 +0200, Daniel Dittmar
<da************@sap.corp> wrote:

You must also consider the code that uses the iteration, at least if you
want to walk the structure for multiple purposes

<snip>

Compare also os.path.walk with os.walk.

Daniel
--
http://mail.python.org/mailman/listinfo/python-list



Yes, that''s a good point, and it''s one of the reasons I tend to prefer
the generator now. But anyway, it''s just me, or does the ''chained
yield'' look ugly to someone else? It may be just a question of getting
used to it, but nevertheless it''s bugging me...
--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: ca********@gmail.com
mail: ca********@yahoo.com


Carlos Ribeiro <ca********@gmail.com> wrote:
...

Yes, that''s a good point, and it''s one of the reasons I tend to prefer
the generator now. But anyway, it''s just me, or does the ''chained
yield'' look ugly to someone else? It may be just a question of getting
used to it, but nevertheless it''s bugging me...



I''m not sure why it should look ugly to you. What alternatives would
you consider non-ugly for the common (in any generator) idiom:
for x in y: yield x
?

Perhaps some syntax hack such as a new statement keyword ''yieldall''
where the above idiom could be expressed as
yieldall y
? Or some other syntax hack such as ''yield<<y'', or ''yield from y'',
ditto? Personally, it would seem to me that such special syntax would
be just one more bit of Python to learn, without substantial benefits,
but that''s because I see nothing ugly in today''s idiom -- it does just
what it says, plainly and unpretentiously...
Alex


这篇关于关于递归发生器的样式问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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