函子及其在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