hynet1024 发表于 2023-6-29 23:06:24

关于全局变量的定义问题

本帖最后由 hynet1024 于 2023-6-29 23:07 编辑

我在Python代码的开头定义了一个全局变量,但在引用时总提示未定义,请求指点

见代码:定义在第10行,引用在第47行(第32行没问题)

import sys

import datetime
import openpyxl

from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import Slot
from IDcheck_ui import Ui_Form

global code_data
weight =
check =

class MyWidget(QWidget):
        def __init__(self):
                super().__init__()
                self.ui = Ui_Form()
                self.ui.setupUi(self)


        @Slot()
        def on_select_clicked(self):
                import tkinter as tk
                from tkinter import filedialog as fd

                root = tk.Tk()
                root.withdraw()

                filename = fd.askopenfilename(filetypes=[('Excel Files', '*.xlsx')])
                self.ui.excelfile.setPlaceholderText(filename.replace('/','\\'))
                ws = openpyxl.load_workbook(filename)['Sheet1']
                code_data = dict(list(ws.iter_rows(values_only=True)))


        @Slot()
        def on_check_clicked(self):
                ID = self.ui.ID.text()
                if len(ID) == 18:# 身份证号长度是否为18位
                        if ID.isdigit():# 前17位是否为数字
                                id17 = list(map(int, list(ID)))# 将前17位转换为数字列表
                                if int(ID) in range(19000101, int(datetime.datetime.now().strftime("%Y%m%d")) + 1):
                                        try:
                                                datetime.date.fromisoformat(ID)
                                                mod = sum(list(map(lambda x, y: x * y, id17, weight))) % 11
                                                if str(check) == ID[-1]:# 判断余数与对应的校验码是否匹配
                                                        # print(len(code_data))
                                                        if len(code_data) == 0:
                                                                address = '户籍地址不详'
                                                        else:
                                                                address = code_data.get(ID, "户籍地址不详")
                                                        self.ui.infor.setPlainText(f'校验无误:性别[{"女" if int(ID[-2]) % 2 == 0 else "男"}],户籍地址为:{address}')
                                                else:
                                                        self.ui.infor.setPlainText(f'身份证末位校验码不正确(应为[{check}])')
                                        except ValueError:
                                                self.ui.infor.setPlainText(f'出生日期[{ID}年{ID}月{ID}日]不是合法的日期')
                                else:
                                        self.ui.infor.setPlainText(f'出生日期[{ID}]不正确,应介于之间')
                        else:
                                self.ui.infor.setPlainText('身份证前17位应全部为数字')
                else:
                        # self.ui.infor.textCursor().insertText('身份证号长度应为18位\n')
                        self.ui.infor.setPlainText('身份证号长度应为18位')


if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = MyWidget()
        window.setWindowTitle('身份证合法性校验')
        window.show()
        sys.exit(app.exec())
       

sfqxx 发表于 2023-6-29 23:10:53

代码中定义了一个全局变量`code_data`,但在`on_check_clicked`方法中的引用提示未定义的错误。这是因为在`on_select_clicked`方法中定义的局部变量`code_data`与全局变量`code_data`命名相同,导致在`on_check_clicked`方法中无法访问到全局变量。

要解决这个问题,你可以在`on_select_clicked`方法内将`code_data`声明为全局变量,使用`global`关键字进行声明,这样就可以在其他方法中正常引用了。

修改代码如下:

@Slot()
def on_select_clicked(self):
    import tkinter as tk
    from tkinter import filedialog as fd

    root = tk.Tk()
    root.withdraw()

    filename = fd.askopenfilename(filetypes=[('Excel Files', '*.xlsx')])
    self.ui.excelfile.setPlaceholderText(filename.replace('/','\\'))
    ws = openpyxl.load_workbook(filename)['Sheet1']
    global code_data# 将局部变量声明为全局变量
    code_data = dict(list(ws.iter_rows(values_only=True)))
通过添加`global code_data`语句,将`code_data`声明为全局变量,就可以在其他方法中正常引用了。

hynet1024 发表于 2023-6-29 23:36:30

sfqxx 发表于 2023-6-29 23:10
代码中定义了一个全局变量`code_data`,但在`on_check_clicked`方法中的引用提示未定义的错误。这是因为在` ...

受教了,居然忽视了变量赋值就也是定义,谢谢!

sfqxx 发表于 2023-6-30 07:09:05

hynet1024 发表于 2023-6-29 23:36
受教了,居然忽视了变量赋值就也是定义,谢谢!

不客气

hynet1024 发表于 2023-6-30 08:54:08

本帖最后由 hynet1024 于 2023-6-30 09:09 编辑

刚才按您的提示,修改如下:

函数外部定义全局变量:
global code_data
code_data = {}                #必不可少

on_select_click 内部:
global code_data
code_data = dict(list(ws.iter_rows(values_only=True)))

如此程序方可正常运行,并满足需求。只是:一定要这样做吗?原理是什么?有没有更好的办法?

还望不吝赐教!
页: [1]
查看完整版本: 关于全局变量的定义问题