Python类入门问题:如何调用对象变量名及try/except使用是否正确
我刚学习Python编程,在实验中编写了Vehicle类代码(如下),并创建了vehicle1、vehicle2等对象:
class Vehicle(object): def __init__(self, maxspeed, mileage, color="white"): self.maxspeed=maxspeed; self.mileage=mileage; self.color=color; def assign_seating_capacity(self, seating_capacity): self.seating_capacity=seating_capacity def properties(self): print("Properties of the vehicle:") print("Maximum Speed:", self.maxspeed) print("Mileage:", self.mileage) print("Color:", self.color) try: print("Seating Capacity:", self.seating_capacity) except AttributeError: print("Seating capacity unknown")
问题1:能否在properties方法中调用对象的变量名,使输出变为“Properties of vehicle1:”而非“Properties of the vehicle:”?
Python里对象本身不会记录指向它的变量名,变量名只是对对象的引用,所以直接通过self拿不到变量名。有两种可行的解决方式:
推荐方案:给对象添加name属性
在类的__init__方法里新增一个name参数,把变量名作为参数传入,后续直接调用这个属性即可:class Vehicle(object): def __init__(self, maxspeed, mileage, color="white", name="the vehicle"): self.maxspeed = maxspeed self.mileage = mileage self.color = color self.name = name # 新增name属性 # 其他方法不变 def properties(self): print(f"Properties of {self.name}:") # 使用name属性 print("Maximum Speed:", self.maxspeed) print("Mileage:", self.mileage) print("Color:", self.color) try: print("Seating Capacity:", self.seating_capacity) except AttributeError: print("Seating capacity unknown") # 创建对象时传入名字 vehicle1 = Vehicle(120, 20, name="vehicle1") vehicle1.properties() # 输出:Properties of vehicle1:备选方案:反向查找变量名(不推荐)
通过globals()或locals()遍历当前命名空间,找到指向该对象的变量名,但这种方法有局限性——同一个对象可能被多个变量引用,且仅能查找全局/当前局部作用域内的变量:def get_object_name(obj): # 遍历全局命名空间找匹配的变量 for name, value in globals().items(): if value is obj: return name return "the vehicle" # 在properties方法中调用 def properties(self): print(f"Properties of {get_object_name(self)}:") # 后续输出不变这种方式不推荐,因为逻辑不稳定,可读性也差,优先用第一种方案。
问题2:用try/except处理未调用assign_seating_capacity时的AttributeError是否正确?对比初始化时设置self.seating_capacity = None的方式,哪种更合理?
两种方式都能解决问题,但适用场景不同:
try/except的方式(EAFP风格)
这是Python推崇的“先尝试再请求原谅”的写法,代码简洁,适合属性属于可选属性的场景(比如部分车辆不需要记录座位容量)。但缺点是如果座位容量是车辆的固有属性,这种写法会让类的结构不清晰,其他开发者阅读代码时可能不知道这个属性的存在。初始化设为None的方式(LBYL风格)
在__init__里直接初始化self.seating_capacity = None,属于“先检查再执行”的写法,优点是类的结构更清晰,所有人一看就知道这个对象有seating_capacity属性,只是初始值为None。后续判断时直接用if self.seating_capacity is not None即可,不需要捕获异常,可读性更强。
总结:如果座位容量是所有Vehicle对象都应该具备的属性(只是可能延迟设置),优先用初始化设为None的方式;如果是可选属性,两种方式都可以,但依然推荐统一初始化,让类的定义更明确。
内容的提问来源于stack exchange,提问作者LaurenKai

