【发布时间】:2016-10-01 15:00:10
【问题描述】:
注意:这是 CodeReview 上的 crossposted,根据建议
前提:我有一个类层次结构(Python),其中tidy 是其中一种方法。它删除类型为 ASTIgnore 的节点,并将该节点的子节点重新绑定到其父节点。
目标节点不能删除自己,也没有看到它的父节点(用于重新绑定)。因此,目标(ASTIgnore 类型)的删除将发生在其父级,父级检查其子级的类型。
问题:需要如何实现以减少代码异味?
这些方法中哪一种最不坏,或者还有其他方法(见底部)?
# A)
if child.nodetype == "ASTIgnore":
# B)
if child.isIgnored():
# C)
if child.isIgnoreType:
# D)
if isinstance(child, ASTIgnore):
类和tidy 如下所示。我将根据最简洁的实现删除冗余。
class ASTNode(object):
def __init__(self):
self.nodetype = self.__class__.__name__
self.isIgnoreType = False
def isIgnored(self):
return False
def tidy(self):
# Removes "Ignore" type/attribute nodes while maintaining hierarchy
if self.children:
for child in self.children:
child.tidy()
for i, child in reversed(list(enumerate(self.children))):
#--------- Is this Bad? ----------
if child.nodetype == "ASTIgnore":
#------ --------------------------
if not child.children:
# leaf node deletion
self.children.pop(i)
else:
# target node deletion + hierarchy correction
grandkids = child.children
self.children[i:i+1] = grandkids
class ASTIgnore(ASTNode):
def __init__(self):
ASTNode.__init__()
self.isIgnoreType = True
def isIgnored(self):
return True
关于 Duck Typing 和 Tell-Not-Ask 政策的问题:
我是 Python 新手,想成为一名 Python 编码员(一般来说也是一名更好的编码员)。因此,
我如何鸭式上面的?如果属性/函数在对象构造之外从未被触及,检查属性值(igIgnoreType)/函数(isIgnored)是否会被视为Duck Typing?
我确实有另一个实现,其中tidy 在 Ignore 类型节点中被重载。 不再进行类型检查,但父级仍需移除目标子级,并重新绑定孙子级。在这里,Ignore 类型返回它们的子节点,即叶节点的 []。但是,仍然检查返回是否为None。我确定这肯定是 Duck Typing,但正在检查 None 和代码复制,错误代码?
class ASTNode(object):
def tidy(self):
for i, child in reversed(list(enumerate(self.children))):
grandkids = child.tidy()
if grandkids is not None:
self.children[i:i+1] = grandkids
return None
class ASTIgnore(ASTNode):
def tidy(self):
for i, child in reversed(list(enumerate(self.children))):
grandkids = child.tidy()
if grandkids is not None:
self.children[i:i+1] = grandkids
return self.children
_edit0
基于Eric's 投票,isIgnored() 函数检查实现看起来像
def tidy(self):
"""
Clean up useless nodes (ASTIgnore), and rebalance the tree
Cleanup is done bottom-top
in reverse order, so that the deletion/insertion doesn't become a pain
"""
if self.children:
# Only work on parents (non-leaf nodes)
for i, child in reversed(list(enumerate(self.children))):
# recurse, so as to ensure the grandkids are clean
child.tidy()
if child.isIgnored():
grandkids = child.children
self.children[i: i + 1] = grandkids
【问题讨论】:
-
IMO
isIgnored()使您的代码最容易理解。对于读者来说,拥有额外的路标比使用重复代码的第二个密集函数更容易。 -
将其发布到 Code Review:我将有机会获得答案。
-
Crossposted 这个在 CodeReview 上。添加了 Eric 的投票实现。
-
@LaurentLAPORTE 不,这个问题不太适合 Code View。
标签: python typechecking duck-typing