Python类中使用global传递列表异常:返回长度不一致求助
你遇到的问题核心在于**global关键字的作用范围只限于当前模块**,不是跨模块的。
你在调用模块里定义的TABLE和Names_db,和NamesClass模块里用global声明的那两个变量,完全是两个独立的命名空间里的东西。类里的global TABLE, Names_db只是告诉Python:“我要使用当前模块(也就是NamesClass)里的全局变量”,根本不会影响调用模块里的同名变量。所以你调用模块里的Names_db自始至终都是初始的空列表,长度自然是0,而类方法返回的是NamesClass模块里那个Names_db的长度,所以出现了1888和0的差异。
全局变量本来就不是好的编程习惯,尤其是跨模块使用的时候,很容易出现这种混淆。给你几个更靠谱的解决办法:
方法1:用类属性存储数据(推荐)
把TABLE和Names_db改成Names类的类属性,这样调用者可以直接通过类访问这些数据,不需要依赖全局变量:
修改NamesClass.py的代码:
class Names: # 定义类属性,所有实例共享 TABLE = [] Names_db = [] @classmethod def LoadTable(cls, rdatapath): """ load and sort a list from the text file return the length of the list """ # 清空类属性,避免重复加载时数据残留 cls.TABLE = [] cls.Names_db = [] first_time = True with open(rdatapath) as f: for line_of_text in f: line_of_text = line_of_text.strip() aname = line_of_text.split(',') cls.TABLE.append(f"{aname[1]},{aname[0]},{aname[2]},{aname[3]}") #name, year, sex, occurences cls.TABLE.sort() #sort by name for i, a_record in enumerate(cls.TABLE): record = a_record.split(',') if first_time: previous_name = record[0] previous_sex = record[2] sum = 0 first_time = False if previous_name != record[0]: cls.Names_db.append(f"{i}{previous_name}{previous_sex}{sum}") sum = 0 first_time = True previous_name = record[0] previous_sex = record[2] sum += int(record[3]) return len(cls.Names_db)
调用模块的代码修改成这样:
from NamesClass import Names RDATAPATH = "C:/users/richo/documents/python/Name Data/yob.txt" length = Names.LoadTable(RDATAPATH) print(length, len(Names.Names_db))
这样运行后,两个数值就会一致了,因为你访问的是Names类的Names_db属性,和类方法里操作的是同一个对象。
方法2:让方法直接返回数据
如果不需要长期保存这些数据,直接让LoadTable方法返回长度和Names_db列表,调用者接收后自己处理:
修改NamesClass.py的代码:
class Names: def __init__(self): pass @staticmethod def LoadTable(rdatapath): """ load and sort a list from the text file return the length of the list and the Names_db list """ TABLE = [] Names_db = [] first_time = True with open(rdatapath) as f: for line_of_text in f: line_of_text = line_of_text.strip() aname = line_of_text.split(',') TABLE.append(f"{aname[1]},{aname[0]},{aname[2]},{aname[3]}") #name, year, sex, occurences TABLE.sort() #sort by name for i, a_record in enumerate(TABLE): record = a_record.split(',') if first_time: previous_name = record[0] previous_sex = record[2] sum = 0 first_time = False if previous_name != record[0]: Names_db.append(f"{i}{previous_name}{previous_sex}{sum}") sum = 0 first_time = True previous_name = record[0] previous_sex = record[2] sum += int(record[3]) return len(Names_db), Names_db
调用模块的代码:
from NamesClass import Names RDATAPATH = "C:/users/richo/documents/python/Name Data/yob.txt" length, Names_db = Names.LoadTable(RDATAPATH) print(length, len(Names_db))
这种方式更简洁,完全不需要依赖任何全局变量,数据传递清晰明了。
方法3:(不推荐)直接访问模块的全局变量
如果你非要用全局变量的方式,那调用者需要直接访问NamesClass模块里的全局变量,而不是自己定义同名变量:
调用模块代码修改成:
import NamesClass RDATAPATH = "C:/users/richo/documents/python/Name Data/yob.txt" length = NamesClass.Names.LoadTable(RDATAPATH) print(length, len(NamesClass.Names_db))
但这种方式不推荐,因为全局变量会让代码的依赖关系变得模糊,后期维护容易出问题。
内容的提问来源于stack exchange,提问作者Rich Osborne

