Pythonic多态参数

时间:2019-05-19 15:57:10

标签: python python-3.x

我对Python有点陌生。我遇到了在Blender中创建几何的情况。我正在使用一个枚举来定义几何类型。不同类型的几何需要不同的初始化参数。例如,ICOSPHERE需要细分,而UV_SPHERE需要细分和环。

使用本质上是多态参数列表的函数来处理此问题的Python方式是什么?要调用该函数,我们给它提供一个枚举和该枚举的适当参数,然后该函数使用一个switch块或类似的东西来处理每种类型的枚举。我不想使用函数重载-我想要一个可以处理各种情况的函数。

我猜这些参数可能是字典。这会将参数的变量列表封装到单个参数中。有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

这是一个建议,它是基于使用一个函数和一个枚举类的。

class Geometry:
    ICOSPHERE = 1
    UV_SPHERE = 2


def blendrFunc(gtype, **kwargs):
    arg1 = kwargs['arg1']

    if gtype == Geometry.ICOSPHERE:
        arg2 = kwargs['arg2']
        icosphere_func(arg1, arg2)

    elif  gtype == Geometry.UV_SPHERE:
        uvsphere_func(arg1)

if __name__ == '__main__':
    blendrFunc(Geometry.ICOSPHERE, arg1 = 1, arg2 = (1, 2))

    blendrFunc(Geometry.UV_SPHERE, arg1 = [3, 4])

基本上将关键字词典用于灵活的参数。某些关键字可以在几何类型之间共享,也可以表示不同几何对象的不同类型。某些关键字可能是必需的,或者不用于其他几何。

您可以通过执行以下操作来更好地处理参数。

arg = kwargs.get('arg', None)
if arg is None:
    raise ValueError('UVSPHERE requires arg to be ...')

答案 1 :(得分:1)

您可以编写函数来处理任意数量的参数和/或关键字参数。这是通过在表示参数(*)或关键字参数(**)的参数中添加星号来实现的。

任意参数作为元组:

>>> def func_with_arbitrary_args(*args):
...     print(args)
...     print(type(args))
...     for arg in args:
...         print(arg)

>>> func_with_arbitrary_args(1, 2, 3)
    (1, 2, 3)
    <class 'tuple'>
    1
    2
    3

任意关键字参数被用作字典:

>>> def func_with_arbitrary_kwargs(**kwargs):
...     print(kwargs)
...     print(type(kwargs))
...     for key in kwargs:
...         value = kwargs[key]
...         print(key, value)

>>> func_with_arbitrary_kwargs(name='Joe', size=10)
    {'name': 'Joe', 'size': 10}
    <class 'dict'>
    name Joe
    size 10

使用这种语法,您可以将任何参数列表或关键字参数字典传递给函数,并在内部处理这些args / kwargs。

例如,您可以添加诸如if kwargs['shape'] == 'circle:'之类的检查来断言您的kwarg所描述的形状,因此您可以相应地对其进行处理。

此外,请注意,您可以使用列表/元组/字典的解包来简化函数的调用。同样,这是用星号完成的,但是在函数调用上而不是在函数定义上:

>>> some_list = [1, 2, 3]
>>> func_with_arbitrary_args(*some_list)
# output ommited

>>> some_tuple = (1, 2, 3)    
>>> func_with_arbitrary_args(*some_tuple)
# output ommited

>>> some_dictionary = {'name': 'Joe', 'size': 10}
>>> func_with_arbitrary_kwargs(**some_dictionary)
# output ommited