有条件执行,而无需重复检查条件

  • 本文关键字:条件 执行 有条件 python
  • 更新时间 :
  • 英文 :


我有一个适合以下模板的代码的类:

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.switchTrue时,我希望执行单行代码,而无需在每次迭代中检查self.switch。当self.switchFalse时,我希望忽略单行代码,而不必重复检查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_loopsecond_loop,然后在__init__中,根据self.f = self.first_loopself.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的实现,为一个示例)。

最新更新