63451


やろうとしたことを満たすコードを書いたのですが、BaseNutritionクラスのメソッドnutrition_calculatorがなんとなく、汚い（冗長なコードのような気がする）のですが、もっときれいに書く方法はありますか？初心者で正直、関数、クラスの使い訳もうまくできないと思います。正直このようなコードをクラスで書くべきかどうかもわかりません。何がいいコードで何が悪いのかよくわからないので、見ていただきたいと思いました。改善できるところがありましたら教えていただけると嬉しいです。（あいまいな質問ですいません。）

やろうとしたこと。  
まず、BaseNutritionクラスで食べ物の総量、総量グラムに対するタンパク質、炭水化物、脂質の属性を作った。  
そして、BaseNutritionオブジェクトに栄養価の辞書データを与えることで、その食べ物を何グラムかを、nutrition_calculatorメソッドに渡すことによって、渡した重さに対する栄養価がわかるようなコードを書きました。

[code]

    class BaseNutrition():
    
        def __init__(self, amount, kcal, carbohydrates, protein, fat):
            self.amount = amount
            self.kcal_per_gram = kcal / amount
            self.carbohydrates_per_gram = carbohydrates / amount
            self.protein_per_gram =  protein / amount
            self.fat_per_gram = fat / amount
    
        def nutrition_calculator(self, grams):
            kcal = round(grams * self.kcal_per_gram,1)
            carbs = round(grams * self.carbohydrates_per_gram,1)
            protein = round(grams * self.protein_per_gram, 1)
            fat = round(grams * self.fat_per_gram, 1)
    
            result_calculation = []
            result_calculation.append(kcal)
            result_calculation.append(carbs)
            result_calculation.append(protein)
            result_calculation.append(fat)
    
            return result_calculation
    
    chiken_nutrition = {"kcal":116,
              "carbohydrates": 0,
              "protein": 19,
              "fat": 4 ,
              "amount": 100}
    
    chiken = BaseNutrition(**chiken_nutrition)
    
    
    print(chiken.nutrition_calculator(200)) # [232.0, 0.0, 38.0, 8.0]
    
[/code]


CC BY-SA 4.0
2020-02-28T14:20:36.203
63439
2020-02-29T03:18:18.827
2020-02-29T01:43:23.857
3060
36091
question
python python3
うまいclassの書き方


そうですね、、、この場合、クラスではなく関数でも十分ではないかと思います。

[code]

    def nutrition_calculator(base, amount):
      return [
        round(amount * val / base['amount'], 1)
        for attr, val in base.items() if attr != 'amount'
      ]
    
    if __name__=='__main__':
    
      chiken_nutrition = {
        'kcal':          116,
        'carbohydrates':   0,
        'protein':        19,
        'fat':             4,
        'amount':        100,
      }
    
      print(nutrition_calculator(chiken_nutrition, 200))
    
[/code]

とは言うものの、例えば `chiken_nutrition` に `amount` キーがない場合などのエラー処理がありませんし、出力結果が

[code]

    [232.0, 0.0, 38.0, 8.0]
    
[/code]

となっていて、それぞれの数値がどの属性に対応するのか判然としません(Python 3.6以降では辞書のキーの順序が挿入順になりますけれども)。

以下のコードでは、エラー処理を追加して、戻り値を dict 型のインスタンスにしています。参考にしてみて下さい。

[code]

    import sys
    
    class BaseNutrition(object):
      base_key = 'amount'
    
      def __init__(self, nutri):
        self.nutri = nutri
    
      def __enter__(self):
        try:
          self.amount = self.nutri[self.base_key]
          1 / self.amount
        except:
          self.__exit__(*sys.exc_info())
          return None
    
        return self
    
      def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is None:
          return
        elif exc_type == KeyError:
          print(f"`{self.base_key}' is not found.")
        elif exc_type == TypeError:
          print(f"`{self.base_key}' is not a number.")
        elif exc_type == ZeroDivisionError:
          print(f"`{self.base_key}' is zero.")
        else:
          print(exc_type, exc_value, traceback)
    
      def calculator(self, amount):
        return {
          attr:
            amount if attr == self.base_key
                   else round(amount * val / self.amount, 1)
          for attr, val in self.nutri.items()
        }
    
    if __name__=='__main__':
    
      chiken_nutrition = {
        'kcal':          116,
        'carbohydrates':   0,
        'protein':        19,
        'fat':             4,
        'amount':        100,
      }
    
      with BaseNutrition(chiken_nutrition) as chiken:
        if chiken is not None:
          print(chiken.calculator(amount=200))
          print(chiken.calculator(amount=50))
    
    =>
    {'kcal': 232.0, 'carbohydrates': 0.0, 'protein': 38.0, 'fat': 8.0, 'amount': 200}
    {'kcal': 58.0, 'carbohydrates': 0.0, 'protein': 9.5, 'fat': 2.0, 'amount': 50}
    
[/code]


CC BY-SA 4.0
2020-02-29T03:18:18.827
63451
2020-02-29T03:18:18.827
63439
answer