Python 减少函数的数量';s参数
目前,我的程序中有些函数包含15个或更多参数。但是,这15个参数永远不需要同时使用 我有一些switch语句函数,使用字典来执行所需的相关函数。下面是我最极端的例子: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
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可以避免这一点。