【问题标题】:python repeats function 3 timespython重复函数3次
【发布时间】:2020-09-09 17:04:08
【问题描述】:

这段代码的目的是:

  1. 要求用户输入他的姓名。
  2. 要求用户输入他的出生日期
  3. 代码会将姓名拆分为名字、中间名和姓氏
  4. 代码将以年、月和日为单位计算年龄。
  5. 代码会将所有这些数据存储在字典中

代码如下:

from datetime import datetime
from dateutil.relativedelta import relativedelta


    class Test:
        def __init__(self):
            self.today = datetime.today()
    
        def name(self):
            first_name, middle_name, last_name = input("enter your name:\n".title()).split(' ')
            return first_name, middle_name, last_name
    
        def age(self):
            date_of_birth = input("enter your date of birth:\n")
            date_of_birth = datetime.strptime(date_of_birth, "%d/%m/%Y")
            age = relativedelta(self.today, date_of_birth)
            return age
    
        def data(self):
            data = {"first name": self.name()[0],
                    "middle_name": self.name()[1],
                    "last name": self.name()[2],
                    "age years": self.age().years,
                    "age months": self.age().months,
                    "age days": self.age().days}
            print(data)
    
    
    Test().data()

代码没有错误。

但是名字和年龄的问题每个重复了三遍。 像这样的

输入您的出生日期:

26/9/1986

输入您的出生日期:

26/9/1986

输入您的出生日期:

26/9/1986

【问题讨论】:

  • 每次你打电话给self.age(你打了三遍),它都会问问题,与self.name类似
  • self.name() 称为名称函数。调用一次,将结果存储在变量中,然后构建字典
  • 在将变量加载到 data 字典之前,您应该将 self.name() 分配给变量。

标签: python user-input


【解决方案1】:

您拨打了三遍age()。你可以调用它一次,然后访问它的成员:

def data(self):
    name = self.name()
    age = self.age()
    data = {"first name": name[0],
            "middle_name": name[1],
            "last name": name[2],
            "age years": age.years,
            "age months": age.months,
            "age days": age.days}
    print(data)

【讨论】:

  • 你不想这样拆分名字
【解决方案2】:

我建议您使用实例并在init方法本身中调用名称输入,如下所示:

class Test:
    def __init__(self):
        self.today = datetime.today()
        self.full_name = input("enter your full name:\n".title()).split(' ')
        self.dob = input("enter your date of birth:\n")

    @property
    def name(self):
        first_name, middle_name, last_name = self.full_name
        return first_name, middle_name, last_name

    @property
    def age(self):
        date_of_birth = self.dob
        date_of_birth = datetime.strptime(date_of_birth, "%d/%m/%Y")
        age = relativedelta(self.today, date_of_birth)
        return age

    def data(self):
        data = {"first name": self.name[0],
                "middle_name": self.name[1],
                "last name": self.name[2],
                "age years": self.age.years,
                "age months": self.age.months,
                "age days": self.age.days}
        print(data)

所以当您实例化类对象时,您实际上将初始化您需要的值作为__init__ 方法中的输入,然后在您需要使用的任何时候使用数据方法,它将值存储到变量中,直到您重新实例化它。

【讨论】:

    【解决方案3】:

    您分别调用了self.ageself.name 三次。您应该只调用它们中的每一个,并将结果保存到相关变量中。

    也许最好将这些变量设置为实例的属性以备将来使用,但作为对问题的最低限度的修复,这里有一个 data 版本,它只执行一次相关调用。

        def data(self):
    
            first_name, middle_name, last_name = self.name()
            
            age = self.age()
            
            data = {"first name": first_name,
                    "middle_name": middle_name,
                    "last name": last_name,
                    "age years": age.years,
                    "age months": age.months,
                    "age days": age.days}
            print(data)
    

    【讨论】:

      【解决方案4】:

      您的 nameage 函数会在您每次调用它们时重新提示用户输入新的输入。缓存它们可能会更好;您可以通过将其存储为实例属性来自己执行此操作,或者只使用functools.lru_cache

      from functools import lru_cache
      
      ...
      
          @lru_cache
          def name(self):
              first_name, middle_name, last_name = input("enter your name:\n".title()).split(' ')
              return first_name, middle_name, last_name
      
          @lru_cache
          def age(self):
              date_of_birth = input("enter your date of birth:\n")
              date_of_birth = datetime.strptime(date_of_birth, "%d/%m/%Y")
              age = relativedelta(self.today, date_of_birth)
              return age
      

      【讨论】:

      • 这是一个非常糟糕的使用 lru 缓存的方法