【问题标题】:method logical development in class课堂上的方法逻辑发展
【发布时间】:2016-08-13 19:01:27
【问题描述】:

这是我研究的一个简单代码。来自zetcode.com

你需要 Pyqt5 lib 来执行它:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

In this example, a QCheckBox widget
is used to toggle the title of a window.

author: Jan Bodnar
website: zetcode.com 
last edited: January 2015
"""

import sys
from PyQt5.QtWidgets import QWidget, QCheckBox, QApplication
from PyQt5.QtCore import Qt


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):      

        cb = QCheckBox('Show title', self)
        cb.move(20, 20)
        cb.toggle()
        cb.stateChanged.connect(self.changeTitle)

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('QCheckBox')
        self.show()


    def changeTitle(self, state):

        if state == Qt.Checked:
            self.setWindowTitle('QCheckBox')
        else:
            self.setWindowTitle('')


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

我的问题更多是关于类,args 的性质。

如果你看到这部分代码:

cb.stateChanged.connect(self.changeTitle)

很明显它连接到changeTitle函数,但是我们有相同的函数:

def changeTitle(self, state):

开头是:

if state == Qt.Checked:

我的问题是关于状态的。为什么作者添加了 state 以及为什么它充当对象,如果没有在此代码中以任何方式定义。?

如果作者这样做,对我来说是合乎逻辑的:

cb.stateChanged.connect(self.changeTitle(state))

这样就知道有参数需要根据if条件执行。

很想听听您的解释。谢谢。

【问题讨论】:

  • 显然cb.stateChanged.connect 采用了一个回调函数,即当cb 的状态发生任何变化时都会调用该函数。当调用发生时,一个参数被传递给回调函数,代表新的状态。因此,您传递的方法定义了一个 state 参数来接收它。如果您确实尝试了cb.stateChanged.connect(self.changeTitle(state)),您将遇到两个问题: 1. state 那时没有定义;和 2. 这只会在状态发生任何变化之前调用一次回调。
  • 谢谢。是的,它显然很安静:),但是,我们如何从技术上知道这一点?如果我理解正确,对于所有具有回调性质的方法,我们可以在 () 中创建一个参数,它将充当触发器、响应等?
  • 你是什么意思“从技术上知道”?阅读文档?源代码?事件回调是 GUI 框架中非常常见的模式。
  • 还有你的问题“我们可以在()中创建一个参数,作为触发器、响应等?”对我来说是不可理解的。
  • 如果我使用self.pusbutton.clicked.connect(self.buttonpressed) 然后定义方法,我不需要添加任何额外的参数。在这种情况下,我想,这不是回调方法。我只是想知道,你怎么知道哪些self.button 选项支持回调,最重要的是,你在哪里检查。谢谢。

标签: class python-3.x methods pyqt5


【解决方案1】:

如果你看到这部分代码:

cb.stateChanged.connect(self.changeTitle)

很明显它与changeTitle函数有关,

其实self.changeTitle是一种方法。并不是说它会改变任何东西,您可以在这里传递任何可调用对象。

但是我们有相同的功能:

def changeTitle(self, state):

我假设您的意思是“在同一个班级”?

开头是:

if state == Qt.Checked:

我的问题是关于状态的。为什么作者添加状态

“添加”到什么???

以及为什么它作为一个对象,

你是什么意思“作为一个对象”? (顺便说一句,你知道 Python 中的一切都是对象吗?)

如果没有在此代码中以任何方式定义。?

这是一个传递给函数的参数。你在这里有什么困惑?

如果作者这样做,对我来说是合乎逻辑的:

cb.stateChanged.connect(self.changeTitle(state))

好的,我明白了...正如我上面所说,在 Python 中,所有内容(字符串、整数、列表等,还有函数、方法、类甚至模块)都是对象。有些对象是“可调用的”——它们实现了__call__(self, ...) 方法。当您将调用运算符() 应用于可调用对象时,它的__call__ 方法将被执行。函数和方法(显然)是可调用的,类也是可调用的(调用类是你实例化它的方式)。

IOW,给定一个函数 foo:

def foo(x):
   print("FOOO {}".format(x))

您可以将其用作普通变量(将其传递给另一个函数等),然后您可以调用它:

def bar(func):
    print("in bar, func is {}".format(func))
    print("calling func")
    func(42)


bar(foo)

如果你回头看原始代码:

cb.stateChanged.connect(self.changeTitle)

你可以看到我们现在没有调用self.changeTitle(没有括号...),我们只是将方法对象传递给cb.stateChanged.connect()。当cb 对象认为它合适时,它会回调它(这就是它被命名为“回调”的原因),并将state 参数的正确值传递给它。

现在你在这里建议:

cb.stateChanged.connect(self.changeTitle(state))

不会传递self.changeTitle(一个方法对象),而是先调用self.changeTitle(state),然后将这个调用的结果(self.changeTitle(state)的返回值)传递给cb.stateChangedConnect()——这是完全不同的。

注意:实际上这会引发NameError,因为state 没有定义,但这是另一个问题。

这样就知道有参数需要根据if条件执行。

这不是它的工作原理。 API定义了传递给cb.stateChangedConnect()的回调必须接受state参数,而cb.stateChangedConnect()传递这个参数。

【讨论】:

    猜你喜欢
    • 2019-01-03
    • 2015-04-29
    • 2017-04-06
    • 1970-01-01
    • 2018-10-03
    • 2011-10-19
    • 2020-06-27
    • 1970-01-01
    • 2020-08-01
    相关资源
    最近更新 更多