Python函数内部类变量调用失败求助:如何正确调用?
问题分析
你遇到的错误Function 'gpscall' has no 'GPS' member,核心原因是GPS类定义在gpscall函数的内部作用域里,外部代码(比如__main__块)根本无法直接访问这个类。而且你调用gpscall(gpscall.GPS.LATITUDE)的逻辑也有问题——你试图在调用函数之前就访问函数内部的类成员,这在Python的作用域规则里是完全不允许的。
另外你的代码还有几个小细节需要修正:
DEGREES = [9]明显是笔误,应该是DEGREES = variables[9]- 用
[int(s) for s in variables[1] if s.isdigit()]提取数字会把连续数字拆成单个元素(比如"12"会变成[1,2]),应该改成提取完整的数字串 - 串口读取的代码里
decoded = (ser.read(1).decode)少了调用括号,应该是decoded = ser.read(1).decode()
优化后的解决方案
我们可以调整逻辑,让gpscall函数负责读取并解析GPS数据,要么返回完整的GPS对象供外部自由调用,要么根据传入的参数返回指定属性值。下面是两种可行的方案:
方案1:返回完整的GPS对象(推荐,更灵活)
这种方式能让你在外部自由访问所有GPS属性,后续扩展需求也更方便:
import time import serial # 假设你已导入serial模块并初始化了ser对象 class GPS: def __init__(self, variables): # 修复数字提取逻辑:提取完整数字串而非单个数字 self.PULSE_SAWTOOTH = int(''.join([s for s in variables[1] if s.isdigit()])) self.TRACKED_SATELLITES = int(''.join([s for s in variables[2] if s.isdigit()])) self.VISIBLE_SATELLITES = int(''.join([s for s in variables[3] if s.isdigit()])) # 经纬度拆分处理 self.LONGITUDE = variables[5] longlen = len(self.LONGITUDE) self.LONGDEG = self.LONGITUDE[0:longlen-7] self.LONGMIN = self.LONGITUDE[longlen-7:] self.LATITUDE = variables[6] latlen = len(self.LATITUDE) self.LATDEG = self.LATITUDE[0:latlen-7] self.LATMIN = self.LATITUDE[latlen-7:] self.HEIGHT = variables[7] self.KNOTS = variables[8] self.DEGREES = variables[9] # 修正笔误 self.GPS_STATUS = variables[10] self.TIMING_MODE = variables[17] self.FIRMWARE_VERSION = variables[20] def gpscall(): # 向串口写入GPS指令 ser.write(com.GPSstatus.encode()) time.sleep(1) # 读取串口返回数据 out = '' while ser.inWaiting() > 0: decoded = ser.read(1).decode() # 修复decode调用 out += decoded # 处理输出字符串,拆分变量 substr = out[:-9] # 简化切片写法 variables = substr.splitlines() # 创建GPS实例并返回 return GPS(variables) if __name__ == "__main__": # 获取完整的GPS数据对象 gps_data = gpscall() # 按需访问并打印指定属性 print("纬度:", gps_data.LATITUDE) print("跟踪卫星数:", gps_data.TRACKED_SATELLITES) # 其他属性也可以直接调用,比如gps_data.FIRMWARE_VERSION
方案2:根据参数返回指定属性
如果你只需要单次获取某个特定属性,可以让函数接收属性名称字符串,直接返回对应值:
import time import serial class GPS: def __init__(self, variables): # 同方案1的初始化逻辑 self.PULSE_SAWTOOTH = int(''.join([s for s in variables[1] if s.isdigit()])) self.TRACKED_SATELLITES = int(''.join([s for s in variables[2] if s.isdigit()])) self.VISIBLE_SATELLITES = int(''.join([s for s in variables[3] if s.isdigit()])) self.LONGITUDE = variables[5] longlen = len(self.LONGITUDE) self.LONGDEG = self.LONGITUDE[0:longlen-7] self.LONGMIN = self.LONGITUDE[longlen-7:] self.LATITUDE = variables[6] latlen = len(self.LATITUDE) self.LATDEG = self.LATITUDE[0:latlen-7] self.LATMIN = self.LATITUDE[latlen-7:] self.HEIGHT = variables[7] self.KNOTS = variables[8] self.DEGREES = variables[9] self.GPS_STATUS = variables[10] self.TIMING_MODE = variables[17] self.FIRMWARE_VERSION = variables[20] def gpscall(attribute_name): # 读取串口数据逻辑同方案1 ser.write(com.GPSstatus.encode()) time.sleep(1) out = '' while ser.inWaiting() > 0: decoded = ser.read(1).decode() out += decoded substr = out[:-9] variables = substr.splitlines() gps_instance = GPS(variables) # 动态获取属性,同时处理属性不存在的情况 try: value = getattr(gps_instance, attribute_name) print(value) return value except AttributeError: print(f"GPS类不存在该属性:{attribute_name}") return None if __name__ == "__main__": # 调用函数并指定要返回的属性 gpscall("LATITUDE") gpscall("TRACKED_SATELLITES")
关键知识点说明
- Python作用域规则:函数内部定义的类/变量,只能在函数内部访问,外部无法直接引用。把GPS类移到函数外面,或者在函数内部创建实例后返回,是解决问题的核心。
- getattr函数:方案2中用
getattr(gps_instance, attribute_name)可以动态获取对象属性,让函数的复用性更强。 - 串口读取修正:原来的
decoded = (ser.read(1).decode)少了调用括号,decode()才是执行解码操作的正确写法。
内容的提问来源于stack exchange,提问作者Denver Quin
相关产品推荐
相关产品推荐

