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
随机推荐
- 【BZOJ1294】[SCOI2009]围豆豆Bean 射线法+状压DP+SPFA
[BZOJ1294][SCOI2009]围豆豆Bean Description Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别 ...
- HDU 6312 - Game - [博弈][杭电2018多校赛2]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6312 Problem Description Alice and Bob are playing a ...
- python读取文件行号和内容的便捷方法
处理数据时候,需要得到数据所在和行号,使用enumerate时便捷的方法: file = open('file.txt','r') for (num,value) in enumerate(file) ...
- 【紫书】Quadtrees UVA - 297 四叉树涂色
题意:前序遍历给出两个像素方块.求两个方块叠加后有几个黑色格子. 题解:每次读进来一个方块,就在二维数组上涂色.每次把白色涂黑就cnt++: 具体递归方法是以右上角坐标与边长为参数,每次通过几何规律往 ...
- Spark Streaming 在数据平台日志解析功能的应用
https://mp.weixin.qq.com/s/bGXhC9hvDj4lzK7wYYHGDg 目前,我们使用Filebeat监控日志产生的目录,收集产生的日志,打到logstash集群,接入ka ...
- iOS多线程编程之NSThread的使用(转载)
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1.NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的 ...
- Python requests 301/302/303重定向(跨域/本域)cookie、Location问题
今天使用request的get方法获取一个网站的登录页信息,结果使用charles抓包的时候发现该网站登录页303(重定向的问题),网上查了很多资料,原因如下: 一.cookie 原因:利用reque ...
- Linux连接字符串
https://blog.csdn.net/ysdaniel/article/details/6920866 或者 '/g' in.txt>out.txt
- Android(三) 匹配屏幕密度
过去,程序员通常以像素为单位设计计算机用户界面.例如:图片大小为80×32像素.这样处理的问题在于,如果在一个dpi(每英寸点数) 高的显示器上运行该程序,则用户界面会显得很小.在有些情况下,用户界面 ...
- 在centos7下安装svn
SVN的安装 yum install subversion 服务端命令 1. svnserver - 控制svn系统服务的启动等 2. svnadmin - 版本库的创建/导出/导入/删除等 3. s ...