📜  函子及其在Python中的使用

📅  最后修改于: 2022-05-13 01:55:48.979000             🧑  作者: Mango

函子及其在Python中的使用

让我们先了解函子:
函子是可以被视为函数的对象。

什么时候使用函子?

  • 当您想要隐藏/抽象实际实现时,使用函子。假设您想根据输入调用不同的函数,但您不希望用户代码显式调用这些不同的函数。这是函子可以提供帮助的理想情况。
  • 在这种情况下,我们可以选择一个仿函数,它根据输入在内部调用最合适的函数
  • 现在,如果以后调用的函数都没有增加,那么它只是后端代码的简单更改,而不会干扰任何用户代码。因此函子有助于创建可维护、解耦和可扩展的代码。

让我们通过一个简单的设计问题示例来理解它。问题是设计类/方法,它将根据输入类型调用不同的排序方法。如果输入是 int 类型,则应该调用 Mergesort函数,如果输入是 float 类型,则 Heapsort 否则只需调用 quicksort函数

# Python code to illustrate program 
# without functors 
class GodClass(object): 
      
    def DoSomething(self,x): 
          
        x_first=x[0] 
          
        if type(x_first) is int : 
            return self.__MergeSort(x) 
        if type(x_first) is float : 
            return self.__HeapSort(x) 
        else : 
            return self.__QuickSort(x) 
          
    def __MergeSort(self,a): 
        #" Dummy MergeSort " 
        print ("Data is Merge sorted")
        return a 
      
    def __HeapSort(self,b): 
        # " Dummy HeapSort " 
        print( "Data is Heap sorted")
        return b
      
    def __QuickSort(self,c): 
        # "Dummy QuickSort" 
        print ("Data is Quick sorted")
        return c 
# Here the user code need to know about the conditions for calling different strategy 
# and making it tightly coupled code. 
      
godObject=GodClass() 
print (godObject.DoSomething([1,2,3])) 

输出:

Data is Merge sorted
[1, 2, 3]

这段代码中有一些明显的设计缺陷
1.内部实现应该对用户代码隐藏,即应该维护抽象
2. 每个类都应该处理单一的职责/功能。
2. 代码是紧耦合的。

让我们在Python中使用仿函数来解决同样的问题

# Python code to illustrate program 
# using functors 
  
class Functor(object): 
    def __init__(self, n=10): 
        self.n = n 
              
    # This construct allows objects to be called as functions in python 
    def __call__(self, x) : 
        x_first = x[0] 
        if type(x_first) is int: 
            return self. __MergeSort(x) 
        if type(x_first) is float: 
            return self. __HeapSort(x) 
        else : 
            return self.__QuickSort(x) 
  
    def __MergeSort(self,a): 
        #" Dummy MergeSort " 
        print ("Data is Merge sorted")
        return a 
    def __HeapSort(self,b): 
        # " Dummy HeapSort " 
        print ("Data is Heap sorted")
        return b 
    def __QuickSort(self,c): 
        # "Dummy QuickSort" 
        print ("Data is Quick sorted")
        return c 
  
# Now let's code the class which will call the above functions. 
# Without the functor this class should know which specific function to be called 
# based on the type of input 
  
### USER CODE 
class Caller(object): 
    def __init__(self): 
        self.sort=Functor() 
      
    def Dosomething(self,x): 
# Here it simply calls the function and doesn't need to care about 
# which sorting is used. It only knows that sorted output will be the 
# result of this call 
        return self.sort(x) 
  
Call=Caller() 
  
# Here passing different input 
print(Call.Dosomething([5,4,6])) # Mergesort 
  
print(Call.Dosomething([2.23,3.45,5.65])) # heapsort 
print(Call.Dosomething(['a','s','b','q'])) # quick sort 
# creating word vocab 

输出:

Data is Merge sorted
[5, 4, 6]
Data is Heap sorted
[2.23, 3.45, 5.65]
Data is Quick sorted
['a', 's', 'b', 'q']

上述设计使更改底层策略或实现变得容易,而不会干扰任何用户代码。用户代码可以可靠地使用上述仿函数,而无需知道引擎盖下发生了什么,
使代码解耦,易于扩展和维护。

现在,随着Python中的函数,您还了解了Python中的策略模式,该模式要求将调用特定函数的类与列出或选择策略的类分开。

参考:
https://www.daniweb.com/programming/software-development/threads/485098/functors-in-python