• 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,然后返回一个可调用的对象,再传入不同的参数

  • 相关阅读:
    第二阶段每日总结01
    第十二周进度条
    构建之法阅读笔记05
    找水王01
    第十一周进度条
    第十周进度条
    构建之法阅读笔记04
    第九周进度条
    每日工作总结10
    每日工作总结09
  • 原文地址:https://www.cnblogs.com/beiluowuzheng/p/8463141.html
Copyright © 2020-2023  润新知