参数类型

Python函数的参数类型一共有五种,分别是:

  • POSITIONAL_OR_KEYWORD(位置参数或关键字参数)
  • VAR_POSITIONAL(可变参数)
  • KEYWORD_ONLY(关键字参数)
  • VAR_KEYWORD(可变关键字参数)
  • POSITIONAL_ONLY(位置参数)

下面用举几个例子解释一下这5个参数类型的含义:

      

POSITIONAL_OR_KEYWORD如其名所见,既可以用位置传参,也可以用关键字传参,并且他没有任何*的声明

  1. >>> def foo(name):
  2. ... print(name)
  3. ...
  4. >>> foo("hello")
  5. hello
  6. >>> foo(name="hello")
  7. hello

  

VAR_POSITIONAL是可变参数,通过*来声明,它会把接收到的值存入一个元组

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

  

KEYWORD_ONLY只能通过关键字传参,这种参数会在VAR_POSITIONAL参数类型的后面,而且不带**前缀,如同语义,只能通过指定关键字来传参,不可以用位置传参

  1. >>> def foo(n1, *, n2):
  2. ... print(n1, n2)
  3. ...
  4. >>> foo("hello", n2="world")
  5. hello world

  

VAR_KEYWORD是可变关键字参数,通过前缀**来声明,这种参数类型可以接收0个或多个参数,并存入一个字典

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

  

POSITIONAL_ONLY是第五个参数类型,但是它已经不重要了,因为高版本的Python无法创建一个POSITIONAL_ONLY类型的参数,但是有些使用C语言实现且不接收关键字参数的函数(如divmod)支持

从下面的例子,我们可以看到,新定义的foo函数,每个参数都对应到上面的一个类型

  1. >>> def foo(name, *args, middle=None, **kwargs):
  2. ... print("name:", name)
  3. ... print("args:", args)
  4. ... print("middle:", middle)
  5. ... print("kwargs:", kwargs)
  6. ...
  7. >>> foo("hello", 1, 2, 3, middle="world", a=1, b=2, c=3)
  8. name: hello
  9. args: (1, 2, 3)
  10. middle: world
  11. kwargs: {'a': 1, 'b': 2, 'c': 3}
  12. >>> my_foo = {"name": "hello", "middle": "world", "a": "1", "b": "2", "c": "3"}
  13. >>> foo(**my_foo)
  14. name: hello
  15. args: ()
  16. middle: world
  17. kwargs: {'a': '1', 'b': '2', 'c': '3'}
  18. >>> from inspect import signature
  19. >>> sig = signature(foo)
  20. >>> for name, param in sig.parameters.items():
  21. ... print(param.kind, ":", name, '=', param.default)
  22. ...
  23. POSITIONAL_OR_KEYWORD : name = <class 'inspect._empty'>
  24. VAR_POSITIONAL : args = <class 'inspect._empty'>
  25. KEYWORD_ONLY : middle = None
  26. VAR_KEYWORD : kwargs = <class 'inspect._empty'>

  

参数绑定

将函数的参数绑定到一个字典上

  1. >>> def foo(name, *args, middle=None, **kwargs):
  2. ... print("name:", name)
  3. ... print("args:", args)
  4. ... print("middle:", middle)
  5. ... print("kwargs:", kwargs)
  6. ...
  7. >>> my_foo = {"name": "hello", "middle": "world", "a": "1", "b": "2", "c": "3"}
  8. >>> from inspect import signature
  9. >>> sig = signature(foo)
  10. >>> bound_args = sig.bind(**my_foo)
  11. >>> for name, value in bound_args.arguments.items():
  12. ... print(name, '=', value)
  13. ...
  14. name = hello
  15. middle = world
  16. kwargs = {'a': '1', 'b': '2', 'c': '3'}
  17. >>> del my_foo["name"]
  18. >>> bound_args = sig.bind(**my_foo)
  19. Traceback (most recent call last):
  20. ...
  21. TypeError: missing a required argument: 'name'

  

在inspect模块的帮助下,展示了Python数据模型把实参绑定给函数调用的形参的机制,这与解释器使用的机制相同,当我们删除字典中的name,执行时会报错缺少name参数。

再者,我们使用operator模块进行参数绑定

  1. >>> from operator import methodcaller
  2. >>> s = "The time has come"
  3. >>> upcase = methodcaller("upper")
  4. >>> upcase(s)
  5. 'THE TIME HAS COME'
  6. >>> hiphenate = methodcaller("replace", " ", "-")
  7. >>> hiphenate(s)
  8. 'The-time-has-come'

  

如上,methodcaller创建的函数会在对象上调用参数指定的方法,我们可以自己建立一个对象并生成自己的方法,再用methodcaller调用

  1. class Person:
  2. def __init__(self, name):
  3. self.name = name
  4.  
  5. def say(self, text):
  6. print(self.name, 'say:', text)
  7.  
  8. p = Person("John")
  9. person_say = methodcaller("say", "hello")
  10. person_say(p)

  

最后会打印:

  1. John say: hello

  

使用function.partial冻结参数

function.partial这个高阶函数用于部分应用函数,部分应用是指,基于一个函数创建一个新的可调用对象,把原函数的某些参数固定

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

  

如上,我们使用mul创建了triple函数,把第一个参数固定为3,然后返回一个可调用的对象,再传入不同的参数

Python中函数参数类型和参数绑定的更多相关文章

  1. python中函数的不定长参数

    例1: #定义一个含有不定长参数的函数,本例第三个参数*args def sum_nums(a,b,*args): print('_'*30) print(a) print(b) print(args ...

  2. 对Python中函数参数类型及排序问题,三个方面的总结

    Python中函数的参数问题有点复杂,主要是因为参数类型问题导致的情况比较多,下面来分析一下. 参数类型:缺省参数,关键字参数,不定长位置参数,不定长关键字参数. 其实总共可以分为 位置参数和关键字参 ...

  3. python中函数的参数

    函数参数(一) 思考一个问题,如下: 现在需要定义一个函数,这个函数能够完成2个数的加法运算,并且把结果打印出来,该怎样设计?下面的代码可以吗?有什么缺陷吗? def add2num(): a = 1 ...

  4. Python中函数的参数传递与可变长参数

    转自旭东的博客原文 Python中函数的参数传递与可变长参数 Python中传递参数有以下几种类型: (1)像C++一样的默认缺省函数 (2)根据参数名传参数 (3)可变长度参数 示例如下: (1)默 ...

  5. python 中函数的参数

    一.python中的函数参数形式 python中函数一般有四种表现形式: 1.def function(arg1, arg2, arg3...) 这种是python中最常见的一中函数参数定义形式,函数 ...

  6. 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针

      您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...

  7. python中函数的参数解析

    python中函数的各种参数梳理: 1.形参:函数定义时传入的参数 2.实参:函数调用时传入的参数 (有形参必传实参,形参里自身特点可不传的,可传可不传) 3.缺省参数:不传为默认值,传了会覆盖(下面 ...

  8. (转)python中函数参数中如果带有默认参数list的特殊情况

    在python中函数参数中如果带有默认参数list遇到问题 先看一段代码 1 2 3 4 5 6 7 8 9 def f(x,l=[]):     for i in range(x):         ...

  9. python中函数参数的引用方式

    值传递和引用传递时C++中的概念,在python中函数参数的传递是变量指向的对象的物理内存地址!!! python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是“传对象引用”的方 ...

  10. Python中函数的参数-arguments

    归纳起来,Python中函数的定义形式和调用形式主要有如下几种形式: # 函数的定义形式 def func(name) # 匹配positional参数或者keyword参数 def func(nam ...

随机推荐

  1. java中的中文变量和方法

    在网上看到java居然支持中文变量名.方法.这里我只试了变量名和方法,类名这些没有试....真是给力 package com.gxf.fun; public class TestForChinese ...

  2. POJ3233Matrix Power Series(矩阵快速幂)

    题意 题目链接 给出$n \times n$的矩阵$A$,求$\sum_{i = 1}^k A^i $,每个元素对$m$取模 Sol 考虑直接分治 当$k$为奇数时 $\sum_{i = 1}^k A ...

  3. img IE下支持最大宽度

    border:0 none; max-width: 560px; height:auto; width:expression(this.width > 600 ? "600px&quo ...

  4. 构建第一个Spring Boot2.0应用之Controller(三)

    Controller控制器主要是接收浏览器请求.下面说一说@Controller注解和@RestController的区别: (1)@Controller类中的方法可以直接通过返回String跳转到j ...

  5. windows无法连接到打印机 操作失败,错误为0x00000002 解决方案

    平时使用局域网打印机没有问题,今天突然脱机了,错误号为0x00000002 服务器上打印机一切正常,别人使用也一切正常. 最后,重启了Spooler服务后搞定. 重新链接打印机,搞定!

  6. git版本分支和分支、分支和主分支切换

    问题描述: 公司里项目管理使用的是gitLab(收费的), 如果开发人员提交代码,  需要首先创建一个分支, 然后把代码提交到你创建的分支上去(不允许把代码直接提交到主分支上). 在代码提交到已经创建 ...

  7. HTML5 参数传递

    页面显示效果,如下图: 主页面代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...

  8. linux 命令——36 diff(转)

    diff命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版本的diff还支持二进制文件.diff程序的输 ...

  9. php之header的不同用法

    1.header()函数的作用是:发送一个原始 HTTP 标头[Http Header]到客户端. header(string,replace,http_response_code) /*string ...

  10. World Wind Java开发之二 使用Winbuilders设计图形用户界面(转)

    http://blog.csdn.net/giser_whu/article/details/40892955 在eclipse中使用WindowsBuildes可以像在VS中一样,拖拽用户图形界面. ...