鱼C论坛

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

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

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

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

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

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

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

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

  1. import sys

  2. import datetime
  3. import openpyxl

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

  7. global code_data
  8. weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  9. check = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]

  10. class MyWidget(QWidget):
  11.         def __init__(self):
  12.                 super().__init__()
  13.                 self.ui = Ui_Form()
  14.                 self.ui.setupUi(self)


  15.         @Slot()
  16.         def on_select_clicked(self):
  17.                 import tkinter as tk
  18.                 from tkinter import filedialog as fd

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

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


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


  53. if __name__ == "__main__":
  54.         app = QApplication(sys.argv)
  55.         window = MyWidget()
  56.         window.setWindowTitle('身份证合法性校验')
  57.         window.show()
  58.         sys.exit(app.exec())
  59.        
复制代码
最佳答案
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`关键字进行声明,这样就可以在其他方法中正常引用了。

修改代码如下:

  1. @Slot()
  2. def on_select_clicked(self):
  3.     import tkinter as tk
  4.     from tkinter import filedialog as fd

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

  7.     filename = fd.askopenfilename(filetypes=[('Excel Files', '*.xlsx')])
  8.     self.ui.excelfile.setPlaceholderText(filename.replace('/','\\'))
  9.     ws = openpyxl.load_workbook(filename)['Sheet1']
  10.     global code_data  # 将局部变量声明为全局变量
  11.     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`关键字进行声明,这样就可以在其他方法中正常引用了。

修改代码如下:

  1. @Slot()
  2. def on_select_clicked(self):
  3.     import tkinter as tk
  4.     from tkinter import filedialog as fd

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

  7.     filename = fd.askopenfilename(filetypes=[('Excel Files', '*.xlsx')])
  8.     self.ui.excelfile.setPlaceholderText(filename.replace('/','\\'))
  9.     ws = openpyxl.load_workbook(filename)['Sheet1']
  10.     global code_data  # 将局部变量声明为全局变量
  11.     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-5-20 13:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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