この記事の内容は主に次のトピックと方法に関するものです。記事は少し長いので、簡単に参照できるように保存しておいてください。
関数パラメータは関数の入力であり、5 つのグループに分類できます。
これまでに見てきた例では、すべてのパラメーターは通常の位置パラメーターまたはキーワード パラメーターです。また、それらを位置引数およびキーワード引数として渡す方法についても説明しました。これらについてはあまり言うことはないので、他のカテゴリーについて見ていきます。その前に、オプションのパラメーターを見てみましょう。
ここで説明するカテゴリに加えて、パラメーターは必須オプションとオプション オプションに分類することもできます。オプションのパラメータにはデフォルト値があり、その値は関数定義で指定されます。構文は、名前=値の形式です。例は次のとおりです。
# 定义参数有默认值的函数,调用时其为可选型参数 def func(a, b=4, c=88): print(a, b, c) func(1) # prints: 1 4 88 func(b=5, a=7, c=9) # prints: 7 5 9 func(42, c=9) # prints: 42 4 9 func(42, 43, 44) # prints: 42, 43, 44
ここで、a は必須パラメータですが、b のデフォルト値は 4、c のデフォルト値は 88 です。どちらもオプションです。必須パラメータは、キーワードのみのパラメータを除き、関数定義内のすべてのオプション パラメータの左側に常に指定する必要があることに注意することが重要です。上記の例で c のデフォルト値を削除して、何が起こるかを確認してください。
場合によっては、関数の位置パラメータの正確な数を指定したくない場合があり、Python は可変位置パラメータを使用してこれを提供します。 . ちょっとした能力。非常に一般的な使用例である minimum() 関数を見てみましょう。
これは、入力値の最小値を計算する関数です。コードは次のとおりです:
# 不定量位置参数 def minimum(*n): # print(type(n)) # n 是个元组 if n: # mn = n[0] for value in n[1:]: if value < mn: mn = value print(mn) minimum(1, 3, -7, 9) # n = (1, 3, -7, 9) - prints: -7 minimum() # n = () - prints: nothing
上でわかるように、形式的な関数を定義すると、パラメータにアスタリスク * を付けると、関数が呼び出されたときに、このパラメータが不特定数の位置引数を収集することを Python に伝えます。関数内の n はタプルです。コード内の print(type(n)) 行のコメントを解除し、プログラムを実行して出力を確認できます。
関数は、不定の位置パラメータを最大 1 つだけ持つことができることに注意してください。それ以上の位置パラメータがあっても意味がありません。 Python はそれらの間でパラメータを分割する方法を決定できません。また、可変位置パラメーターのデフォルト値を指定することもできません。デフォルト値は常に空のタプルです。
ヒント:
コードで n が空かどうかを確認するために単純な if n: がどのように使用されているかに気づきましたか? これは、Python では、コレクション オブジェクトが評価時に空ではないためです。 True に設定され、それ以外の場合は False に評価されます。これは、タプル、セット、リスト、辞書などに当てはまります。
もう 1 つ注意すべき点は、パラメーターなしで関数を呼び出す場合、何もせずに何もしないのではなく、エラーをスローした方がよい場合があるということです。この場合、この関数を堅牢にすることに関心があるのではなく、可変の位置パラメーターを理解することに関心があります。
また、不定の位置パラメーターを定義する構文が反復可能なアンパックの構文に非常に似ていることに気づきましたか?これは偶然ではありません。結局のところ、2 つの特性は互いに鏡像です。また、不定の位置パラメーターを使用すると、アンパックされた反復可能の長さが関数定義のパラメーターの数と一致するかどうかを気にする必要がないため、これらは一緒に使用されることもよくあります。
可変キーワード パラメーター (可変キーワード パラメーター) は、可変位置パラメーターとよく似ています。唯一の違いは、構文 (* の代わりに **) と、それらが辞書形式で収集されるという事実です。
# 不定量关键字参数 def func(**kwargs): print(kwargs) func(a=1, b=42) # prints {'a': 1, 'b': 42} func() # prints {} func(a=1, b=46, c=99) # prints {'a': 1, 'b': 46, 'c': 99}
上に示すように、パラメータ名の前に ** を追加します。関数定義は、Python がこの名前を使用して可変数のキーワード引数を収集することを指示します。可変位置引数の場合と同様、各関数は最大 1 つの可変長キーワード引数を持つことができ、デフォルト値は指定できません。
可変個引数の位置引数が反復可能なアンパックに似ているのと同様に、可変個引数のキーワード引数は辞書のアンパックに似ています。ディクショナリのアンパックは、可変キーワード パラメーターを持つ関数に引数を渡すためにもよく使用されます。
可変数のキーワード引数を渡せることがなぜそれほど重要なのかは明らかではないかもしれませんが、この機能の使用方法の例を通して、その重要性をより現実的に理解できるようになります。
データベースに接続する関数を定義します。パラメータなしでこの関数を呼び出すことで、デフォルトのデータベースに接続したいと考えています。また、適切なパラメータを関数に渡して他のデータベースに接続したいと考えています。読み進める前に、数分かけて自分で解決策を見つけてみてください。
# 可变量关键字参数 def connect(**options): conn_params = { 'host': options.get('host', '127.0.0.1'), 'port': options.get('port', 5432), 'user': options.get('user', ''), 'pwd': options.get('pwd', ''), } print(conn_params) # 然后连接数据库(注释掉的代码行) # db.connect(**conn_params) connect() connect(host='127.0.0.42', port=5433) connect(port=5431, user='admin', pwd='super')
関数内で、使用する接続パラメータ ディクショナリ (conn_params) を準備できることに注意してください。デフォルト値はフォールバックとして機能し、関数呼び出し時にそれらを指定してオーバーライドすることができます。より少ないコード行でこれを実現するより良い方法がありますが、現時点ではそれについては気にしません。上記のコードを実行すると、次の結果が得られます。
{'a': 1, 'b': 46, 'c': 99} {'host': '127.0.0.1', 'port': 5432, 'user': '', 'pwd': ''} {'host': '127.0.0.42', 'port': 5433, 'user': '', 'pwd': ''} {'host': '127.0.0.1', 'port': 5431, 'user': 'admin', 'pwd': 'super'}
関数呼び出しと出力の間の対応関係、および関数に渡される内容に基づいてデフォルト値がどのようにオーバーライドされるかに注意してください。
从Python 3.8开始,PEP 570 (https://www.python.org/dev/peps/pep-0570/)引入了仅限位置的参数。有一种新的函数参数语法,/,表示一组函数形参必须在位置上指定,不能作为关键字参数传递。让我们看一个简单的例子:
# 仅限位置参数 def func(a, b, /, c): print(a, b, c) func(1, 2, 3) # prints: 1 2 3 func(1, 2, c=3) # prints 1 2 3
在上面的例子中,我们定义了一个函数func(),它指定了三个参数:a、b和c。函数签名中的/表示a和b必须按位置传递,也就是说,不能通过关键字传递。
示例中的最后两行显示,我们可以按位置传递所有三个参数来调用函数,或者可以按关键字传递c。这两种情况都可以正常工作,因为c定义在函数签名中的/之后。如果我们试图通过通过关键字传递a或b来调用函数,像这样:
func(1, b=2, c=3)
这将产生如下类似回溯跟踪信息:
Traceback (most recent call last): File "……", line 9, in <module> func(1, b=2, c=3) TypeError: func() got some positional-only arguments passed as keyword arguments: 'b'
前面的例子告诉我们,Python现在反馈给我们调用func()的方式,其意思是:通过关键字传递了参数b,但不允许这样做。
仅限位置参数也可以是可选的,如下所示:
# 可选的仅限位置参数 def func(a, b=2, /): print(a, b) func(4, 5) # prints 4 5 func(3) # prints 3 2
通过一些从官方文档中借来的例子来看看这个特性给该语言带来了什么。一个优点是能够完全模拟现有C编码函数的行为:
def divmod(a, b, /): "模拟内建函数 divmod()" return (a // b, a % b)
另一个重要的用例是在形参名没有啥有意义的帮助的情况下排除关键字实参:
len(obj='hello')
在上面的例子中,obj关键字参数降低了可读性。此外,如果我们希望重构len函数的内部结构,并将obj重命名为the_object(或任何其他名称),更改保证不会破坏任何客户端代码,因为不会有任何对len()函数的调用,会涉及到现在已经过时的obj参数名称。
最后,使用仅限位置形参意味着/左边的任何值都可以在不定量关键字实参中使用,如下例所示:
def func_name(name, /, **kwargs): print(name) print(kwargs) func_name('Positional-only name', name='Name in **kwargs') # 打印输出为: # Positional-only name # {'name': 'Name in **kwargs'}
在函数签名中保留参数名以便在**kwargs中使用的能力可以生成更简单、更清晰的代码。
现在来研究一下仅限位置类似版:仅限关键字参数。
Python 3引入了仅限关键字的参数。我们只简要地研究它们,因为它们的用例并不常见。有两种方法可以指定它们,要么在不定量位置参数之后,要么在不定的*之后。来看两个例子。代码如下:
# 仅限关键字参数 def kwo(*a, c): print(a, c) kwo(1, 2, 3, c=7) # prints: (1, 2, 3) 7 kwo(c=4) # prints: () 4 # kwo(1, 2) # 此行出问题——无效于法,并有如下错误 # TypeError: kwo() missing 1 required keyword-only argument: 'c' def kwo2(a, b=42, *, c): print(a, b, c) kwo2(3, b=7, c=99) # prints: 3 7 99 kwo2(3, c=13) # prints: 3 42 13 # kwo2(3, 23) # 此行出问题——无效于法,并有如下错误 # TypeError: kwo2() missing 1 required keyword-only argument: 'c'
正如预期的那样,函数kwo()接受数量可变的位置参数(a)和一个只有关键字的关键字c。调用的结果很简单,你可以取消对第三个调用的注释,以查看Python返回什么错误。
同样的情况也适用于函数kwo2(),它与kwo的不同之处在于,它接受一个位置参数a、一个关键字参数b和一个只有关键字的参数c。你可以取消对第三个调用的注释,以查看产生的错误。
现在应已知道了如何指定不同类型的输入参数,接下来看看如何在函数定义中组合它们。
可以在同一个函数中组合不同的参数类型(事实上,这样做通常非常有用)。就像在同一个函数调用中组合不同类型的实参一样,在顺序上有一些限制:
对于仅限位置参数和普通参数,任何必需的参数必须在任何可选参数之前定义。这意味着,如果你有一个可选的仅限位置参数,那么所有常规参数也必须是可选的。该规则不影响仅限关键字的参数。
如果没有例子,这些规则可能会有点难以理解,所以来看几个示例:
# 定义个带有所有参数形式的函数 def func(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: 1 2 3 args: (5, 7, 9) kwargs: {'A': 'a', 'B': 'b'}
现在再来看一个只有关键字参数的例子:
# 仅限观自在参数 def allparams(a, /, b, c=42, *args, d=256, e, **kwargs): print('a, b, c:', a, b, c) print('d, e:', d, e) print('args:', args) print('kwargs:', kwargs) allparams(1, 2, 3, 4, 5, 6, e=7, f=9, g=10)
注意,在函数声明中有仅限位置形参和仅限关键字形参:a仅限位置形参,而d和e仅限关键字形参。他们是在*args可变量位置参数之后,如果它们紧跟在单个*的后面,也会是一样的(在这种情况下,将没有任何可变位置参数)。运行程序会得到以下结果:
a, b, c: 1 2 3 d, e: 256 7 args: (4, 5, 6) kwargs: {'f': 9, 'g': 10}
另一件需要注意的事情是我们为可变量位置参数和关键字参数命名。你可以自由选择不同的名称,但请注意,args和kwargs是这些参数的常规名称,至少在一般情况下是这样。
为了简要回顾一下使用仅限位置和关键字说明符的函数签名,下面是一些进一步的示例。省略不定量位置和关键字参数,为简洁起见,我们只剩下以下语法:
def xxxFuncName(positional_only_parameters, /, positional_or_keyword_parameters, *, keyword_only_parameters): # 函数体 pass
首先,我们有仅限位置的参数,然后是位置或关键字参数,最后是仅限关键字参数。
其他一些有效签名如下:
def xxxFuncName(p1, p2, /, p_or_kw, *, kw): def xxxFuncName(p1, p2=None, /, p_or_kw=None, *, kw): def xxxFuncName(p1, p2=None, /, *, kw): def xxxFuncName(p1, p2=None, /): def xxxFuncName(p1, p2, /, p_or_kw): def xxxFuncName(p1, p2, /):
以上均为有效签名,下列为无效签名:
def xxxFuncName(p1, p2=None, /, p_or_kw, *, kw): def xxxFuncName(p1=None, p2, /, p_or_kw=None, *, kw): def xxxFuncName(p1=None, p2, /):
你可以在官方文档中阅读语法规范:
https://docs.python.org/3/reference/compound_stmts.html#functiondefinitions
提示:在这一点上,要很好的理解与掌握,一个有用的练习方法是实现上述示例签名中的任何一个,打印出这些参数的值,就像我们在前面的练习中所做的那样,并以不同的方式传递参数。
要注意的一件事是,在Python中,默认值是在定义时创建的;因此,根据默认值的可变性,对同一函数的后续调用可能会有不同的行为。让我们看一个例子:
# 带有可变默认值参数函数 def func(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} ############
这个输出告诉我们,即使使用其他值调用函数,默认值也会被保留。我想到的一个问题是,如何每次都获得一个新的空值?惯例是这样的:
# 无陷阱可变缺省默认值 def func(a=None): if a is None: a = [] # 干些使用a的工作 ...
注意,通过使用前面的技术,如果调用函数时没有传递a,我们总是得到一个全新的空列表。
本文详细介绍了函数的输入参数分类、示例和调用,都是围绕如下主题展开:
位置或关键字参数:同时允许位置和关键字参数;
可变位置参数:在元组中收集任意数量的位置参数;
可变关键字参数:在字典中收集任意数量的关键字参数;
仅限位置参数:只能作为位置参数传递;
•仅限关键字参数:只能作为关键字参数传递。
以上がPython プログラミング: 関数の入力パラメーターを定義するのは簡単ですか?これらのルールをマスターしましたか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。