448 字
1 分钟
妙妙 Python * 2
从这个视频引入
先来看题!

第一题(原题)
def add_list(item, lst=[]): lst.append(item) return lstprint(add_list(1), add_list(2))输出是[1, 2] [1, 2]。因为lst是同一个。
第一题A:[1] [2]
加3字符
def add_list(item, lst=[]): lst.append(item) return lstprint(add_list(1), add_list(2,[]))目前能想到最短的,同理换一下顺序也行:
def add_list(item, lst=[]): lst.append(item) return lstprint(add_list(1,[]), add_list(2))思路是创建新的空lst
第一题C:[1] [1, 2]
第一个想到的需要加4字符:
def add_list(item, lst=[1]): lst.append(item) # print(add_list.__defaults__) return lstprint(add_list(1,[]), add_list(2))但是啊重新思考一下,[1] [1, 2],实际上和我分开print是一样的,而分开print实际上就是闭包,让这个lst复制一份,而不是共享引用(不知道这么理解对不对,有点像CoW的)。而最简单的让lst是真实的值的办法就是对他进行一些操作,但为了尽可能少改,操作结果不能改变。而python里非常通用的操作就是*。
def add_list(item, lst=[]): lst.append(item) return lst*1print(add_list(1), add_list(2))因此,只需要加2字符。
第二题(原题)
funcs = [lambda: i for i in range(3)]print([f() for f in funcs])输出是[2, 2, 2],这个真得慢慢想才能理解。lambda表达式相当于return了i,但是i是变量,会延迟绑定,所以f() return的都是同一个i的引用。
第二题A:[0, 1, 2]
这个和第一题C有点像,本质上是要进行一次copy,而不要存引用。加4字符。
funcs = [lambda i=i: i for i in range(3)]print([f() for f in funcs])没忍住看了眼评论区,[]改(),2字符的确实精妙,推导式变生成器了
funcs = (lambda: i for i in range(3))print([f() for f in funcs])第二题C:[0, 0, 0]
这个是先做的,lambda表达式,把return改成固定的就行,所以修改1字符
funcs = [lambda: 0 for i in range(3)]print([f() for f in funcs])第二题A还是算我的4字符,那么就是3+2+4+1=10。不考虑黑魔法,理论极限应该就是3+2+2+1=8?不过考虑到特定版本的UAF,可能还真不好说..(https://github.com/python/cpython/issues/91153,https://github.com/Nambers/python-audit_hook_head_finder)
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
妙妙 Python * 2
https://blog.chaomixian.top/posts/python-lmao/ 部分信息可能已经过时
相关文章 智能推荐









