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,然后返回一个可调用的对象,再传入不同的参数
Python中函数参数类型和参数绑定的更多相关文章
- python中函数的不定长参数
例1: #定义一个含有不定长参数的函数,本例第三个参数*args def sum_nums(a,b,*args): print('_'*30) print(a) print(b) print(args ...
- 对Python中函数参数类型及排序问题,三个方面的总结
Python中函数的参数问题有点复杂,主要是因为参数类型问题导致的情况比较多,下面来分析一下. 参数类型:缺省参数,关键字参数,不定长位置参数,不定长关键字参数. 其实总共可以分为 位置参数和关键字参 ...
- python中函数的参数
函数参数(一) 思考一个问题,如下: 现在需要定义一个函数,这个函数能够完成2个数的加法运算,并且把结果打印出来,该怎样设计?下面的代码可以吗?有什么缺陷吗? def add2num(): a = 1 ...
- Python中函数的参数传递与可变长参数
转自旭东的博客原文 Python中函数的参数传递与可变长参数 Python中传递参数有以下几种类型: (1)像C++一样的默认缺省函数 (2)根据参数名传参数 (3)可变长度参数 示例如下: (1)默 ...
- python 中函数的参数
一.python中的函数参数形式 python中函数一般有四种表现形式: 1.def function(arg1, arg2, arg3...) 这种是python中最常见的一中函数参数定义形式,函数 ...
- 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针
您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...
- python中函数的参数解析
python中函数的各种参数梳理: 1.形参:函数定义时传入的参数 2.实参:函数调用时传入的参数 (有形参必传实参,形参里自身特点可不传的,可传可不传) 3.缺省参数:不传为默认值,传了会覆盖(下面 ...
- (转)python中函数参数中如果带有默认参数list的特殊情况
在python中函数参数中如果带有默认参数list遇到问题 先看一段代码 1 2 3 4 5 6 7 8 9 def f(x,l=[]): for i in range(x): ...
- python中函数参数的引用方式
值传递和引用传递时C++中的概念,在python中函数参数的传递是变量指向的对象的物理内存地址!!! python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是“传对象引用”的方 ...
- Python中函数的参数-arguments
归纳起来,Python中函数的定义形式和调用形式主要有如下几种形式: # 函数的定义形式 def func(name) # 匹配positional参数或者keyword参数 def func(nam ...
随机推荐
- jquery jquery中是否加()的问题
自己总结的,慢慢修改再: 1带上()代表立即执行 去掉()代表当有事件发生的时候,我再执行
- Flask之目录结构
学习Flask,整合其目录结构也是比较重要的.一个最基础的Flask目录如下所示: 一.SQLAlchemy-utils 由于sqlalchemy中没有提供choice方法,所以借助SQLAlchem ...
- Web前端开发的学习过程
2018年 5月27日 开始在MDN上学习HTML/CSS/JavaScript.——6月18日 基本学完MDN的“学习Web开发”的HTML/CSS/JavaScript部分. 6月9日 开始在IF ...
- 如何在VS中快速导入新的源码以及文件夹
参考链接:http://www.cjjjs.com/paper/xmkf/201641716212844.aspx 在visual studio 2013中尝试发现的问题:原文中“显示所有文件 ”的操 ...
- CSS文档优化
首先了解下CSS的渲染逻辑,它是从标记的最后一位开始搜索的,例如:.myclass li a,首选它会遍历所有的<a>,然后看哪些<a>之前有<li>,然后再看哪些 ...
- 构建第一个Spring Boot2.0应用之集成dubbo上---环境搭建(九)
一.环境: Windows: IDE:IntelliJ IDEA 2017.1.1 JDK:1.8.0_161 Maven:3.3.9 springboot:2.0.2.RELEASE Linux(C ...
- Localroast使用总结
全手打原创,转载请标明出处: https://www.cnblogs.com/dreamsqin/p/10883248.html,多谢~=.= 什么是Localroast 一个根据 JSON 文件快速 ...
- SAP Cloud for Customer Extensibility的设计与实现
今天的文章来自Jerry的同事,SAP成都研究院C4C开发团队的开发人员徐欢(Xu Boris).徐欢就坐我左手边的位置,因此我工作中但凡遇到C4C的技术问题,一扭头就可以请教他了,非常方便.下图是他 ...
- 工作流性能优化(敢问activiti有扩展性?)(3)
2015/4/20 周末回去想了下,hibernate.mybatis.jdbc,都行,最终定了用mybatis,谁叫它这么优雅,acvtiviti是依赖了mybatis的,就不用再引入包了: 看了配 ...
- sparkSQL中udf的使用
在Spark中使用sql时一些功能需要自定义方法实现,这时候就可以使用UDF功能来实现 多参数支持 UDF不支持参数*的方式输入多个参数,例如String*,不过可以使用array来解决这个问题. 定 ...