令人困惑的对象组合 python 代码

A confusing object composition python code

目前,我正在 python 参加在线速成课程,遇到了一个令人困惑的代码。

如下图,是一个用来找出棉质polo衫数量的代码

 class Clothing:
   stock={ 'name': [],'material' :[], 'amount':[]}
   def __init__(self,name):
     material = ""
     self.name = name
   def add_item(self, name, material, amount):
     Clothing.stock['name'].append(self.name)
     Clothing.stock['material'].append(self.material)
     Clothing.stock['amount'].append(amount)
   def Stock_by_Material(self, material):
     count=0
     n=0
     for item in Clothing.stock['material']:
       if item == material:
         count += Clothing.stock['amount'][n]
         n+=1
     return count

 class shirt(Clothing):
   material="Cotton"
 class pants(Clothing):
   material="Cotton"

 polo = shirt("Polo")
 sweatpants = pants("Sweatpants")
 polo.add_item(polo.name, polo.material, 4)
 sweatpants.add_item(sweatpants.name, sweatpants.material, 6)
 current_stock = polo.Stock_by_Material("Cotton")
 print(current_stock)

明明棉质polo衫的数量是4,而代码给出的答案是棉质polo衫和运动裤的数量之和10(其实也算正确)

我的问题是,polo.Stock_by_Material 方法不应该只在实例 "polo" 中迭代字典中的元素而不是 "polo" 和 "sweatpants" 吗?我的意思是 "polo" 和 "sweatpants" 甚至不在同一个 class 中,所以 polo.Stock_by_Material 方法怎么会计算两个 classes 的数量?

如果我在这里犯了一些愚蠢的错误,请原谅我。我进入 python 仅 1 周,之前没有任何编程经验。非常感谢!

您正在通过 material(棉花)聚合。衬衫和运动裤 class 的 material 属性都设置为棉质。因此,有 10 个棉花项目,这就是您最后显示的内容。

如果你想按item聚合,可以如下图所示。

class Clothing:
   stock={ 'name': [],'material' :[], 'amount':[]}
   def __init__(self,name):
     material = ""
     self.name = name
   def add_item(self, name, material, amount):
     Clothing.stock['name'].append(self.name)
     Clothing.stock['material'].append(self.material)
     Clothing.stock['amount'].append(amount)
   def Stock_by_Material(self, material):
     count=0
     n=0
     for item in Clothing.stock['material']:
       if item == material:
         count += Clothing.stock['amount'][n]
         n+=1
     return count
   def Stock_by_item(self, name):
     count=0
     n=0
     for rec in Clothing.stock['name']:
       if rec == name:
         count += Clothing.stock['amount'][n]
         n+=1
     return count

class shirt(Clothing):
   material="Cotton"

class pants(Clothing):
   material="Cotton"

polo = shirt("Polo")
other_polo_shirts = shirt("Polo")

sweatpants = pants("Sweatpants")
polo.add_item(polo.name, polo.material, 4)
other_polo_shirts.add_item(other_polo_shirts.name, other_polo_shirts.material, 16)

sweatpants.add_item(sweatpants.name, sweatpants.material, 6)
current_stock = polo.Stock_by_item("Polo")
print(current_stock)

如果我答对了你的问题,

stock 是 class 服装的 static 变量。 class 的所有子项都将共享此变量。

因此 polo 和运动裤共享同一个字典。

希望对您有所帮助。

正如@Sagi 提到的那样,returns stock 的所有棉花库存在 Cloathing 及其子 class 对象之间共享。然而,您的困惑是合理的,因为此代码违反了单一责任原则,库存不应成为服装的一部分 class。

Sagi 是正确的。 Stock_by_Material 函数还需要检查 'name' 以确保它是 'Polo',然后才将其添加到计数中。你没有遗漏任何东西,课程的制作者只是犯了一个错误。

在这个条件语句中,在迭代中创建问题,所以尝试将其注释掉。当然你的程序会 运行.

class Clothing:
  stock={ 'name': [],'material' :[], 'amount':[]}
  def __init__(self,name):
    material = ""
    self.name = name
  def add_item(self, name, material, amount):
    Clothing.stock['name'].append(self.name)
    Clothing.stock['material'].append(self.material)
    Clothing.stock['amount'].append(amount)
  def Stock_by_Material(self, material):
    count=0
    n=0
    for item in Clothing.stock['amount']:
      # if item == material:
        count += Clothing.stock['amount'][n]
        n+=1
    return count

class shirt(Clothing):
  material="Cotton"
class pants(Clothing):
  material="Cotton"
  
polo = shirt("Polo")
sweatpants = pants("Sweatpants")
polo.add_item(polo.name, polo.material, 4)
sweatpants.add_item(sweatpants.name, sweatpants.material, 6)
current_stock = polo.Stock_by_Material("Cotton")
print(current_stock)