- python - 如何使用条件来定义类?

74 2

我想生成一个class,其中输入元素的数目由 TrueFalse条件决定。 我尝试了这样的方法

 

class Test:


 def __init__(self, cond):


 self.cond = cond


 if cond == True:


 def __call__(self, a, b, c):


 d1 = a + b + c


 return d1


 elif cond == False:


 def __call__(self, a, b):


 d2 = a + b


 return d2



result1 = Test(cond=True)(a, b, c)


result2 = Test(cond=False)(a, b)



但是,它显然不起作用,并且提供了以下错误:

 

TypeError: 'Test' object is not callable



我怀疑我使用了错误的def,因为 __init__在这个例子中可能不适合。

  • 如何在这样的方式下使用最为方便?
  • 是否可以使用class来实现这一点?

我知道使用def函数是相当容易的,而不是class

时间: 原作者:

136 0

我会重组您的代码。在__init__()中添加条件或逻辑不是一个好主意,它只用于变量初始化。

相反,你应该使groupwise__call__()分离,这样就可以在类实例化中调用。

 

class Test:


 def __init__(self, cond):


 self.cond = cond



 def __call__(self, a, b, c=0):


 if self.cond:


 return a + b + c


 else:


 return a + b



a, b, c = 1, 2, 3



result1 = Test(cond=True)(a, b, c)


result2 = Test(cond=False)(a, b)



print(result1) # 6


print(result2) # 3



原作者:
130 1

一种避免这种情况的常见方法是定义子类。

 

class Test:


 def __call__(self, a, b, c):


 return a + b + c



class Test2 (Test):


 def __call__(self, a, b):


 return a + b



result1 = Test()(a, b, c)


result2 = Test2()(a, b)



从表面上看,这几乎不是一种改进;但是,在你可能在不止一个地方使用条件的情况下,重组本身可以得到可观的回报。

原作者:
107 0

不进行条件函数定义。

 

class Test:


 def __init__(self, cond):


 self.cond = cond



 def __call__(self, a, b, c=0):


 if self.cond:


 return a + b + c


 else:


 return a + b



a, b, c = 1, 2, 3



print(Test(cond=True)(a, b, c))


# => 6



print(Test(cond=False)(a, b))


# => 3



还有,不要做像这样的比较 if cond == True:elif cond == False:这也是一个反模式,如果cond是一个布尔值,那么if cond:else:是完美的。

原作者:
139 1

在这种情况下,通过将参数处理为参数(因此,跳过初始配置与你的cond,因为 python不强制你有固定数量的它们),可以实现更多pythonically的结果,以及:

  • 使用列表作为参数:
  •  
    
    class Test:
    
    
     def __call__(self, args):
    
    
     return sum(args)
    
    
    
    my_test = Test()
    
    
    print(my_test([1, 2, 3]))
    
    
    # output: 6
    
    
    
    
  • 使用"可变量"来接受任意数量的位置参数:
  •  
    
    class Test:
    
    
     def __call__(self, *args):
    
    
     return sum(args)
    
    
    
    my_test = Test()
    
    
    print(my_test(1, 2, 3))
    
    
    # output: 6
    
    
    
    

注意*args实际上是一个列表本身,主要区别在于调用调用的方式。

这两种方法都可以使用任意数量的参数,如果你具有特定于特定数量的参数的特定行为,你可以像任何清单一样检查args的长度以同样的方式访问它的元素,比如,用args[0]

如果需要初始配置,则可以在仍然灵活处理参数的同时强制执行某些行为,例如,以下版本的类拒绝输入长度不同于2,if cond is True如果False是,则输入与3不同,所有输入都具有相同的方法:

 

class Test:


 def __init__(self, cond):


 self.cond = cond



 def __call__(self, *args):


 if (self.cond is True and len(args)!= 3) 


 or (self.cond is False and len(args)!= 2):


 raise ValueError



 return sum(args)



当实例化类时,当你想要省略cond时,你可以在__init__中添加默认值。

原作者:
115 5

如果不进入元类内容,最简单的方法就是定义__call__来接受变量数量的变量。

 

class Test:


 def __init__(self, cond):


 self.cond = cond



 def __call__(self, *args):


 if self.cond:


 if len(args)!= 3:


 raise ValueError('When cond=True, requires 3 arguments')


 else:


 if len(args)!= 2:


 raise ValueError('When cond=False, requires 2 arguments')



 return sum(args)



原作者:
103 0

尽管如此,如果你记住函数是python中的第一个类对象,那么最直接的方法就是重新定义__call__:

 

class Test:


 def method1(self, a, b, c):


 d1 = a + b + c


 return d1


 def method2(self, a, b):


 d2 = a + b


 return d2



 def __init__(self, cond):


 self.cond = cond


 if cond:


 self.__call__=self.method1


 else:


 self.__call__=self.method2



Test(cond=True)(1, 2, 3)


6


Test(cond=False)(1, 2)


3



原作者:
...