-1

最低工作代码:

step1_failed = False
try:
    print("step #1")
except:
    step1_failed = True
print("step #2")  # always appening after step #1 but before step #3 regardless of if step #1 failed or not
if not step1_failed:
    print("step #3") # only if step #1 execute without error

我的问题是:有没有我看不到的更好的方法?

理想情况下没有任何虚拟变量,如 step1_failed。

我认为也许“终于”和“其他”是答案,但最终发生在 else 之后,我需要在 else 语句之前做一些事情。

这个用例是针对 PyQt5,我想断开一个信号并在做某事后重新连接它以避免不必要的递归。但我需要重新连接它,前提是它最初是连接的。

这是我的 PyQt5 代码,可以理解我为什么需要这个:

def somefunction():
    connected_at_first = True  # assuming it was connected
    try:
        lineedit1.textChanged.disconnect(somefunction)  # throw a TypeError if it is not connected
    except TypeError:
        connected_at_first = False  # happen only if lineedit1 wasn't connected

    lineedit1.setText("always happening !")

    # reconnecting lineedit1 if it was connected at the beginning
    if connected_at_first:
        lineedit1.textChanged.connect(somefunction)
4

3 回答 3

1

如果要避免递归,可以使用blockSignals()

def somefunction():
    blocked = lineedit1.blockSignals(True)
    lineedit1.setText("always happening !")
    lineedit1.blockSignals(blocked)

否则,使用一个简单的标志:

class SomeClass(QtWidgets.QWidget):
    signalFlag = False
    # ...
    def somefunction(self):
        if self.signalFlag:
            return
        self.signalFlag = True
        self.lineEdit.setText("always happening !")
        self.signalFlag = False
于 2021-07-15T16:03:34.023 回答
1

我不知道是否有更清洁的方法,但您的方法可以包含在上下文管理器中。

from contextlib import contextmanager

def tempdisconnect(o, f)
    connected = True
    try:
        o.disconnect(f)
    except TypeError:
        connected = False

    yield

    if connected:
        o.connect(f)

with tempdisconnect(lineedit1.textChanged, somefunction):
    lineedit1.setText("always happening !")

更好的 APIdisconnect是返回断开连接的函数(类似于signal.signal工作方式)或 return None。那么tempdisconnect可以写成

def tempdisconnect(o, f):
    old = o.disconnect(f)
    yield
    o.connect(old)

这也假设这是一个无操作,因此它在语句o.connect(None)主体之前和之后保持未连接。with

于 2021-07-15T16:04:54.803 回答
0

根据 chepner 的回答,我修改了他的代码,以便能够删除同一函数的重复连接并处理多个函数。

from contextlib import contextmanager

@contextmanager
def tempdisconnect(signal, func):
    if not isinstance(func, (tuple, list)):
        func = (func,)
    connected = [True] * len(func)

    for i in range(len(func)):
        a = 0
        try:
            while True:
                signal.disconnect(func[i])
                a += 1
        except TypeError:
            if a == 0:
                connected[i] = False

    yield

    if connected != False:
        for i in range(len(func)):
            if connected[i]:
                signal.connect(func[i])

用法 :

# Disconnect somefunction (even if it was accidently connected multiple times)
with tempdisconnect(lineEdit1.textChanged, somefunction):
    lineEdit1.setText("hello")

或者

# Disconnect somefunc1, somefunc2, somefunc3
with tempdisconnect(lineEdit1.textChanged, (somefunc1, somefunc2, somefunc3)):
    lineEdit1.setText("hello")
于 2021-07-15T21:20:44.403 回答