Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 减少函数的数量';s参数_Python_Python 3.x - Fatal编程技术网

Python 减少函数的数量';s参数

Python 减少函数的数量';s参数,python,python-3.x,Python,Python 3.x,目前,我的程序中有些函数包含15个或更多参数。但是,这15个参数永远不需要同时使用 我有一些switch语句函数,使用字典来执行所需的相关函数。下面是我最极端的例子: def Instrument_Type_Calcs_C(InstType_C, raw_data_LP, maxcounts_C, Measurement_Min, Measurement_Max, Measurement_Type, SG, Tank_Shape, area

目前,我的程序中有些函数包含15个或更多参数。但是,这15个参数永远不需要同时使用

我有一些switch语句函数,使用字典来执行所需的相关函数。下面是我最极端的例子:

def Instrument_Type_Calcs_C(InstType_C, raw_data_LP, maxcounts_C, Measurement_Min,
                            Measurement_Max, Measurement_Type, SG, Tank_Shape, area, dish,
                            diameter, length, Strapping_Table, Poly_Data, Tank_Number,
                            LevelOffset):
    switcher = {
        '8AI': lambda: inst.FourTwenty(raw_data_LP, maxcounts_C, Measurement_Min,
                                       Measurement_Max, Measurement_Type, SG, Tank_Shape,
                                       area, dish, diameter, length, Strapping_Table,
                                       Poly_Data, Tank_Number, LevelOffset),
        'Magprobe': lambda: inst.SGMagprobe(raw_data_LP,
                                            Tank_Shape, area, dish, diameter, length,
                                            Strapping_Table, Poly_Data, Tank_Number,
                                            LevelOffset),
        'TLS': lambda: inst.TLS(raw_data_LP),
    }
    return switcher.get(InstType_C, lambda : None)()
现在我已经尝试研究了
*args
**kwargs
,但我不确定这些是否对我有帮助。如果使用
*args
定义函数,调用函数时仍需要定义所有参数。然而,我需要在
if:elif:
语句中调用三个不同的函数来声明正确数量的参数。即:

if type == '8AI':
    volume = Instrument_Type_Calcs_C(InstType_C, raw_data_LP, maxcounts_C, Measurement_Min,
                                     Measurement_Max, Measurement_Type, SG, Tank_Shape, area,
                                     dish, diameter, length, Strapping_Table, Poly_Data,
                                     Tank_Number, LevelOffset)
elif type == 'Magprobe':
    volume = Instrument_Type_Calcs_C(InstType_C, raw_data_LP, SG, Tank_Shape, area, dish,
                                     diameter, length, Strapping_Table, Poly_Data,
                                     Tank_Number, LevelOffset)
elif type == 'TLS':
    volume = Instrument_Type_Calcs_C(InstType_C, raw_data_LP)
显然,这只是违背了switch语句的要点,并不能解决真正长的函数调用的问题


总的来说,它不会对我的代码造成任何问题,但如果有更好的实现方法,我想了解如何使用。

您可以使用默认参数和命名参数来解决问题

但是如果你需要有那么多参数的函数,我想你可以让你的程序更面向对象

创建一个类,该类的一个实例具有
\uuuuu call\uuuu
运算符(或只是一个方法),该运算符以您最常用的参数为特征


并为它提供其他方法来控制不经常更改的设置。

您可以使用字典中的“参数”类参数,在其中放置所有需要的参数。大概是这样的:

def FoobarFunction(parameters):
    if parameters["KnownParameter"] == ... :
        # Do Something
        ...

使用默认参数(如注释中所述,即
def func(a,optional=None,optional2=None…):
或者您也可以这样做:

def Instrument_Type_Calcs_C(InstType_C, **kwargs):
    # You can also simply added a proper list of strings, I was merely to lazy to write on up
    allowed_kwargs = ('raw_data_LP, maxcounts_C, Measurement_Min,
                                 Measurement_Max, Measurement_Type, SG, Tank_Shape, area,
                                 dish, diameter, length, Strapping_Table, Poly_Data,
                                 Tank_Number, LevelOffset').strip(' ').split(',')
    wrong_kwargs = [k for in kwargs if k not in allowed_kwargs]
    if wrong_kwargs:
        raise ValueError("Invalid Kwarg passed! %s" wrong_kwargs)

    # rest of your code
    ...
kwargs
是打包到dict中的所有命名参数的一种,因此您可以在函数中访问它,就像访问字典一样

但是,正如你已经指出的,你也许应该考虑<代码> OOP>代码>你的代码。上面的解决方案简单地清理了函数头,而不是函数的可读性,也没有达到更好的简单性。 顺便说一句,您还可以在函数中使用带星号的表达式(

***
*
),它们基本上是解压列表(
*
)或dict(
***
)。这在列表理解或解压到其他变量时非常有用:

l = ['hello', 1, 2] 
s, *nums = *l

s  # 'hello' 

nums  # [1, 2]

您可以使切换函数接受除第一个参数以外的所有参数、
InstType_C
、关键字参数。这样就可以指定在每次调用中要传递的值

为了说明这一点,我将其应用到了您的示例代码中。为了使某些东西实际上可以运行,添加了一些代码中没有的东西,但仅用于测试目的

这可能会使它看起来没有多大的改进,但这是因为在测试中定义了一组包含自己名称的变量。这使得对切换器函数的调用更长,因为每个关键字参数都被分配了一个同名变量的值,所以它们的长度大约是原来的两倍在实际操作中

所有的测试代码都使它看起来非常长和复杂,但我希望您可以忽略它,以了解其优点

您没有遵循命名约定这一事实也使事情看起来“繁忙”,因为它会弄乱语法突出显示,因此适用于显示的代码

# For testing define and create a class with methods to call.
# Each method will just print out the values of the arguments it was passed.
class Inst(object):
    def FourTwenty(self, *args):
        print('called FourTwenty({})\n'.format(args))
    def SGMagprobe(self, *args):
        print('called SGMagprobe({})\n'.format(args))
    def TLS(self, *args):
        print('called TLS({})\n'.format(args))

inst = Inst()  # create instance for testing

# For testing create variables to pass as arguments, each variable will contain
# the variable's name as its value. i.e. some_variable = 'some_variable'.
arguments = [arg.strip() for arg in (
    "raw_data_LP, maxcounts_C, Measurement_Min, Measurement_Max, "
    "Measurement_Type, SG, Tank_Shape, area, dish, diameter, length, "
    "Strapping_Table, Poly_Data, Tank_Number, LevelOffset").split(',')]
for arg in arguments:
    globals()[arg] = arg

#### End of testing scaffold.

class AttrDict(dict):
    """Allows use of dot notation to access dictionary's contents."""
    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self

def Instrument_Type_Calcs_C(InstType_C, **kwargs):
    kwargs = AttrDict(kwargs)  # make them easier to access

    switcher = {
        '8AI': lambda: inst.FourTwenty(kwargs.raw_data_LP, kwargs.maxcounts_C,
                                       kwargs.Measurement_Min,
                                       kwargs.Measurement_Max, kwargs.Measurement_Type,
                                       kwargs.SG, kwargs.Tank_Shape, kwargs.area, kwargs.dish,
                                       kwargs.diameter, kwargs.length, kwargs.Strapping_Table,
                                       kwargs.Poly_Data, kwargs.Tank_Number, kwargs.LevelOffset),
        'Magprobe': lambda: inst.SGMagprobe(kwargs.raw_data_LP, kwargs.Tank_Shape, kwargs.area,
                                            kwargs.dish, kwargs.diameter, kwargs.length,
                                            kwargs.Strapping_Table, kwargs.Poly_Data,
                                            kwargs.Tank_Number, kwargs.LevelOffset),
        'TLS': lambda: inst.TLS(kwargs.raw_data_LP),
    }
    return switcher.get(InstType_C, lambda: None)()

volume = Instrument_Type_Calcs_C('8AI', raw_data_LP=raw_data_LP,
                                 maxcounts_C=maxcounts_C, Measurement_Min=Measurement_Min,
                                 Measurement_Max=Measurement_Max,
                                 Measurement_Type=Measurement_Type, SG=SG,
                                 Tank_Shape=Tank_Shape, area=area, dish=dish,
                                 diameter=diameter, length=length,
                                 Strapping_Table=Strapping_Table, Poly_Data=Poly_Data,
                                 Tank_Number=Tank_Number, LevelOffset=LevelOffset)
volume = Instrument_Type_Calcs_C('Magprobe', raw_data_LP=raw_data_LP, SG=SG,
                                 Tank_Shape=Tank_Shape, area=area, dish=dish,
                                 diameter=diameter, length=length,
                                 Strapping_Table=Strapping_Table, Poly_Data=Poly_Data,
                                 Tank_Number=Tank_Number, LevelOffset=LevelOffset)
volume = Instrument_Type_Calcs_C('TLS', raw_data_LP=raw_data_LP)

您是否尝试过使用默认参数?
def Instrument\u Type\u Calcs\u C(Instrument\u C,raw\u data\u LP=None,…)
您可以通过将
**kwargs
定义为一个参数来实现这一点。是的,这是另一种方法。但是字典更清晰。我强烈反对。不仅仅是因为它不符合音速,您还需要先初始化字典。使用kwargs可以避免这一点。