【问题标题】:Creating class instance within a loop and updating it在循环中创建类实例并更新它
【发布时间】:2018-06-15 05:38:34
【问题描述】:

假设我有一个像这样的数据集('test.csv'):

Name,Fruit,Price
John,Apple,1.00
Steve,Apple,1.00
John,Mango,2.00
Adam,Apple,1.00
Steve,Banana,1.00

虽然有几种更简单的方法可以做到这一点,但我想在 python 中将这些信息组织为一个类。因此,理想情况下,类的实例应如下所示:

{'name': 'John', 'Fruits': ['Apple','Mango'], 'Price':[1.00, 2.00]}

我将数据集加载到类中的方法是将每个实例存储在一个列表中。

class org(object):
    def __init__(self,name,fruit,price):
        self.name = name
        self.fruit = [fruit]
        self.price = [price]

    classes = []
    with open('test.csv') as f:
        for line in f:
            if not 'Name' in line:
                linesp=line.rstrip().split(',')
                name = linesp[0]
                fruit = linesp[1]
                price = linesp[2]
                inst = org(name,fruit,price)
                classes.append(inst)
    for c in classes:
        print (c.__dict__)
  1. 在这种情况下,我如何知道“John”是否已经作为实例存在?

  2. 如果是这样,我如何更新“John”?使用类方法?

@classmethod
    def update(cls, value):
        cls.fruit.append(fruit)

【问题讨论】:

  • 这不是您所要求的,但可以根据您的需要进行修改:Creating a singleton。在您的情况下,您并不完全想要“只有一个实例”(单例),但您确实想要“每种类型只有一个实例”,所以看看这些想法是否有帮助
  • 你愿意使用字典而不是列表吗?
  • 您确实需要修复缩进。您发布的代码非常难以阅读,并且不是有效的 Python。

标签: python loops class oop


【解决方案1】:

不需要任何特殊的东西来更新您的实例。您的类的属性是公开的,因此只需访问它们进行更新。

如果你坚持使用列表作为你的实例容器,你可以做某事。像这样:

classes = []
with open('test.csv') as f:
    for line in f:
        if not 'Name' in line:
            name,fruit,price=line.rstrip().split(',')
            exists = [inst for inst in classes if inst.name == name]
            if exists:
                exists[0].fruit.append(fruit)
                exists[0].price.append(price)
            else:
                classes.append(org(name,fruit,price))
for c in classes:
    print (c.__dict__)

但是,我建议改用 dict,因为它可以更轻松地查找和访问实例

classes = {}
with open('test.csv') as f:
    for line in f:
        if not 'Name' in line:
            name,fruit,price=line.rstrip().split(',')
            if name in classes:
                classes.get(name).fruit.append(fruit)
                classes.get(name).price.append(price)
            else:
                classes.update({name: org(name,fruit,price)})

for c in classes.values():
    print (c.__dict__)

两种解决方案都会给你同样的东西:

{'name': 'John', 'fruit': ['Apple', 'Mango'], 'price': ['1.00', '2.00']}
{'name': 'Steve', 'fruit': ['Apple', 'Banana'], 'price': ['1.00', '1.00']}
{'name': 'Adam', 'fruit': ['Apple'], 'price': ['1.00']}

为了完整起见,下面 cmets 中的 @MadPhysicist 可能意味着更新 dict 的笨拙方式是我使用 dict 的方法而不是通过订阅访问项目。

# update existing instance in the dict
classes[name].fruit.append(fruit)

# add new instance to the dict
classes[name] = org(name, fruit, price)

我个人觉得这有点难看,因此我倾向于使用这些方法:)

【讨论】:

  • 使用字典的想法是正确的。为此+1。更新 dict 的方式非常笨拙。
  • @MadPhysicist 请详细说明您认为它笨重的原因? :)
  • 如果您要检查是否包含,请使用直接索引而不是 get 来获取项目。此外,在这里可能无关紧要,但是检索一次引用并对其执行两件事比每次要对其执行某些操作时都查找它要有效得多。你可能想看看dict.setdefault,但你需要一个构造函数来创建一个空实例。
  • 如果您要提高效率,首先使用 defaultdict 而不是 dict.setdefault 应该更快。但是,正如您所说,它的缺点是构造函数需要更改才能接受没有参数的实例化。如果你想保持类的原样,我认为做exists = classes.get(name),如果它是真的更新存在,否则用新实例更新字典会更好,因为你保持最大查找次数为1 .
  • 另外,为什么classes.update({name: org(name,fruit,price)}) 而不仅仅是classes[name] = org(...)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-02
  • 1970-01-01
  • 1970-01-01
  • 2018-12-20
  • 1970-01-01
  • 2021-06-06
  • 1970-01-01
相关资源
最近更新 更多