[英]Python got multiple values for argument
我有一个对象,它有一个依赖注入字段,用于实现方法 provide() 的对象:
class DataContainer():
PROVIDERS = dict()
def __init__(self):
self.provider = None
def provide(self, *args, **kwargs):
if self.provider:
return self.provider.provide(self, *args, **kwargs)
raise KeyError("No provider selected")
我为它编写了一个自定义 Provider 对象,如下所示:
# INTERFACE:
class Provider(ABC):
@abstractmethod
def provide(self, *args, **kwargs):
pass
@abstractmethod
def add_product(self, name: str, product: ProviderProduct, *args, **kwargs) -> None:
pass
@abstractmethod
def remove_product(self, name: str, *args, **kwargs) -> None:
pass
class ProviderProduct(ABC):
@abstractmethod
def configure(self, *args, **kwargs) -> ProviderProduct:
pass
IMPLEMENTATION:
class TestProvider(Provider):
REGISTERED = dict()
def provide(self, product, from_dict, *args, **kwargs):
if product in TestProvider.REGISTERED:
return TestProvider.REGISTERED[product].configure(from_dict)
raise KeyError("{} not in REGISTERED".format(product))
class AbstractTestProduct(ProviderProduct, ABC):
INDEX = [0]
COLUMNS = list()
def configure(self, from_dict: Dict) -> ProviderProduct:
df = pd.DataFrame(index=self.INDEX, columns=self.COLUMNS)
df.update(from_dict)
return df
def add_product(self, name, product):
if isinstance(product, AbstractTestProduct):
TestProvider.REGISTERED[name] = product
else:
raise ValueError("Given {} class is not of AbstractTestProduct type".format(product.__class__.__name__))
def remove_product(self, name):
if name in TestProvider.REGISTERED.keys():
del TestProvider.REGISTERED[name]
else:
raise KeyError("{} not found in registered list".format(name))
现在,当我为它编写一些单元测试时,事情出错了:
class TestProviderTestSuite(unittest.TestCase):
@classmethod
def setUpClass(cls):
class TestProviderProduct1(AbstractTestProduct):
COLUMNS = ['test_col_1_1', 'test_col_1_2', 'test_col_1_3']
class TestProviderProduct2(AbstractTestProduct):
COLUMNS = ['test_col_2_1', 'test_col_2_2', 'test_col_2_3', 'test_col_2_4']
class TestProviderProduct3(AbstractTestProduct):
COLUMNS = ['test_col_3_1', 'test_col_3_2', 'test_col_3_3', 'test_col_3_4', 'test_col_3_5']
cls.data_container = DataContainer()
cls.data_container.register_provider("dataframe", TestProvider())
cls.data_container.change_provider('dataframe')
cls.data_container.add_provider_product("a", TestProviderProduct1())
cls.data_container.add_provider_product("b", TestProviderProduct2())
cls.data_container.add_provider_product("c", TestProviderProduct3())
def test_should_provide_empty_product_df_a(self):
# Given
# -
# When
product_df_a = self.data_container.provide(product="a")
# Then
self.assertEqual(3, len(product_df_a.columns))
self.assertEqual(1, len(product_df_a.index))
self.assertTrue(0 in product_df_a.index)
self.assertTrue(product_df_a.isnull().all(axis='columns').values[0])
我在上面的测试中收到以下错误:
self = <utils.providers.test_provider.TestProviderTestSuite testMethod=test_should_provide_empty_product_df_a>
def test_should_provide_empty_product_df_a(self):
# Given
# -
# When
> product_df_a = self.data_container.provide(product="a")
tests\test_provider.py:43:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <DataContainer.DataContainer object at 0x0000022FF859CB48>, args = (), kwargs = {'product': 'a'}
def provide(self, *args, **kwargs):
if self.provider:
> return self.provider.provide(self, *args, **kwargs)
E TypeError: provide() got multiple values for argument 'product'
我不明白为什么解释器,当它收到对 DataContainer 方法的调用 .provide(product="a") 确定 'product' 关键字参数被传递两次。
有任何想法吗?
这对我来说是在 Python 3.7 上发生的。
在 DataContainer 中,函数provide
接受参数*args
和**kwargs
这意味着当您在测试中调用它时, product="a"
将被收集在kwargs
。
这意味着当您使用TestProvider
的provide
函数时,您不会将 product 作为第一个参数,而是作为关键字参数(在**kwargs
)。 第二个product
来自位置参数,该参数由您作为参数传递的 self 填充(您确定要将 self 作为第一个参数传递吗?)。
他们有很多方法可以解决这个问题,最简单的方法是使所有provide
的签名相同
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.