简体   繁体   中英

File "<string>", line 1, in <lambda> NameError: name 'self' is not defined

I try to pass a variable into a function as name by using lambda but when I run it I get this error File "", line 1, in NameError: name 'self' is not defined and it happens in show_items function

what is the problem here I tried anything I could but it didn't work?

    from ast import While
from PyQt5 import QtGui, QtWidgets,QtCore
from PyQt5.uic import loadUi
from PyQt5.QtWidgets import QApplication, QMainWindow,QDialog,QLabel,QTableWidget,QTableWidgetItem,QWidget,QListWidget
import sys
import sqlite3
import ctypes
from PyQt5 import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow,QDialog,QLabel,QTableWidget,QTableWidgetItem,QWidget,QListWidget,QGraphicsOpacityEffect
from PyQt5.QtCore import QPropertyAnimation, QPoint, QEasingCurve , QTimer
import time
from time import sleep
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
connection = sqlite3.connect("main.db")
cu = connection.cursor()
class mainapp(QMainWindow):
    def __init__(self):
        super(mainapp, self).__init__()
        loadUi("main.ui", self)
        self.pages.setCurrentIndex(0)
        self.labelShow.setWordWrap(True)
   
        self.menuFrame.move(1100 , 0)
        self.menuFrame_2.move(1100 , 0)
        self.show_items()
        
    def show_items (self):
        cu.execute("SELECT * FROM notes ")
        all = cu.fetchall()
        count = 1
        height = 0
        push_style = "background-color: rgb(249, 167, 183);\nborder : none;"    
        for i in all:
            main_height = height + 120
            # print(i)
            print(type(i[0]))
            exec("nameInfo"+(str(count))+" ="+'(str(i[0]))'+"")
            # print(eval("nameInfo"+(str(count))))
            exec("self.pushButton = QtWidgets.QPushButton(self.infoFrame)")
            eval("self.pushButton.setGeometry(QtCore.QRect(10, height, 655, 110))")
            eval("self.pushButton.setMinimumSize(QtCore.QSize(655, 110))")
            eval("self.pushButton.setMaximumSize(QtCore.QSize(200, 110))")
            eval("self.pushButton.setStyleSheet(push_style)")
            eval("self.pushButton.setText(nameInfo"+(str(count))+")")
            exec("self.pushButton.clicked.connect(lambda: self.show_Id(nameInfo"+'(str(count))'+"))")
            self.pushButton.setObjectName("pushButton")
            
            # self.verticalLayout.addWidget(self.infoFrame)
            height = height + 130
            print(height)
            count = count + 1
        # self.infoFrame.setMaximumHeight(main_height)
        self.infoFrame.setMinimumHeight(main_height)
    def show_Id(self , name):
        print(name)



app = QApplication(sys.argv)
calculator_app = mainapp()
calculator_app.show()

sys.exit(app.exec_())

I can't test it but all problem can be because you use exec() / eval() which may run code without knowing that there is self in your code.

But you should't use separated variables nameInfo1 , nameInfo2 , but list nameInfo = [] and then you don't need exec() / eval()

Something like this:

   def show_items(self):
        
        connection = sqlite3.connect("main.db")
        cursor = connection.cursor()

        cursor.execute("SELECT * FROM notes")
        
        height = 0
        push_style = "background-color: rgb(249, 167, 183);\nborder : none;"
        
        #self.all_rows = []
        self.all_names = []
        self.all_buttons = []
        
        for row in cursor.fetchall():

            #self.all_rows.append(row)     # <--- keep all rows on list
            self.all_names.append(row[0])  # <--- keep all names on list

            main_height = height + 120
            
            button = QtWidgets.QPushButton(self.infoFrame)
            button.setGeometry(QtCore.QRect(10, height, 655, 110))
            button.setMinimumSize(QtCore.QSize(655, 110))
            button.setMaximumSize(QtCore.QSize(200, 110))
            button.setStyleSheet(push_style)
            
            button.setText(row[0])
            
            button.clicked.connect(lambda value=row[0]: self.show_id(value))  # it needs `value=` when `lambda` is created in `for`-loop
            
            button.setObjectName("pushButton")
            
            self.all_buttons.append(button)  # <--- keep all buttons on list
            
            # self.verticalLayout.addWidget(self.infoFrame)
            height += 130

        # self.infoFrame.setMaximumHeight(main_height)
        self.infoFrame.setMinimumHeight(main_height)

EDIT

PyQt may also need to keep all buttons in list. if you try to use the same variable self.pushButton for all buttons then it may create only last one because when you assign new value to variable self.pushButton then it may remove previous button from window.

And when you use lambda in for -loop them you need value=row[0] in lambda value=row[0]: ... . If you use directly row[0] the it will NOT send value but only reference to variable row and later all functions will have reference to the same row (with last value) and all functions will use the same (last) value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM