【问题标题】:Can someone help me passing a function as argument in python?有人可以帮我在python中传递一个函数作为参数吗?
【发布时间】:2020-06-23 12:36:00
【问题描述】:

我在 python 中有以下类。我想将函数 get_priority 作为访问对象任务的参数传递。将第二个任务添加到 taskManager 时出现以下错误:

如果 value == array[int(middle)].accessMethod(): AttributeError: Task 实例没有属性“accessMethod”

任务类

class Task:

    def __init__(self,id,name,category="",priority=1):
        self.id = id
        self.name = name
        self.category = category
        self.priority = priority
        self.concluded = False
        self.active_days = 0
        print("Beggining Class")

    def get_name(self):
        return self.name

    def get_category(self):
        return self.category

    def get_priority(self):
        return self.priority

    def set_name(self,name):
        self.name = name

    def set_category(self,category):
        self.category = category

    def set_priority(self,priority):
        self.priority = priority

    def __str__(self):
        return str(self.id) + " | " + self.name + " | " + self.category + " | " + str(self.priority) + " | "

任务管理器类

from task import Task

class TaskManager(object):
    """docstring forTaskManager."""

    def __init__(self):
        print("Initing TaskManager")
        self.taskArray = []

    """Adding task ordered by priority"""
    """Maibe adding a check for autheticity of the object """
    def addTask(self,task):
        if len(self.taskArray) == 0 or self.taskArray[0].get_priority() <= task.get_priority():
            self.taskArray.insert(0,task)
        else:
            index = self.__binarySearchIndex(task.get_priority,self.taskArray,'get_priority')
            self.taskArray.insert(index,task)

    def __binarySearchIndex(self,value,array,acessMethod):
        middle = (len(self.taskArray) / 2) if ((len(self.taskArray) % 2) == 0) else (len(self.taskArray) / 2) + 1
        if middle == 1:
            middle = 0
        if value == array[middle].acessMethod():
            return middle
        elif value < array[middle].acessMethod():
            self.__binarySearchIndex(value,array[:middle])
        else:
            self.__binarySearchIndex(value,array[middle:])

    def __str__(self):
        taskString = ""
        for task in self.taskArray:
            taskString = taskString + str(task) + " \n"
        return taskString

【问题讨论】:

  • Task 类不需要那么多不必要的getter 和setter。直接访问属性,直到需要保护访问,此时您可以用属性替换它们而不影响现有代码。

标签: python function functional-programming arguments


【解决方案1】:

使用 getattr 从你传递的字符串中获取函数

method_to_call = getattr(Task, accessMethod)

if value == array[middle].method_to_call():

【讨论】:

    【解决方案2】:

    我实际上采用了另一种方式,而不是通过名称调用方法,我只是创建了一个 lambda 函数来从 Task 对象中提取我想要的任何属性。

    class Task:
    
        def __init__(self,id,name,category="",priority=1):
            self.id = id
            self.name = name
            self.category = category
            self.priority = priority
            self.concluded = False
            self.active_days = 0
            print("Beggining Class")
    
        def get_name(self):
            return self.name
    
        def get_category(self):
            return self.category
    
        def get_priority(self):
            return self.priority
    
        def set_name(self,name):
            self.name = name
    
        def set_category(self,category):
            self.category = category
    
        def set_priority(self,priority):
            self.priority = priority
    
        def __str__(self):
            return str(self.id) + " | " + self.name + " | " + self.category + " | " + str(self.priority) + " | "
    
    class TaskManager(object):
        """docstring forTaskManager."""
    
        def __init__(self):
            print("Initing TaskManager")
            self.taskArray = []
    
        """Adding task ordered by priority"""
        """Maibe adding a check for autheticity of the object """
        def addTask(self,task):
            if len(self.taskArray) == 0 or self.taskArray[0].get_priority() <= task.get_priority():
                self.taskArray.insert(0,task)
            else:
                index = self.__binarySearchIndex(task.get_priority(),self.taskArray, lambda task: task.get_priority())
                self.taskArray.insert(index,task)
    
        def __binarySearchIndex(self,value,array,accessMethod):
            if len(array) == 0:
                return 0
            middle = (len(self.taskArray) / 2) if ((len(self.taskArray) % 2) == 0) else (len(self.taskArray) // 2) + 1
            if middle == 1:
                middle = 0
            if value == accessMethod(array[middle]):
                return middle
            elif value < accessMethod(array[middle]):
                return middle + self.__binarySearchIndex(value,array[:middle],accessMethod)
            else:
                return middle - self.__binarySearchIndex(value,array[middle:],accessMethod)
    
        def __str__(self):
            taskString = ""
            for task in self.taskArray:
                taskString = taskString + str(task) + " \n"
            return taskString
    
    if __name__ == "__main__":
        taskA = Task(1, "taskA", priority=2)
        taskB = Task(2, "taskB", priority=1)
        taskC = Task(3, "taskC", priority=1)
        taskD = Task(4, "taskD", priority=3)
        manager = TaskManager()
        manager.addTask(taskA)
        manager.addTask(taskB)
        manager.addTask(taskC)
        manager.addTask(taskD)
        for task in manager.taskArray:
            print(task)
    
    

    我还帮助调试了您的程序。对于初学者,您对二分搜索的递归调用不会返回值,这是您想要的行为。

    【讨论】:

      【解决方案3】:

      根本不传递包含名称的字符串。使用methodcaller 函数。

      例如:

      from operator import methodcaller
      
      
      class TaskManager(object):
      
          def __init__(self):
              self.taskArray = []
      
          def addTask(self, task):
              if (len(self.taskArray) == 0
                  or self.taskArray[0].get_priority() <= task.get_priority():
                  self.taskArray.insert(0,task)
              else:
                  index = self.__binarySearchIndex(
                      task.get_priority(),
                      self.taskArray,
                      methodcaller('get_priority')
                  )
                  self.taskArray.insert(index, task)
      
          def __binarySearchIndex(self, value, array, accessMethod):
              middle = (len(self.taskArray) / 2) if ((len(self.taskArray) % 2) == 0) else (len(self.taskArray) / 2) + 1
              if middle == 1:
                  middle = 0
              if value == accessMethod(array[middle]):
                  return middle
              elif value < accessMethod(array[middle]):
                  self.__binarySearchIndex(value,array[:middle])
              else:
                  self.__binarySearchIndex(value,array[middle:])
      
          ...

      如果您简化 Task 类以摆脱不必要的 getter 和 setter:

      class Task:
      
          def __init__(self,id,name,category="",priority=1):
              self.id = id
              self.name = name
              self.category = category
              self.priority = priority
              self.concluded = False
              self.active_days = 0
              print("Beggining Class")
      
          def __str__(self):
              return str(self.id) + " | " + self.name + " | " + self.category + " | " + str(self.priority) + " | "
      

      那么您可以使用attrgetter 代替methodcaller

      from operator import attrgetter
      
      class TaskManager(object):
      
          def __init__(self):
              self.taskArray = []
      
          def addTask(self, task):
              if (len(self.taskArray) == 0
                  or self.taskArray[0].get_priority() <= task.get_priority:
                  self.taskArray.insert(0,task)
              else:
                  index = self.__binarySearchIndex(
                      task.get_priority, 
                      self.taskArray,
                      attrgetter('get_priority')
                  )
                  self.taskArray.insert(index, task)
      
          def __binarySearchIndex(self, value, array, accessMethod):
              middle = (len(self.taskArray) / 2) if ((len(self.taskArray) % 2) == 0) else (len(self.taskArray) / 2) + 1
              if middle == 1:
                  middle = 0
              if value == accessMethod(array[middle]):
                  return middle
              elif value < accessMethod(array[middle]):
                  self.__binarySearchIndex(value,array[:middle])
              else:
                  self.__binarySearchIndex(value,array[middle:])
      
          ...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-28
        相关资源
        最近更新 更多