Почему getattr (self, "x") не совпадает с self.x в этом примере? - PullRequest
0 голосов
/ 16 февраля 2020

Я обнаружил случай, когда getattr(self, "x") ведет себя не так, как self.x. Извините за длину поста - я не знал, как воспроизвести поведение без PySide2 вокруг. Так что с этим example.qml файлом:

import QtQuick 2.10
import QtQuick.Controls 2.1
import QtQuick.Window 2.2
import QtQuick.Controls.Material 2.3

ApplicationWindow {
    id: applicationWindow
    Material.theme: Material.Dark
    title: qsTr("Test Invoke")
    visible: true

    width: 600
    height: 500

    Slider {
        id: slider1
        x: 69
        y: 215
        value: Manager.xyz
        property bool updateValueWhileDragging: true
        onMoved: Manager.xyz = value
    }
}

и этим example.py файлом:

import sys
import os

from PySide2.QtCore import Qt, QObject, Signal, Slot, Property
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtWidgets import QSlider, QPushButton, QCheckBox

class Manager(QObject):
    xyz_slot = Signal()
    def __init__(self):
        QObject.__init__(self)
        self.__xyz = None
        self.xyz_slot.connect(self.on_xyz_changed)
        self.xyz = 0.3

    @Property(float, notify=xyz_slot) # (6)
    def xyz(self):
        # (1) This works
        # return self.__xyz
        # (2) This doesn't work and produces the error:
        # Error: 'Manager' object has no attribute '__xyz'
        return getattr(self, "__xyz")

    @xyz.setter
    def set_xyz(self, val):
        if self.__xyz == val:
            return
        self.__xyz = val
        self.xyz_slot.emit()

    @Slot()
    def on_xyz_changed(self):
        print(self.__xyz)

if __name__ == "__main__":
    os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    manager = Manager()
    ctx = engine.rootContext()
    ctx.setContextProperty("Manager", manager)
    engine.load('example.qml')
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

с использованием Python 3,7.

Почему getattr (2) версия не работает?

Обратите внимание, что мне нужна версия с getattr, потому что я хочу украсить другие классы. В этом случае невозможно использовать версию с точечным вызовом. В документации есть пример, который утверждает, что boh - то же самое. Я могу представить, что, возможно, C ++-код PySide2 вызывает разницу. Однако я не знаю, как действовать дальше.

1 Ответ

1 голос
/ 16 февраля 2020

Поскольку вы используете двойное подчеркивание с искажением имени.

Из документов

Обратите внимание, что код, переданный exec() или eval(), делает не считать имя класса вызывающего класса текущим классом; это похоже на действие глобального оператора, действие которого также ограничено кодом, который байтово скомпилирован вместе. То же ограничение применяется к getattr(), setattr() и delattr(), а также к прямым ссылкам на __dict__.

Возможно, вам не нужно использовать двойное подчеркивание, так что просто не используйте его.

...