自动更新 class 个属性
Auto updating class properties
我正在构建一个 knapsack
class,它将 Items
(另一个 class)的列表作为参数。
每件物品都有重量和价值,背包应该有总重量(所有item.weights
的总和)和总价值(所有item.values
的总和)。
我想要完成的是让 knapsack.total_weight
和 knapsack.total_value
在我 knapsack.items.append(new_item)
时自动更新。
到目前为止,我已经尝试用 @property
装饰 items
、total_weight
和 total_value
,但它似乎不起作用。关于如何正确使用 属性 装饰器的任何想法,或者我应该看看不同的实现吗?
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}'
您似乎没有有效地使用 classes。 parent class 的子class 将继承parent class 的属性。您可以使用 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
这样你就可以从你的 parent class 中创建你的项目并使用背包中的属性 class
你的想法是正确的,但你似乎对 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)
更新:
一些注意事项。您可以按照您的方式实现项目 setter,但由此产生的用法是违反直觉的,您必须执行类似 sack.items = item
的操作才能添加项目。您不想为重量或价值定义 setters,因为它们仅在项目更改时更改,不能单独更改。您可以尝试使 Knapsack 成为列表的子类,但是您必须实现一堆 "secret" 方法才能使其工作,我认为对于初学者来说,这有点麻烦。
更新更新:
请注意,以上内容并非优质鳕鱼,仅用于说明实现。例如,我会做 sack.add(Item('x', 'x', 'x'))
并破坏整个事情。
我正在构建一个 knapsack
class,它将 Items
(另一个 class)的列表作为参数。
每件物品都有重量和价值,背包应该有总重量(所有item.weights
的总和)和总价值(所有item.values
的总和)。
我想要完成的是让 knapsack.total_weight
和 knapsack.total_value
在我 knapsack.items.append(new_item)
时自动更新。
到目前为止,我已经尝试用 @property
装饰 items
、total_weight
和 total_value
,但它似乎不起作用。关于如何正确使用 属性 装饰器的任何想法,或者我应该看看不同的实现吗?
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}'
您似乎没有有效地使用 classes。 parent class 的子class 将继承parent class 的属性。您可以使用 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
这样你就可以从你的 parent class 中创建你的项目并使用背包中的属性 class
你的想法是正确的,但你似乎对 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)
更新:
一些注意事项。您可以按照您的方式实现项目 setter,但由此产生的用法是违反直觉的,您必须执行类似 sack.items = item
的操作才能添加项目。您不想为重量或价值定义 setters,因为它们仅在项目更改时更改,不能单独更改。您可以尝试使 Knapsack 成为列表的子类,但是您必须实现一堆 "secret" 方法才能使其工作,我认为对于初学者来说,这有点麻烦。
更新更新:
请注意,以上内容并非优质鳕鱼,仅用于说明实现。例如,我会做 sack.add(Item('x', 'x', 'x'))
并破坏整个事情。