You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:07:58