鱼C论坛

 找回密码
 立即注册
查看: 954|回复: 4

[已解决]关于全局变量的定义问题

[复制链接]
发表于 2023-6-29 23:06:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 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 = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
check = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]

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[0:17].isdigit():  # 前17位是否为数字
                                id17 = list(map(int, list(ID[0:17])))  # 将前17位转换为数字列表
                                if int(ID[6:14]) in range(19000101, int(datetime.datetime.now().strftime("%Y%m%d")) + 1):
                                        try:
                                                datetime.date.fromisoformat(ID[6:14])
                                                mod = sum(list(map(lambda x, y: x * y, id17, weight))) % 11
                                                if str(check[mod]) == ID[-1]:  # 判断余数与对应的校验码是否匹配
                                                        # print(len(code_data))
                                                        if len(code_data) == 0:
                                                                address = '户籍地址不详'
                                                        else:
                                                                address = code_data.get(ID[0:6], "户籍地址不详")
                                                        self.ui.infor.setPlainText(f'校验无误:性别[{"女" if int(ID[-2]) % 2 == 0 else "男"}],户籍地址为:{address}')
                                                else:
                                                        self.ui.infor.setPlainText(f'身份证末位校验码不正确(应为[{check[mod]}])')
                                        except ValueError:
                                                self.ui.infor.setPlainText(f'出生日期[{ID[6:10]}年{ID[10:12]}月{ID[12:14]}日]不是合法的日期')
                                else:
                                        self.ui.infor.setPlainText(f'出生日期[{ID[6:14]}]不正确,应介于[19000101--{datetime.datetime.now().strftime("%Y%m%d")}]之间')
                        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())
        
最佳答案
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`声明为全局变量,就可以在其他方法中正常引用了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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`声明为全局变量,就可以在其他方法中正常引用了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

受教了,居然忽视了变量赋值就也是定义,谢谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-30 07:09:05 From FishC Mobile | 显示全部楼层
hynet1024 发表于 2023-6-29 23:36
受教了,居然忽视了变量赋值就也是定义,谢谢!

不客气
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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)))

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

还望不吝赐教!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-22 15:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表