note :根据建议
,这是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
关于使用“请勿 - 不 - 要求”政策打鸭的问题:
我是Python的新手,想成为一个pythonic编码器(一般来说是一个更好的编码器)。因此,
我如何 Duck Type 以上?如果在对象构造之外从未触及属性/函数,那么检查属性值(igIgnoreType
)/函数(isIgnored
)是否会被视为 Duck Typing ?
我还有另一个实现,其中tidy
在忽略类型节点中重载。 不再进行类型检查,但父级仍然必须删除目标子级,并重新绑定孙级。这里,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
答案 0 :(得分:1)
我认为使用tidy
方法的返回值是在节点之间传递信息的好方法。无论如何,你打算在你的每个孩子身上调用tidy
,所以获得一个返回值,告诉你如何处理这个孩子会使整个代码变得更简单。
使用super
从派生类调用基类的实现,只需更改返回值,就可以避免重复自己:
class ASTIgnore(ASTNode):
def tidy(self):
super().tidy() # called for the side-effects, return value is overridden
return self.children
如果您使用的是Python 2,其中super
比Python 3中的神奇有点神奇,那么您需要使用super(ASTIgnore, self)
代替super()
。< / p>