locals()是python 中的内置函数,他的作用是返回代表环境里全部变量的一个字典。最近做代码优化的时候发现用到的地方不少,就对其进行了一番研究,在此给大家分享这个内置函数的用法。
基本用法
直接打印即可
def xxx():
a = 1
c = {'ss': 222}
print(locals())
if __name__ == '__main__':
xxx()
结果为:
关键点->提取的是局部的变量
无论我们是在全局环境中加上一个别的变量,还是在main下方添加,这个locals里面都是没有那些额外的变量的,locals()代表的只有这个xxx函数中有的变量
而如果在main中使用,他会把上面的b也算进去,但不会包含xxx内部的变量,xxx函数本身也会变成一个字典的键。
思考如果有同名怎么办
众所周知,字典里不可能有相同的两个键,那么怎么处理同名的函数和变量呢?
其实,python中的函数和变量也是不能重名的,后定义的会覆盖掉前面定义的。
比如我们使用了xxx函数后,又定义了一个xxx变量,再使用这个函数的时候就会有类型错误。
环境变量字典locals()也会在同一个名称多次出现时,取他上方最后出现的那个作为他的值。
关键点->能够被传递吗
编写另一个函数yyy,接收参数并打印
运行发现可以很好的打印出来
关键点->可以被外部改变吗
尝试在yyy函数中增加键和修改键的值,观察效果
可以很明显的发现,在yyy函数中增加的键值对很好的传递了回去,但是修改的部分并没有生效
如何传递这份值,这里有个猜想,或许可以用字典的update方法,在不同的locals()之间更新
为便于观察,在打印的地方加了前导字符串进行了区分。
可以观察到,这里面xxx1处和yyy函数打印dic时,xxx函数中的locals()已经完整的传递了进来,但是在更新的过程中,你观察yyy1的打印,会发现没有a这个键。如果你在yyy1下方使用print(locals().get('a')),这是个None的返回值。
然后在yyy函数中又增加了a变量和e变量,往回传递的时候,还是没有把a的值改变。
关键点->内部自己可以改变吗
结合上一个步骤,我们直接在单个函数中尝试用字典键的方式进行改变a变量的值。结果在locals()打印中,依然没有改变。所以依靠传递locals()来修改变量还不如自己建立一个字典来的好用。
可以被复制吗
上面一节的结尾想要自己建一个字典,那么这个locals()能够直接被复制成字典吗。
我们从copy库中导入deepcopy,在新的函数中尝试。
可以很明显的看到,在这次操作中,zzz函数中的locals()的副本传递给了yyy,并更新了他的locals(),yyy中改变 了a变量的值,并再次传递了回去,但更新依然是无效的,yyy0和和yyy1处的打印显示了a还是没有被更新过来,效果和上面的几乎没有差别。 所以是可以复制的,但是没有什么大用。
使用小结
从上面的过程中可以看出,locals()可以传递,但只能更新没有的值,已有的值不能更新。使用的时候推荐直接用字典键赋值的方式增加,不需要倒手返回值。
常见使用场景
django渲染模板
在django前后端结合编程中,经常使用locals来直接把环境变量渲染给页面。
return render(request,'模板名称',context=locals())
在render函数的源代码里,这个功能是在服务端实现的渲染,返回的最终是个二进制的字符串,所以多余的环境变量也不用担心会泄露出去。