Python中如何从外部独立函数访问已创建的类对象属性?
问题:无法通过实例名称字符串访问已创建的类实例属性
我刚学编程一个月,写了Category类并创建了food、clothing、entertainment三个实例,每个实例都做了存款和取款操作。现在想写一个外部函数,遍历包含实例名称的列表["food", "clothing", "entertainment"],打印每个实例的totalwithdrawals属性值,但循环里每次都会创建新的Category对象,导致输出的都是初始值0,而非实际的取款总额。
以下是我的代码:
class Category: def __init__(self, name): self.ledger = [] self.total = 0 self.name = name self.totalwithdrawals = 0 pass def __repr__(self): spaces = " " astfull = "*" * 23 #max 23 characters ast = "*" midpos = round((30-len(self.name))/2) #finding the middle position to add the object name title = astfull[:midpos] + self.name + ast*(30-(midpos+len(self.name))) #print object name in middle of bunch of asterisks c = "" for i in range(0, len(self.ledger), 2): #look into ledger list for amount and descriptions of deposits and withdrawals and create a report a_uncomp = str(self.ledger[i]) b_uncomp = str(self.ledger[i+1]) a_pos = a_uncomp.find(":") b_pos = b_uncomp.find(":") a = a_uncomp[a_pos + 2:(a_pos + 10)] b = b_uncomp[b_pos + 2:(b_pos + 26)] spacesf = spaces * (30 - (len(a) + len(b))) c += b + spacesf + a + "\n" totalf = "Total: " + str(self.total) return title + "\n" + c + totalf def deposit(self, amount, description = False): #deposit method with optional description self.ledger.append("amount: " + str(amount)) self.total += amount if description: self.ledger.append("description: " + description) else: self.ledger.append("description: ") def withdraw (self, amount, description = False): #withdraw method with optional description self.ledger.append("amount: " + str(-abs(amount))) if description: self.ledger.append("description: " + description) else: self.ledger.append("description: ") if (self.total + -abs(amount)) < 0: #return false if not enough money to withdraw specified amount return False else: #if enough money, rest amount from total variable for the specific object (deposits + withdrawals). self.total += -abs(amount) self.totalwithdrawals += -abs(amount) #separate variable storing ONLY withdrawals return True #adding three categories for testing food = Category("food") clothing = Category("clothing") entertainment = Category("entertainment") #doing bunch of random deposits and withdraws for testing food.deposit(1000, "initial deposit") food.withdraw(254, "supermarket") clothing.deposit(1000, "initial deposit") clothing.withdraw(634.23, "prada and channel") entertainment.deposit(536, "initial deposit") entertainment.withdraw(152, "trip to bcn") def create_spend_chart(categories): print(food.totalwithdrawals) print(clothing.totalwithdrawals) print(entertainment.totalwithdrawals) #These three blocks of print is what i want to get for i in categories: i = Category(i) print(i.totalwithdrawals) #but when i loop through a list with the same names as the categories all i get is a bunch of 0s. print(create_spend_chart(["food", "clothing", "entertainment"]))
解决方案
方法1:用字典映射实例名称与实例对象
创建一个字典,把实例名称字符串和对应的实例对象关联起来,遍历列表时从字典中取出已存在的实例,而非创建新对象:
# 在创建实例后添加字典 category_instances = { "food": food, "clothing": clothing, "entertainment": entertainment } def create_spend_chart(categories): # 先打印预期结果对比 print(food.totalwithdrawals) print(clothing.totalwithdrawals) print(entertainment.totalwithdrawals) # 遍历名称列表,从字典中取实例 for name in categories: instance = category_instances[name] print(instance.totalwithdrawals) print(create_spend_chart(["food", "clothing", "entertainment"]))
方法2:直接传入实例列表(更推荐)
不需要传名称字符串,直接把已创建的实例组成列表传入函数,这样可以直接访问实例属性:
def create_spend_chart(categories): for instance in categories: print(instance.totalwithdrawals) # 传入实例列表而非名称字符串 print(create_spend_chart([food, clothing, entertainment]))
方法3:通过globals()获取全局实例(不推荐)
如果实例是全局变量,可以通过globals()字典按名称获取,但这种方式不够安全,容易引发意外问题,仅作了解:
def create_spend_chart(categories): for name in categories: instance = globals()[name] print(instance.totalwithdrawals) print(create_spend_chart(["food", "clothing", "entertainment"]))
内容的提问来源于stack exchange,提问作者Freddy Frost
相关产品推荐
相关产品推荐

