还有什么比这个问题更适合python的解决方案?

时间:2019-01-28 15:05:56

标签: python python-3.x design-patterns

我的课堂结构如下。

class foo(object):
    def __call__(self,param1):
        pass
class bar(object):
    def __call__(self,param1,param2):
        pass

我有很多此类的课程。我正在按如下方式使用此可调用类。

classes = [foo(), bar()]
for C in classes:
    res = C(param1) 
 '''here i want to put condition if class takes 1 argumnet just pass 1  
 parameter otherwise pass two.'''

我想到了一种这样的模式。

class abc():
    def __init__(self):
        self.param1 = 'xyz'
        self.param2 = 'pqr'

    def something(self, classes): # classes = [foo(), bar()]
        for C in classes:
            if C.__class__.__name__ in ['bar']:  
                res = C(self.param1, self.param2)
            else:
                res = C(self.param2)
  

但在上述解决方案中必须维护带有两个参数的类列表,因为我将向文件中添加更多类,因此会变得混乱。

我不知道这是否正确(pythonic)。

  • 我想到的另一个想法是检查该类正在接受多少个参数。如果它的2则传递一个额外的参数,否则传递1个参数。我已经看过这个解决方案How can I find the number of arguments of a Python function?。但是我对这是最适合我的问题的最合适解决方案的信心不足。
  • 关于此的几件事:
    • 在我的用例中,只有两种类型的类:一种带有1个参数,一种带有2个。
    • 两个类都采用相同的第一个参数,因此在两种情况下,params1都是我要传递的相同参数。对于具有两个必需参数的类,我正在传递包含一些数据的附加参数(params2)。 附言:对于此问题的任何帮助或新想法,都表示感谢。 UPD:更新了代码。

1 个答案:

答案 0 :(得分:1)

基本上,您想在对象的__call__()方法上使用多态性,但是可调用对象签名不相同存在问题。

一个简单的答案是:您只能对兼容类型使用多态,这意味着您的可调用对象必须具有兼容的签名。

希望有一种快速简便的方法来解决此问题:只需修改方法签名,以便它们接受varargs和kwargs:

class Foo(object):
    def __call__(self,param1, *args, **kw):
        pass

class Bar(object):
    def __call__(self, param1, param2, *args, **kw):
        pass

对于无法更改可调用对象签名的情况,仍然有一种解决方法:使用lambda作为代理:

def func1(y, z):
   pass

def func2(x):
   pass


callables = [func1, lambda y, z: func2(y)]
for c in callables:
    c(42, 1138)

请注意,最后一个示例实际上称为the adapter pattern

不相关:此:

if C.__class__.__name__ in ['bar']:

是一种效率低下且令人费解的书写方式:

if C.__class__.__name__ == 'bar':

这本身就是一种效率低下,令人费解且易碎的书写方式:

if type(C) is bar:

这本身就是一种可能的设计气味(有合法的用例来检查对象的确切类型,但通常这确实是设计问题)。