Python tricks(2) -- method默认参数和闭包closure
Python的method可以设置默认参数, 默认参数如果是可变的类型, 比如list, map等, 将会影响所有的该方法调用.
下面是一个简单的例子
def f(a=None, l=[]):
if not a:
return l
l.append(a)
return l if __name__ == "__main__":
print f("a")
print f("b")
print f("b")
print f(l=[])
print f()
输出结果如下:
['a']
['a', 'b']
['a', 'b', 'b']
[]
['a', 'b', 'b']
我们可以看到f的默认参数l在所有的方法调用中都受到影响了, 这个可能并不一定符合默认参数设置的初衷.
想要避免这种影响, 可以这样做.
def f(a=None, l=None):
if not l:
l = []
if not a:
return l
l.append(a)
return l if __name__ == "__main__":
print f("a")
print f("b")
print f("b")
print f(l=[])
print f()
将l设置为None, 在方法内部判断, 并初始化为空, 这样改变后的输出为:
['a']
['b']
['b']
[]
[]
具体可以查阅官方文档的说明[参考1].
下面再来说说闭包.
我个人理解, 闭包的形式是方法的嵌套, 主要的作用是为了在整个调用过程中保存方法的某些状态. 有些时候method的默认参数也可以做到保存方法状态.
用dict保存一些变量信息, 类似context的东西.
闭包实现:
def context():
data = {} def _context(key, value=None):
if value:
data[key] = value
return data
else:
return data.get(key, None), data return _context c = context()
print c("key")
print c("key", "value")
print c("key")
方法默认参数的实现
def d(key, value=None, data={}):
if value:
data[key] = value
return data
else:
return data.get(key, None), data
print d("key")
print d("key", "value")
print d("key")
通过实现类的magic method来实现
class e(object):
def __init__(self):
self.data = {} def __call__(self, key, value=None):
if value:
self.data[key] = value
return self.data
else:
return self.data.get(key, None), self.data f = e()
print f("key")
print f("key", "value")
print f("key")
三种实现的输出结果都是一样的
(None, {})
{'key': 'value'}
('value', {'key': 'value'})
在python中方法本身也是一个对象, 可以有自己的属性等, 通过第三种实现, 我们可以理解默认参数是方法对象的一个属性, 伴随其生命周期.
使用def func()定义的时候就是定义了一个方法的类, 之后获取了一个名为func的实例化对象.
可能有人会奇怪, 这种东西哪里有使用的场景了? 我能想到的一个场景就是, 我想通过查找字典的方式获取一个信息, 这个字典是一个大文件(加载耗时), 我只希望加载一次, 这个时候闭包可以发挥其特殊的作用, 而且代码也比较优雅.
本文是笔者对于python方法的一些理解. 水平有限, 欢迎拍砖!
参考文档:
- Python Docs: http://docs.python.org/2/tutorial/controlflow.html#default-argument-values
Python tricks(2) -- method默认参数和闭包closure的更多相关文章
- Python中list作为默认参数的陷阱
在Python中,作为默认参数的一定要是不可变对象,如果是可变对象,就会出现问题,稍不注意,就会调入陷阱,尤其是初学者,比如我(┬_┬). 我们来看一个例子. def add(L=[]): L.app ...
- python中函数的默认参数陷阱问题
其实也不能说是陷阱,只是一个不容易注意到的地方,尤其是有其他java/c++类编程语言经验的人员,这里涉及到python的一个特点,所以笔者说是陷阱只是一个噱头而已. def test(item, b ...
- python的位置参数、默认参数、关键字参数、可变参数区别
一.位置参数 调用函数时根据函数定义的参数位置来传递参数. #!/usr/bin/env python # coding=utf-8 def print_hello(name, sex): sex_d ...
- Python和Lua的默认作用域以及闭包
默认作用域 前段时间学了下Lua,发现Lua的默认作用域和Python是相反的.Lua定义变量时默认变量的作用域是全局(global,这样说不是很准确,Lua在执行x = 1这样的语句时会从当前环境开 ...
- [Python]可变类型,默认参数与学弟的困惑
一.学弟的困惑 十天前一个夜阑人静.月明星稀的夜晚,我和我的朋友们正在学校东门的小餐馆里吃着方圆3里内最美味的牛蛙,唱着最好听的歌儿,畅聊人生的意义.突然,我的手机一震,气氛瞬间就安静下来,看着牛蛙碗 ...
- python定义函数时默认参数注意事项
如果在调用一个函数时,没有传递默认参数,则函数内的默认参数是对函数的默认参数属性__defaults__的引用, 如 def func(arg1=[]): arg1.append(2) 调用func时 ...
- [python 函数学习篇]默认参数
python函数: 默认参数: retries= 这种形式 def ask_ok(prompt, retries=, complaint='Yes or no, please!'): while Tr ...
- 在python中,用默认参数(list,set,dict...)时要小心
在我们平时写需求的时候,如果没有了解到以下知识点,可能会出现这样的问题,掉进坑里面,甚至很难找到问题的根源.下面我们来看看使用可变默认参数(Mutable default arguments)时会出现 ...
- Python学习笔记之默认参数
函数定义时 参数定义的顺序必须是:必选参数.默认参数.可变参数和关键字参数. def test(a,b,c=1,*d,**e) pass
随机推荐
- linux常用命令之scp详解
使用scp的前提: 1.服务端启动了sshd服务 2.是本地和远程两端的系统都必须要有scp这个命令.即openssh-clients软件包 [安装方法] [root@ ~]# yum install ...
- MVC @RenderBody、@RenderSection、@RenderPage、@Html.RenderPartial、@Html.RenderAction
1.@RenderBody() 作用和母版页中的服务器控件类似,当创建基于此布局页面的视图时,视图的内容会和布局页面合并,而新创建视图的内容会通过布局页面的@RenderBody()方法呈现在标签之间 ...
- Java-06-动手动脑
1.为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来? 因为子类继承于父类,子类中有父类的对象,父类的构造方法初始化后,子类才能运行自己的构造方法 不能放过来,继 ...
- POJ 1964&HDU 1505&HOJ 1644 City Game(最大0,1子矩阵和总结)
最大01子矩阵和,就是一个矩阵的元素不是0就是1,然后求最大的子矩阵,子矩阵里的元素都是相同的. 这个题目,三个oj有不同的要求,hoj的要求是5s,poj是3秒,hdu是1秒.不同的要求就对应不同的 ...
- 2018牛客网暑期ACM多校训练营(第二场) A - run - [DP]
题目链接:https://www.nowcoder.com/acm/contest/140/A 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言262144K ...
- CodeForces - 586C Gennady the Dentist 模拟(数学建模的感觉)
http://codeforces.com/problemset/problem/586/C 题意:1~n个孩子排成一排看病.有这么一个模型:孩子听到前面的哭声自信心就会减弱:第i个孩子看病时会发出v ...
- iOS电话等中断事件的开始和结束通知
#import "ViewController.h" #import <AVFoundation/AVFoundation.h> @interface ViewCont ...
- PLSQL developer开发工具相关配置
首先要安装ORACLE Windows版本32位的客户端,在这里只安装ORACLE客户端就可以了,服务端我们选择使用LINUX版本的. 选择不接受安全更新 选择仅安装数据库软件 选择单实例数据库 语言 ...
- CentOS7 firewall防火墙配置笔记
开启端口 # firewall-cmd --zone=public --add-port=/tcp --permanent 命令含义: --zone #作用域 --ad ...
- Loadrunner之脚本的思考时间(固定/随机)设置、调试、保存、测试服务器监控等(六)
一.思考时间的设置 1)设置固定思考时间: Action(){ // … your code lr_think_time(3); //固定设置此处思考时间3s // … more of your co ...