【问题标题】:Getting an "AttributeError" when trying to use a class function that calls another function from that class inside a second class尝试使用在第二个类中从该类调用另一个函数的类函数时出现“AttributeError”
【发布时间】:2019-07-04 04:39:10
【问题描述】:

我正在编写一个小程序,它使用 pickle 让人们在本地将他们的时间表/工资单保存到他们的计算机上。

我有以下课程:

class ScheduleDataService:

    def create_object_path(self, active_user):

        users_object_path = root / "user_objects" / active_user
        return users_object_path

    def save_users_schedule(self, users_schedule, users_object_path, active_user):
        schedule = open(users_object_path, "wb")
        pickle.dump(users_schedule, schedule)
        schedule.close()

        logger.debug("\nYour schedule has been successfully saved \n")
        logger.info(active_user + "has successfully saved their schedule.")

    def load_users_schedule(self, active_user):
        users_object_path = self.create_object_path(active_user)
        schedule = open(users_object_path, "rb")
        users_schedule = pickle.load(schedule)
        schedule.close()

        return users_schedule

在这个类中,我在类函数“load_users_schedule”中调用类函数“create_object_path”。

在同一个模块中,我有第二个类用于查看用户当前的日程安排:

class ViewSchedule:

    __schedule_data_service: ScheduleDataService

    def __init__(self, schedule_data_service):
        self.__schedule_data_service = schedule_data_service

    def view_day(self, day_to_see, active_user):
        users_schedule = self.__schedule_data_service.load_users_schedule(self, active_user)


        to_view = []

        if day_to_see == "1":
            to_view.append("Monday")
        elif day_to_see == "2":
            to_view.append("Tuesday")
        elif day_to_see == "3":
            to_view.append("Wednesday")
        elif day_to_see == "4":
            to_view.append("Thursday")
        elif day_to_see == "5":
            to_view.append("Friday")
        elif day_to_see.lower() == "all":
            to_view = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
        else:
            logger.debug("Sorry that isn't a valid option please try again")
            logger.info(active_user + "failed to view " + day_to_see + " from their schedule due to incorrect input")
            pass

        for day in users_schedule.week:
            if day.name in to_view:
                logger.debug("")
                for session in day.sessions:
                    logger.debug("Day: " + day.name + " Class Code: " + session.code + " Class length: "
                                 + session.length)
                logger.debug("")

我试图让这个类是上面类的自己的实例。然后我试图调用“load_users_schedule”函数来加载用户日程。当我这样做时,我收到以下错误。

File "generator.py", line 116, in <module>
    ViewSchedule(ScheduleDataService).view_day(day_to_see, active_user)
  File "/shared/projects/pay_sheet_generator/schedule_data.py", line 249, in view_day
    users_schedule = self.__schedule_data_service.load_users_schedule(self, active_user)
  File "/shared/projects/pay_sheet_generator/schedule_data.py", line 40, in load_users_schedule
    users_object_path = self.create_object_path(active_user)
AttributeError: 'ViewSchedule' object has no attribute 'create_object_path'

当我从“load_users_schedule”中删除“create_object_path”并独立运行它们时,代码可以正常工作。如上所示,我正在寻找一种能够将函数相互嵌入的方法,或者解释为什么我不应该这样做。

编辑:

对 ViewSchedule 的调用如下所示

ViewSchedule(ScheduleDataService).view_day(day_to_see, active_user)

【问题讨论】:

  • 您能补充一下您是如何创建ViewSchedule 的对象的吗?另外,您为什么要使用 dunder 变量 __schedule_data_service
  • 调用self.__schedule_data_service.load_users_schedule(self, active_user) - 您无需传递self。一般来说,你几乎不需要通过self
  • @DeveshKumarSingh 我已经添加了对 ViewSchedule 的调用,该调用发生在触发错误的程序的主要流程中。我将它列为一个 dunder 变量,因为我希望它被视为私有的,不是一个可以玩的区域。
  • 您应该注意使用 dunder 变量对名称进行修改,而不是使用单个下划线
  • 另外你为什么不使用ScheduleDataService 的实例来传递给ViewSchedule 构造函数?本质上是ViewSchedule(ScheduleDataService()).view_day(day_to_see, active_user)

标签: python function object


【解决方案1】:

您的代码中存在一些问题。

  1. users_schedule = self.__schedule_data_service.load_users_schedule(self, active_user)这一行,你不需要添加self作为第一个参数,因为当你用实例调用一个类的方法时,第一个参数会自动插入该实例的实例类

  2. 您需要将ScheduleDataService 的实例传递给ViewSchedule 的实例,因此您需要使用ViewSchedule(ScheduleDataService()).view_day(day_to_see, active_user) 而不是ViewSchedule(ScheduleDataService).view_day(day_to_see, active_user)

  3. 另外你应该知道,dunder 变量在 python 中是 name-mangled,因此在你的课堂上小心使用它们

【讨论】:

    【解决方案2】:

    这有点像你想要的。如果人们可以复制和运行您的代码,这将很有帮助。您的代码中没有包含多个变量和导入。

    import pickle
    import logging
    
    root = ""
    logger = logging.getLogger()
    
    
    class ScheduleDataService:
    
        def create_object_path(self, active_user):
    
            users_object_path = root + "user_objects" + active_user
            return users_object_path
    
        def save_users_schedule(self, users_schedule, users_object_path, active_user):
            schedule = open(users_object_path, "wb")
            pickle.dump(users_schedule, schedule)
            schedule.close()
    
            logger.debug("\nYour schedule has been successfully saved \n")
            logger.info(active_user + "has successfully saved their schedule.")
    
        def load_users_schedule(self, active_user):
            users_object_path = self.create_object_path(active_user)
            schedule = open(users_object_path, "rb")
            users_schedule = pickle.load(schedule)
            schedule.close()
    
            return users_schedule
    
    
    class ViewSchedule:
    
        # This gets automatically created inside __init__       __schedule_data_service: ScheduleDataService
    
        def __init__(self, schedule_data_service):
            self.__schedule_data_service = schedule_data_service
    
        def view_day(self, day_to_see, active_user):
            users_schedule = self.__schedule_data_service.load_users_schedule(active_user)
    
    
            to_view = []
    
            if day_to_see == "1":
                to_view.append("Monday")
            elif day_to_see == "2":
                to_view.append("Tuesday")
            elif day_to_see == "3":
                to_view.append("Wednesday")
            elif day_to_see == "4":
                to_view.append("Thursday")
            elif day_to_see == "5":
                to_view.append("Friday")
            elif day_to_see.lower() == "all":
                to_view = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
            else:
                logger.debug("Sorry that isn't a valid option please try again")
                logger.info(active_user + "failed to view " + day_to_see + " from their schedule due to incorrect input")
                pass
    
            for day in users_schedule.week:
                if day.name in to_view:
                    logger.debug("")
                    for session in day.sessions:
                        logger.debug("Day: " + day.name + " Class Code: " + session.code + " Class length: "
                                 + session.length)
                    logger.debug("")
    
    
    active_user = "Bob"
    day_to_see = 1
    
    scheduleDataSvc = ScheduleDataService()
    vs = ViewSchedule(scheduleDataSvc)
    
    vs.view_day(day_to_see, active_user)  
    

    【讨论】:

    • 另外,您不能将字符串与\ 结合使用。你需要+
    • 很抱歉缺少导入。我会确保在下次发布时包括这些内容。 \n 是打印一个新行(它确实如此)而不是组合字符串。组合字符串时,我使用 +.
    • 不用担心。我的意思是:users_object_path = root / "user_objects" / active_user
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 2017-08-10
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多