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
随机推荐
- jfinal的model和record如何相互转化?
一.model转record: Model类: 1. /** * Convert model to record. */public Record toRecord() { return new Re ...
- R的any和all
> x<-1:10 > any(x>8) [1] TRUE > all(x>8) [1] FALSE
- POJ3150 Candies【差分约束】
During the kindergarten days, flymouse was the monitor of his class. Occasionally the head-teacher b ...
- nowcoder2018年全国多校算法寒假训练营练习比赛(第一场)
[气死我了 写完了博客发布 点看来一看怎么只剩下一半不到的内容了!!!!!!!!!!] [就把卡的那两道放上来好了 其余的不弄了 生气!!!!!] 可以说是很久没有打比赛了 今天这一场主要是 基础算 ...
- .NET中的类型对象
.NET中的任何类型,都有对应的一个类型对象.类型对象和类型实例(类型创建的一个对象)不是同一个概念. 类型对象包含类型的静态字段和方法,当类访问静态方法静态字段,实例调用方法时就会去类型对象中查找静 ...
- Python日期格式化知识
Python中日期格式化是非常常见的操作,Python 中能用很多方式处理日期和时间,转换日期格式是一个常见的功能.Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时 ...
- Python 目录【持续更新中】
Python 基础 字符编码 数据类型 文件处理 流程控制 练习题 函数,递归 匿名函数.内置函数 装饰器变形记 函数装饰器 递归 二分法 迭代器和生成器 协程函数 列表表达式 生成器表达式 异常处理 ...
- 一致性 hash 算法(转)
add by zhj:介绍了什么是一致性hash,以及实现一致性hash的一种算法. 原文:http://my.oschina.net/u/195065/blog/193614 目录[-] 一致性 h ...
- oracle(五)tkprof 使用 transient kernal profile 侧面 轮廓
1.show parameter sql_trace value是false表示系统当前不会产生trace文件 2.使产生trace文件 alter session set sql_trace = t ...
- C#静态类,静态构造函数,静态变量
静态变量位于栈上,它是一个全局变量,在编译期就已经生成. public class Cow public static int count; private int id; { id = ++coun ...