我有一个适合以下模板的代码的类:
class aClass:
def __init__(self, switch = False):
self.switch = switch
def f(self):
done = False
while not done:
# a dozen lines of code
if self.switch:
# a single line of code
# another dozen lines of code
因此,if语句中的一行代码将永远不会执行,或者将在 all 迭代中执行。实际上,当对象被初始化时,这实际上就被称为。
当self.switch
是True
时,我希望执行单行代码,而无需在每次迭代中检查self.switch
。当self.switch
为False
时,我希望忽略单行代码,而不必重复检查self.switch
。
我当然已经考虑了f
的两个版本,并根据switch
的值在__init__
中选择适当的版本,但是复制所有这些代码,除了单行不正确,。
任何人都可以提出一种优雅的方法来解决这个问题吗?也许是一种初始化时f
方法的适当版本的方法?
这是一个完全有效的问。如果不是为了性能,则可用于可读性。
用三种单独的方法提取三个逻辑(内部,内部和状态之后),在f()
中,只需写两个大环的实现:
def first(self):
pass
def second(self):
pass
def third(self):
pass
def f(self):
if self.switch:
while ...:
self.first()
self.third()
else:
while ...:
self.first()
self.second()
self.third()
如果您希望它更优雅(尽管取决于口味),则将我的f()
的两个分支表达为两种方法first_loop
和second_loop
,然后在__init__
中,根据self.f = self.first_loop
或self.f = self.second_loop
分配CC_17。
class SuperUnderperformingAccordingToManyYetReadable(object):
def __init__(self, switch):
if self.switch:
self.f = self._first_loop
else:
self.f = self._second_loop
def _first(self):
pass
def _second(self):
pass
def _third(self):
pass
def _first_loop(self):
while ...:
self.first()
self.third()
def _second_loop(self):
while ...:
self.first()
self.second()
self.third()
您可能需要做一些额外的工作来管理折断循环。
如果不应该更改.switch
属性,请尝试在__init__()
方法中动态选择循环车身:
def __init__(self, switch=False):
self.switch = switch
self.__fBody = self.__fSwitchTrue if switch else self.__fSwitchFalse
def f(self):
self.__done = False
while not self.__done:
self.__fBody()
def __fSwitchTrue(self):
self.__fBodyStart()
... # a single line of code
self.__fBodyEnd()
def __fSwitchFalse(self):
self.__fBodyStart()
self.__fBodyEnd()
def __fBodyStart(self):
... # a dozen lines of code
def __fBodyEnd(self):
... # another dozen lines of code
记住要更改一个以上定义的方法使用的值将值更改为属性(例如done
更改为.__done
)。
在对我最初的问题的评论中,约翰科尔曼建议使用exec
,并提供了指向另一个相关问题的链接。
这是一个很好的建议,我是我的解决方案是:
_template_pre = """
def f(self):
for i in range(5):
print("Executing code before the optional segment.")
"""
_template_opt = """
print("Executing the optional segment")
"""
_template_post = """
print("Executing code after the optional segment.")
"""
class aClass:
def __init__(self, switch = False):
if switch:
fdef = _template_pre + _template_opt + _template_post
else:
fdef = _template_pre + _template_post
exec(fdef, globals(), self.__dict__)
# bind the function
self.f = self.f.__get__(self)
您可以验证这一点实际上有效:
aClass(switch = False).f()
aClass(switch = True).f()
在得出关于" Pythonic"的结论之前检查名称tuple的实现,为一个示例)。