Python中函數參數類型和參數綁定


參數類型

Python函數的參數類型一共有五種,分別是:

  • POSITIONAL_OR_KEYWORD(位置參數或關鍵字參數)
  • VAR_POSITIONAL(可變參數)
  • KEYWORD_ONLY(關鍵字參數)
  • VAR_KEYWORD(可變關鍵字參數)
  • POSITIONAL_ONLY(位置參數)

 

下面用舉幾個例子解釋一下這5個參數類型的含義:

      

POSITIONAL_OR_KEYWORD如其名所見,既可以用位置傳參,也可以用關鍵字傳參,並且他沒有任何*的聲明

>>> def foo(name):
...     print(name)
...
>>> foo("hello")
hello
>>> foo(name="hello")
hello

  

VAR_POSITIONAL是可變參數,通過*來聲明,它會把接收到的值存入一個元組

>>> def foo(*args):
...     print(args)
...
>>> foo(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)

  

KEYWORD_ONLY只能通過關鍵字傳參,這種參數會在VAR_POSITIONAL參數類型的后面,而且不帶**前綴,如同語義,只能通過指定關鍵字來傳參,不可以用位置傳參

>>> def foo(n1, *, n2):
...     print(n1, n2)
...
>>> foo("hello", n2="world")
hello world

  

VAR_KEYWORD是可變關鍵字參數,通過前綴**來聲明,這種參數類型可以接收0個或多個參數,並存入一個字典

>>> def foo(**kwargs):
...     for key, value in kwargs.items():
...         print("%s=%s" % (key, value))
...
>>> foo(a=1, b=2, c=3)
a=1
b=2
c=3

  

POSITIONAL_ONLY是第五個參數類型,但是它已經不重要了,因為高版本的Python無法創建一個POSITIONAL_ONLY類型的參數,但是有些使用C語言實現且不接收關鍵字參數的函數(如divmod)支持

 

從下面的例子,我們可以看到,新定義的foo函數,每個參數都對應到上面的一個類型

>>> def foo(name, *args, middle=None, **kwargs):
...     print("name:", name)
...     print("args:", args)
...     print("middle:", middle)
...     print("kwargs:", kwargs)
...
>>> foo("hello", 1, 2, 3, middle="world", a=1, b=2, c=3)
name: hello
args: (1, 2, 3)
middle: world
kwargs: {'a': 1, 'b': 2, 'c': 3}
>>> my_foo = {"name": "hello", "middle": "world", "a": "1", "b": "2", "c": "3"}
>>> foo(**my_foo)
name: hello
args: ()
middle: world
kwargs: {'a': '1', 'b': '2', 'c': '3'}
>>> from inspect import signature
>>> sig = signature(foo)
>>> for name, param in sig.parameters.items():
...     print(param.kind, ":", name, '=', param.default)
...
POSITIONAL_OR_KEYWORD : name = <class 'inspect._empty'>
VAR_POSITIONAL : args = <class 'inspect._empty'>
KEYWORD_ONLY : middle = None
VAR_KEYWORD : kwargs = <class 'inspect._empty'>

  

參數綁定

將函數的參數綁定到一個字典上

>>> def foo(name, *args, middle=None, **kwargs):
...     print("name:", name)
...     print("args:", args)
...     print("middle:", middle)
...     print("kwargs:", kwargs)
...
>>> my_foo = {"name": "hello", "middle": "world", "a": "1", "b": "2", "c": "3"}
>>> from inspect import signature
>>> sig = signature(foo)
>>> bound_args = sig.bind(**my_foo)
>>> for name, value in bound_args.arguments.items():
...     print(name, '=', value)
...
name = hello
middle = world
kwargs = {'a': '1', 'b': '2', 'c': '3'}
>>> del my_foo["name"]
>>> bound_args = sig.bind(**my_foo)
Traceback (most recent call last):
...
TypeError: missing a required argument: 'name'

  

在inspect模塊的幫助下,展示了Python數據模型把實參綁定給函數調用的形參的機制,這與解釋器使用的機制相同,當我們刪除字典中的name,執行時會報錯缺少name參數。

再者,我們使用operator模塊進行參數綁定

>>> from operator import methodcaller
>>> s = "The time has come"
>>> upcase = methodcaller("upper")
>>> upcase(s)
'THE TIME HAS COME'
>>> hiphenate = methodcaller("replace", " ", "-")
>>> hiphenate(s)
'The-time-has-come'

  

如上,methodcaller創建的函數會在對象上調用參數指定的方法,我們可以自己建立一個對象並生成自己的方法,再用methodcaller調用

class Person:
    def __init__(self, name):
        self.name = name

    def say(self, text):
        print(self.name, 'say:', text)


p = Person("John")
person_say = methodcaller("say", "hello")
person_say(p)

  

最后會打印:

John say: hello

  

使用function.partial凍結參數

function.partial這個高階函數用於部分應用函數,部分應用是指,基於一個函數創建一個新的可調用對象,把原函數的某些參數固定

>>> from operator import mul
>>> from functools import partial
>>> triple = partial(mul, 3)
>>> triple(7)
21
>>> list(map(triple, range(1, 10)))
[3, 6, 9, 12, 15, 18, 21, 24, 27]

  

如上,我們使用mul創建了triple函數,把第一個參數固定為3,然后返回一個可調用的對象,再傳入不同的參數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM