当前位置: 首页 > 科技观察

Python编程:定义函数入参容易吗?这些规则你掌握了吗?

时间:2023-03-12 20:48:56 科技观察

本文内容主要涉及以下主题和方法。文章有点长,大家收藏一下,以备参考。函数参数是函数的输入,可以分为五组。位置参数或关键字参数:允许位置参数和关键字参数;可变位置参数:在元组中收集任意数量的位置参数;可变关键字参数:在字典中收集任意数量的关键字参数;positionalonlyArguments:只能作为位置参数传递;仅关键字参数:只能作为关键字参数传递。到目前为止,在我们看过的示例中,我们看到的所有参数都是普通位置参数或关键字参数。您还看到了如何将它们作为位置参数和关键字参数传递。关于它们没有太多要说的,所以我们将看看其他类别。在此之前,让我们看一下可选参数。1.可选参数除了我们这里看到的类别外,参数还可以分为必选和可选。可选参数有默认值,其值在函数定义中指定。语法格式为:name=value。例子如下:#定义一个带有默认参数的函数,默认参数是调用时的可选参数deffunc(a,b=4,c=88):print(a,b,c)func(1)#prints:1488func(b=5,a=7,c=9)#打印:759func(42,c=9)#打印:4249func(42,43,44)#打印:42,43,这里的44,a是必须的参数项,而b的默认值为4,c的默认值为88,两者都是可选的。重要的是要注意,必需参数必须始终出现在函数定义中所有可选参数的左侧,仅关键字参数除外。尝试在上面的示例中删除c的默认值,看看会发生什么。2.未量化的位置参数有时,您可能不想为函数指定确切的位置参数数量,而Python提供了通过使用可变位置参数来实现这一点的能力。让我们看一个非常常见的用例,minimum()函数。这是一个计算其输入值的最小值的函数,代码如下:#未量化的位置参数defminimum(*n):#print(type(n))#nisatupleifn:#mn=n[0]forvalueinn[1:]:ifvaluefunc(1,b=2,c=3)TypeError:func()gotsomepositional-onlyargumentspassedaskeywordarguments:'b'前面的例子告诉我们Python现在反馈给我们有一种调用func()的方法,这意味着:参数b是通过关键字传递的,但这是不允许的。仅位置参数也可以是可选的,如下所示:#optionalpositional-onlyargumentsdeffunc(a,b=2,/):print(a,b)func(4,5)#prints45func(3)#prints32让我们通过从官方文档中借用的一些例子看看这个特性给语言带来了什么。一个优点是能够完全模拟现有C代码函数的行为:defdivmod(a,b,/):"emulatesthebuilt-infunctiondivmod()"return(a//b,a%b)另一个重要用例是当形式参数名称没有任何意义时排除关键字参数:len(obj='hello')在上面的示例中,obj关键字参数降低了可读性。此外,如果我们希望重构len函数的内部结构,并将obj重命名为the_object(或任何其他名称),则保证更改不会破坏任何客户端代码,因为不会调用len()函数,将引用现在已过时的obj参数名称。最后,使用仅位置参数意味着/左侧的任何值都可以用在未量化的关键字参数中,如下例所示:deffunc_name(name,/,**kwargs):print(name)print(kwargs)func_name('Positional-onlyname',name='Namein**kwargs')#printoutis:#Positional-onlyname#{'name':'Namein**kwargs'}在函数签名中保留指定在**kwargs中使用的参数名称的能力可以使代码更简单、更清晰。现在让我们看看仅位置类比:仅关键字参数。5.仅关键字参数Python3引入了仅关键字参数。我们只是简单地研究它们,因为它们的用例并不常见。有两种方法可以指定它们,在不确定的位置参数之后,或者在不确定的*之后。让我们看两个例子。代码如下:#只有关键字参数defkwo(*a,c):print(a,c)kwo(1,2,3,c=7)#prints:(1,2,3)7kwo(c=4)#prints:()4#kwo(1,2)#这行有问题-它无效,并且有以下错误#TypeError:kwo()missing1requiredkeyword-onlyargument:'c'defkwo2(a,b=42,*,c):print(a,b,c)kwo2(3,b=7,c=99)#打印:3799kwo2(3,c=13)#打印:34213#kwo2(3,23)#这行有问题-它对方法无效,并有以下错误#TypeError:kwo2()missing1requiredkeyword-onlyargument:'c'Asexpected,函数kwo()接受数量变量位置参数(a)和一个仅包含关键字的c。调用的结果很简单,你可以取消第三个调用的注释,看看Python返回了什么错误。这同样适用于函数kwo2(),它与??kwo的不同之处在于它接受位置参数a、关键字参数b和仅关键字参数c。您可以取消注释第三个调用以查看产生的错误。现在您知道了如何指定不同类型的输入参数,让我们看看如何在函数定义中组合它们。6.组合输入参数不同的参数类型可以组合在同一个函数中(事实上,这样做常常很有用)。就像在同一个函数调用中组合不同类型的参数一样,在顺序上有一些限制:仅位置参数在前面,然后是斜杠“/”。普通参数跟在任何仅位置参数之后。未量化的位置参数遵循正常参数。只有关键字参数跟在未量化的位置参数之后。未量化的关键字参数总是排在最后。对于仅位置参数和普通参数,必须在任何可选参数之前定义任何必需参数。这意味着如果您有一个可选的仅位置参数,则所有常规参数也必须是可选的。此规则不影响仅关键字参数。如果没有例子,这些规则可能有点难以理解,所以这里有几个例子:#定义一个函数,所有参数的形式为deffunc(a,b,c=7,*args,**kwargs):print('a,b,c:',a,b,c)print('args:',args)print('kwargs:',kwargs)func(1,2,3,5,7,9,A='a',B='b')注意函数定义中参数的顺序。执行该程序将产生以下结果:a,b,c:123args:(5,7,9)kwargs:{'A':'a','B':'b'}现在让我们看一个keyonlyword参数示例:#仅查看自由参数defallparams(a,/,b,c=42,*args,d=256,e,**kwargs):print('a,b,c:',a,b,c)打印('d,e:',d,e)打印('args:',args)打印('kwargs:',kwargs)allparams(1,2,3,4,5,6,e=7,f=9,g=10)注意在函数声明中有positional-only和keyword-only参数:a是positional-only,d和e是keyword-only。它们位于*args变量位置参数之后,如果它们紧跟一个*(在这种情况下将没有变量位置参数),它们将是相同的。运行程序给出以下内容:a,b,c:123d,e:2567args:(4,5,6)kwargs:{'f':9,'g':10}另一件需要注意的事情是我们命名变量位置参数和关键字参数。您可以自由选择不同的名称,但请注意,args和kwargs是这些参数的常规名称,至少在一般情况下是这样。7.更多签名示例为了简要回顾使用位置和仅关键字说明符的函数签名,下面是一些进一步的示例。省略不确定的位置参数和关键字参数,为简洁起见,我们只剩下以下语法:defxxxFuncName(positional_only_parameters,/,positional_or_keyword_parameters,*,keyword_only_parameters):#函数体首先传递我们有位置参数,然后是位置参数或关键字参数,然后finally仅关键字参数。其他一些有效的签名如下:defxxxFuncName(p1,p2,/,p_or_kw,*,kw):defxxxFuncName(p1,p2=None,/,p_or_kw=None,*,kw):defxxxFuncName(p1,p2=None,/,*,kw):defxxxFuncName(p1,p2=None,/):defxxxFuncName(p1,p2,/,p_or_kw):defxxxFuncName(p1,p2,/):以上是有效的签名,以下是无效签名:defxxxFuncName(p1,p2=None,/,p_or_kw,*,kw):defxxxFuncName(p1=None,p2,/,p_or_kw=None,*,kw):defxxxFuncName(p1=None,p2,/):语法规范可以看官方文档:https://img.ydisp.cn/news/20221107/w5qawpgbxbk.htmldata-id="hce1b53f-oFaLwZWF"id="hce1b53f-oFaLwZWF">8。避免陷阱!使用可变默认值需要注意的一件事是,在Python中,默认值是在定义时创建的;因此,根据可变默认值的不同,对同一函数的后续调用可能会有不同的行为。让我们看一个例子:#functionwithvariabledefaultvalueargumentdeffunc(a=[],b={}):print(a)print(b)print('#'*12)a.append(len(a))#影响a的默认值b[len(a)]=len(a)#影响b的默认值func()func()func()两个参数都有可变的默认值。这意味着如果这些对象在执行过程中受到影响,任何修改都将保留在后续函数调用中。看看你是否能理解这些调用的输出:[]{}############[0]{1:1}############[0,1]{1:1,2:2}############这不乱吗?虽然这种行为乍一看似乎很奇怪,但实际上是有道理的,而且非常得心应手——例如,在使用“记忆”术时,就有一个天赋异禀的傲娇。更有趣的是,在调用之间,我们引入了一个不使用默认值的函数,例如:#中间中介调用func()func(a=[1,2,3],b={'B':1})func()运行代码输出结果如下:[]{}############[1,2,3]{'B':1}############[0]{1:1}############这个输出告诉我们,即使用其他值调用函数,默认值也会被保留。我想到的一个问题是,我如何每次都得到一个新的空值?惯例是这样的:#notrapmutabledefaultdefaultdeffunc(a=None):ifaisNone:a=[]#Dosomethingwitha...请注意,通过使用前面的技术,如果我们在没有调用函数的情况下通过a,我们总是得到一个全新的空列表。本文概要本文围绕以下主题详细介绍了输入参数的分类、示例和函数调用:位置或关键字参数:允许位置和关键字参数;可变位置参数:收集元组位置参数中的任何数字;可变关键字参数:在字典中收集任意数量的关键字参数;positionalargumentsonly:只能作为位置参数传递;?仅关键字参数:只能作为关键字参数传递。