python中函数参数
默认参数注意点
优点:灵活,当没有指定与形参对应的实参时就会使用默认参数
缺陷:
例子:
>>> def h(m, l=[]): #默认参数时列表,可变对象
... l.append(m)
... print id(l)
... return l
...
>>> h(1)
140373466854392
[1]
>>> h(2)
140373466854392 #在多次调用的过程中l的id并没有变换
[1, 2] #意外的结果[1,2]
关于默认参数,文档中是这样说的:
Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same "pre-computed" value is used for each call.
大概意思:但解释器执行函数定义时,默认参数值也被计算了,这也意味着默认参数里的表达式只是被执行了一次,而且每次调用都是用同样的上面预先计算的值
所以上面的例子就很容易理解,list在函数定义的时候,就被定义好了,函数的多次调用,都在用一个list
怎么理解
实际上,函数就是一个对象;当python执行def语句时,它会根据编译好的函数体字节码和命名空间等信息新建这个对象,并且会计算默认参数的值。函数的所有构成要素均可通过它的属性来访问,比如可以用func_name属性来查看函数的名称。所有默认参数值则存储在函数对象的__defaults__属性中,它的值为一个列表,列表中每一个元素均为一个默认参数的值
>>> dir(h)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> h.__defaults__
([1, 2],)
>>> h(3)
140373466854392
[1, 2, 3]
>>> h.__defaults__
([1, 2, 3],)
解决办法:动态生成对象,在定义的时候使用None对象做占位符;
前面的例子可以改写成:
>>> def h(a,l=None):
... if l is None:
... l=[]
... l.append(a)
... print id(l)
... return l
...
>>> h(1)
140373466854392
[1]
>>> h(2)
140373466843904
[2]
>>> h(2,[1,2])
140373466854392
[1, 2, 2]
再一个例子:实时返回系统
>>> def t1(when = time.time()): #默认参数在函数定义的时候就被执
... time.sleep(1) 行了,且多次调用都在使用同一个
... return when
>>> def t2(when = time.time): #默认参数只是对象
... time.sleep(1)
... return when
>>> a1=t1()
1448022680.552696
>>> a2=t2()
<built-in function time>
>>> a2()
1448022764.78878
>>> a2()
1448022767.4640501
1448022790.4568429
变长参数
使用方法:
*args 表示任何多个无名参数,它被封装在一个tuple
>>> def f(*a):
... return sum(a)
...
>>> f(1,2,3)
6
**kwargs表示关键字参数,它被封装一个dict
>>> def b(**kw):
... for i,v in kw.items():
... print 'key={0}, value={1}'.format(i,v)
...
>>> b(n=2, name='wxl')
key=name, value=wxl
key=n, value=2
args和kwargs可以随意命名。*args 要在**kwargs前面使用,否则语法错误
适合变长参数场景:
- 修饰器中的使用:比如在django中使用@login_req来规定用户必须在登录状态下才能使用该函数,而修饰函数有很多,参数不同,所以变长函数很好解决问题
def login_req(main):
def required(request,*args,**kwargs):
if not request.session.get('is_login', None):
return redirect('/login/')
else:
return main(request,*args,**kwargs)
return required
@login_req
def index(request):
return render_to_response("index.html")
- 参数的数目不确定,如读取配置文件test.cfg、做全局变量等:
>>> from ConfigParser import ConfigParser
>>> conf= ConfigParser()
>>> conf.read('test.cfg')
['test.cfg']
>>> conf.items('params')
[('name', 'wxl'), ('age', '21'), ('height', '180')]
>>> dict(conf.items('params'))
{'age': '21', 'name': 'wxl', 'height': '180'}
- 当子类调用父类的某些方法,这种如果改变父类程序时,子程序可以不改动
>>> class Super( object ):
... def __init__( self, this, that ):
... self.this = this
... self.that = that
...
>>> class Sub( Super ):
... def __init__( self, myStuff, *args, **kw ):
... super( Sub, self ).__init__( *args, **kw )
... self.myStuff= myStuff
函数传参:既不是传值也不是传引用,而是传对象
与c语言不同的是,python赋值的方式是引用
>>> a=5;
>>> b=a
>>> id(a)
35365592
>>> id(b)
35365592
>>> b=7
>>> id(b)
35365544
上面赋值a的操作实际上是将a指向5所在的内存地址
b=a b相当与a的别名,同样也指向5所在的内存地址
b=7 相当于申请了一块存放有7的内存空间,再把b指向7所在的内存空间
所以python函数中,函数参数在传递的过程中是将整个对象传入,对于可变对象的修改在函数外部及函数内部都可见,调用函数和被调函数之间共享这个对象,
而对于不可变对象,由于并不能真正地被修改,因此,修改通常通过新建对象然后赋值指向来实现
python中函数参数的更多相关文章
- (转)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中函数参数类型及排序问题,三个方面的总结
Python中函数的参数问题有点复杂,主要是因为参数类型问题导致的情况比较多,下面来分析一下. 参数类型:缺省参数,关键字参数,不定长位置参数,不定长关键字参数. 其实总共可以分为 位置参数和关键字参 ...
- python中函数参数*args和**kw的区别
1.函数与参数(实参) 在python中创建函数是def,创建函数名是def f(),f函数名字,def f(a,b),这里的a,b是两个参数,函数名是自定义的,参数也是自定义,随意就好.看图如下效果 ...
- Python中函数参数类型和参数绑定
参数类型 Python函数的参数类型一共有五种,分别是: POSITIONAL_OR_KEYWORD(位置参数或关键字参数) VAR_POSITIONAL(可变参数) KEYWORD_ONLY(关键字 ...
- Python中函数参数 *args 和 **kwargs
普通参数,即在调用函数时必须按照准确的顺序来进行参数传递. 默认参数,即参数含有默认值,在调用函数时可以进行参数传递,若没有进行参数传递则使用默认值,要注意,默认参数必须在普通参数的右侧(否则解释器无 ...
- python中函数的参数
函数参数(一) 思考一个问题,如下: 现在需要定义一个函数,这个函数能够完成2个数的加法运算,并且把结果打印出来,该怎样设计?下面的代码可以吗?有什么缺陷吗? def add2num(): a = 1 ...
- python 中函数参数传递形式
python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...
- python中函数参数传递的几种方法
转自 http://www.douban.com/note/13413855/ Python中函数参数的传递是通过“赋值”来传递的.但这条规则只回答了函数参数传递的“战略问题”,并没有回答“战术问题 ...
随机推荐
- 4.改变eclipse选中文字颜色
window-preferences-general-editors-text editors-annotations-occurrences 和 window-preferences-general ...
- JavaScript and ActionScript3
接触JavaScript和ActionScript3也有一段时间了,它们都是应用比较广泛的脚本语言,经过这几年的工作和学习,静下来的时候想总结一些东西,作为技术上的沉淀以及培训所用,所以就有了这篇文章 ...
- C标准库中atoi的一种可能的实现
为避免与标准库中的atoi产生歧义, 我将自己编写的函数命名为strToInt, 以下是示例代码 #include <stdio.h> int strToInt(const char *s ...
- 20170225-ALV tree 显示
1.写程序, 2.话屏幕9000,CALL SCREEN 9000.(双击屏幕进去画个容器就ok,+OK_CODE,+去掉注释) 3.处理好ALV 的PBO 初始化,处理用户事件PAO,user co ...
- rails elasticsearch searchkick用法
1.安装elasticsearch 之前要先安装java8: 参考https://www.elastic.co/guide/en/elasticsearch/reference/current/zip ...
- YTU 2832: 使用指针访问数组元素--程序填空
2832: 使用指针访问数组元素--程序填空 时间限制: 1 Sec 内存限制: 128 MB 提交: 328 解决: 160 题目描述 输入10个整数值到数组中,使用指针来完成对这10个数组元素 ...
- 织梦DedeCMS未审核文章更新为当前时间
对于个人站长来说,每天文章的更新量都是个巨大的问题,例如,立信CPA培训注册会计师考试网站,有时候我们去别的网站采集大量的文章,然后自己进行手工整理伪原创,但是审核的时候,时间却是采集发布的时间.一方 ...
- Couldn't connect to host, port: smtp.163.com, 25; timeout -1;
运行出现以下报错: Couldn't connect to host, port: smtp.163.com, 25; timeout -1; 也要设置端口 spring.mail.port=25
- Silverlight 2中实现文件上传和电子邮件发送
Silverlight 2中实现文件上传和电子邮件发送 [收藏此页] [打印] 作者:IT168 TerryLee 2008-05-30 内容导航: 使用Web Service上传文件 [I ...
- USACO 回文的路径
传送门 这道题和传纸条在某些方面上非常的相似.不过这道题因为我们要求回文的路径,所以我们可以从中间一条大对角线出发去向两边同时进行DP. 这里就有了些小小的问题.在传纸条中,两个路径一定是同时处在同一 ...