将类的实例分解为列表,或者:更好地对类变量求和的方法?

时间:2013-05-01 01:13:08

标签: python class

这是我一直在努力的项目的一部分。我很难将精神伪代码与我实际可以编写的东西合成,主要是由于个人对这些东西如何运作的误解。

我正在使用以下课程跟踪假想水果摊的库存:

class Fruit(object)
    def __init__(self,name,qty,price)
        self.color = str(color)
        self.qty = int(qty)
        self.price = float(price)

    def getName(self): return self.color
    def getQty(self): return self.qty
    def getPrice(self): return self.price
    def description(self): return self.color,self.qty,self.price

此类中的对象最终会作为字典键的值导入。每个键可以存在多个值,存储在列表中,这样当打印字典时,它会返回类似的内容(为了便于阅读,使用换行符)。

Lemon: [(Yellow, 5, 2.99)]
Apple: [(Red, 10, 0.99), (Green, 9, 0.69)]
Cherry: [(White, 2, 5.99),(Red, 5, 5.99)]

我现在正试着在我想象中的水果摊上得到所有水果的总和值。我原来的想法只是将每个值视为一个列表,遍历列表直到我点击一个整数,将整数乘以它后面的索引中的浮点数,然后将该数量添加到具有运行总计的变量中;然后继续寻找另一个整数。如果列表“Cherry”的“索引1”不是(红色,5,5.99)而不是(2),哪个会很好用。

所以,有几个问题。

  1. 每次我做这样的事情,我都有一个多个值的dictonary,它们都是类对象,每个值都存储为一个括号(因为没有更好的东西可以调用它。)是这样的东西应该发生什么,或者我是否需要重新评估我正在做的事情,因为我导致这种情况发生?

  2. 如果我不需要在这里重新评估我的选择,有没有办法打破“括号”(因为没有更好的事情可以立刻让他们想起来)能够把整件事当作一份清单?

  3. 有没有更好的方法来做我想要做的事情而不涉及迭代列表?

  4. 提前致谢。我已经和这个问题的各个部分打了一个星期。

3 个答案:

答案 0 :(得分:6)

假设这样的字典:

fruit_stand = {
    "Lemon": [(Yellow, 5, 2.99)],
    "Apple": [(Red, 10, 0.99), (Green, 9, 0.69)],
    "Cherry": [(White, 2, 5.99),(Red, 5, 5.99)]
}

您实际上可以迭代字典以获取其密钥:

for fruit_name in fruit_stand:
    print fruit_name

# Lemon
# Apple
# Cherry
# NOTE: Order not guaranteed
# Cherry, Lemon, Apple are equally likely

然后,您可以使用字典的items方法获取keyvalue对的元组(您称之为“括号”):

for fruit_name, fruits in fruit_stand.items():
    print fruit_name, "=>", fruits

# Lemon => [(Yellow, 5, 2.99)]
# Apple => [(Red, 10, 0.99), (Green, 9, 0.69)]
# Cherry => [(White, 2, 5.99),(Red, 5, 5.99)]

list s(这是括号内的[])也是可迭代的:

for fruit in [(White, 2, 5.99),(Red, 5, 5.99)]:
    print fruit

# (White, 2, 5.99)
# (Red, 5, 5.99)

因此,我们可以使用每个fruits列表来访问我们的tuple

for fruit_name, fruit_list in fruit_stand.items():
    # Ignore fruit_name and iterate over the fruits in fruit_list
    for fruit in fruit_list:
        print fruit

正如我们在items看到的那样,我们可以将元组解包为多个值:

x, y = (1, 2)
print x
print y
# 1
# 2

因此我们可以将每个fruit解压缩到其组成部分:

for fruit_name, fruit_list in fruit_stand.items():
    # Ignore fruit_name and iterate over the fruits in fruit_list
    for color, quantity, cost in fruit_list:
        print color, quantity, cost

然后获得总数并不难:

# We need to store our value somewhere
total_value = 0
for fruit_name, fruit_list in fruit_stand.items():
    # Ignore fruit_name and iterate over the fruits in fruit_list
    for color, quantity, cost in fruit_list:
        total_value += (quantity * cost)

print total_value

所有这一切,都有很多更清晰的做事方式:

  1. 您可以使用列表推导来简化for循环:

    for fruit_name in fruit_stand
        operation(fruit_name)
    

    可以翻译成这个列表理解:

    [operation(fruit_name) for fruit_name in fruit_stand]
    

    因此,我们可以将嵌套的for循环转换为:

    sum([cost * quantity \  # Final operation goes in front
        for _, fruits in fruit_stand.items() \
            for _, cost, quantity in fruits])
    

    因为我们实际上不需要列表我们可以摆脱它而Python会为我们创建一个生成器:

    sum(cost * quantity \  # Note the missing []
        for _, fruits in fruit_stand.items() \
            for _, cost, quantity in fruits)
    
  2. 您可以向__add__添加Fruit方法,以便将两组水果组合在一起,可以得出两组Fruit的总费用(但您可能想要要创建一个中间数据结构来做到这一点,比如说Basket所以Fruit不必担心quantity并不真正属于Fruit,除了感觉Fruit的任何实例都有内在数量1.我省略了这个选项的代码,因为这个答案已经太长了。

答案 1 :(得分:3)

您要找的单词是"tuple"。这些“括号”是tuples

Python的主要优势之一是它用于迭代列表的紧凑语法。您可以在一行中计算每种水果的价格总和:

>>> fruit = [("Red", 10, 0.99), ("Green", 9, 0.69)]
>>> sum(qty * price for color, qty, price in fruit)
16.11

将其分解,sum()内的内容称为generator expressionfor color, qty, price in fruit遍历fruit并将元组解压缩为三个命名变量。然后可以在for的左侧使用这些变量。对于fruit列表中的每个元组,生成器表达式计算qty * price

如果您将此表达式放在方括号内,它将变为list comprehension并让您查看计算值。

>>> [qty * price for color, qty, price in fruit]
[9.9, 6.209999999999999]

答案 2 :(得分:1)

我首先抛弃returnFoo方法,因为它只是缩短apple.price类型:

class Fruit(object)
    def __init__(self, name, qty, price)
        self.color = str(color)
        self.qty = int(qty)
        self.price = float(price)

如果您不接受qty='100'之类的任意输入,则不需要类型转换:

class Fruit(object)
    def __init__(self, name, qty, price)
        self.color = color
        self.qty = qty
        self.price = price

你剩下的是一个除了存储值之外什么都不做的类。在这种情况下,我只会使用字典:

fruit = {
    'color': 'red',
    'qty': 1000,
    'price': 1.99
}

为了增加成本,首先需要成果:

fruits = [{
    'color': 'red',
    'qty': 1000,
    'price': 1.99
}, {
    'color': 'blue',
    'qty': 100,
    'price': 15.99
}, {
    'color': 'orange',
    'qty': 10,
    'price': 5.99
}]

然后你可以使用for循环:

total = 0

for fruit in fruits:
    total += fruit['qty'] * fruit['price']

可以使用sum和生成器表达式进一步简化:

total = sum(fruit['price'] * fruit['qty'] for fruit in fruits)

另一种方法是使用FruitStand类和原始Fruit类:

class FruitStand(object):
    def __init__(self, fruits=None):
        self.fruits = fruits or []

    def totalCost(self):
        return sum(fruit.price * fruit.qty for fruit in self.fruits)