1

我正在构建一个knapsack将(另一个类)列表Items作为参数的类。每个物品都有一个重量和一个价值,一个背包应该有一个总重量(所有的总和item.weights)和总价值(所有的总和item.values)。

我想要完成的knapsack.total_weightknapsack.total_valueknapsack.items.append(new_item).

到目前为止,我已经尝试过装饰items,total_weighttotal_valuewith @property,但它似乎不起作用。关于如何正确使用属性装饰器的任何想法,或者我应该查看不同的实现?

class Item:
    def __init__(self,name:str,weight:int,value:int):
        self.name = name
        self.weight = weight
        self.value = value

    def __str__(self):
        return f'{self.name}: {self.weight}kg ({self.value})'

class Knapsack:

    def __init__(self,items=[],max_weight=250,score=None,weight=None):
        self.max_weight = max_weight
        self._items = items
        self._score = score
        self._weight = weight

    @property
    def items(self):
        return self._items

    @items.setter
    def items(self,new_item):
        self._items += [new_item]
        self._score = self._items
        self._weight = self._items

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self,items):
        total_score = 0
        for item in items:
            total_score += item.value
        self._score = total_score

    @property
    def weight(self):
        return self._weight

    @weight.setter
    def weight(self,items):
        total_weight = 0
        for item in items:
            total_weight += item.weight
        self._weight = total_weight

    def __str__(self):
        out = [item.name for item in self.items]
        return f'{"".join(out)}\t{self.score}'
4

2 回答 2

1

你有正确的想法,但你似乎对 OOP 有点陌生。这样的事情怎么样?

class Item:
    def __init__(self, name, value, weight):
        self.name = name
        self.value = value
        self.weight = weight


class Knapsack:
    def __init__(self, max_weight):
        self._items = []
        self.max_weight = max_weight

    @property
    def total_weight(self):
        return sum(i.weight for i in self._items)

    @property
    def total_value(self):
        return sum(i.value for i in self._items)

    def add(self, item):
        if self.total_weight + item.weight > self.max_weight:
            raise ValueError("that ain't gonna fit in there")
        self._items.append(item)

sack = Knapsack(100)
sack.add(Item('a', 1, 10))
sack.add(Item('b', 1, 20))
sack.add(Item('c', 1, 30))

print('Total weight: ', sack.total_weight)
print('Total value: ', sack.total_value)

try:
    sack.add(Item('too big', 1, 50))
except ValueError as e:
    print(e)

更新:

一些笔记。您可以按照您的方式实现项目设置器,但由此产生的用法会违反直觉,您必须执行sack.items = item添加项目之类的操作。您不想为重量或价值定义设置器,因为它们仅在项目更改时才会更改,并且不能单独更改。您可以尝试使 Knapsack 成为列表的子类,但您必须实现一堆“秘密”方法才能使其工作,我认为对于初学者来说,这有点太麻烦了,但收效甚微。

更新更新:

请注意,以上不是高质量的代码,仅用于说明实现。例如,我会做sack.add(Item('x', 'x', 'x'))并打破整个事情。

于 2019-09-23T20:40:29.910 回答
0

您似乎没有有效地使用这些类。父类的子类会继承父类的属性。您可以使用该方法修改这些或添加属性super().__init__。在输出示例中:

class Item:
    def __init__(self, name, weight, value):
        self.name = name
        self.weight = weight
        self.value = value


item = Item('Random_Item', 0, 0)
print('Name: {} \nWeight: {} \nValue: {} '.format(item.name, item.weight, item.value))


class Knapsack(Item):
    def __init__(self, max_weight, score):
        self.max_weight = max_weight
        self.score = score
        super().__init__('A_different_random_item', weight=0, value=0)


knapsack = Knapsack(250, None)
print('Name: {} \nMax Weight: {} \nScore: {} \nValue: {}'.format(knapsack.name, knapsack.max_weight, knapsack.score, knapsack.value))

这给出了输出:

Name: Random_Item 
Weight: 0 
Value: 0
Name: A_different_random_item 
Max Weight: 250 
Score: None 
Value: 0

编辑添加评论

heavy_stone = Item('Wood', weight=251, value=20)

choice = input('Put stone in knapsack: ')
if choice.lower() == 'y' and heavy_stone.weight < 250:
    pass ### ADD ITEM ###
else:
    print('Sorry that weighs {} and is too heavy for your knapsack. It can only hold {}'.format(heavy_stone.weight, knapsack.max_weight))

输出:

Put stone in knapsack: y
Sorry that weighs 251 and is too heavy for your knapsack. It can only hold 250

这样,您可以从父类创建项目并使用背包类的属性

于 2019-09-22T10:43:55.790 回答