在工作中, 有时候会遇到一种情况: 动态地进行变量赋值, 不管是局部变量还是全局变量, 在我们绞尽脑汁的时候, Python已经为我们解决了这个问题.
Python的命名空间通过一种字典的形式来体现, 而具体到函数也就是 ​locals()​
和 ​globals()​
, 分别对应着局部命名空间和全局命名空间. 于是, 我们也就能通过这些方法去实现我们"动态赋值"的需求.
例如:
很自然, 既然 ​globals​
能改变全局命名空间, 那理所当然 ​locals​
应该也能修改局部命名空间.修改函数内的局部变量.
但事实真是如此吗? 不是!
输出:
程序运行报错了!
但是在第二次 ​print locals()​
很清楚能够看到, 局部空间是已经有那些变量了, 其中也有 ​变量a​
并且值也为 ​1​
, 但是为什么到了 ​print a​
却报出 ​NameError异常​
?
再看一个例子:
输出:
上下两段代码, 区别就是, 下面的有显示赋值的代码, 虽然也是同样触发了 ​NameError异常​
, 但是局部变量 ​s​
的值被打印了出来.
这就让我们觉得很纳闷, 难道通过 ​locals()​
改变局部变量, 和直接赋值有不同? 想解决这个问题, 只能去看程序运行的真相了, 又得上大杀器 ​dis​
~
根源探讨
直接对第二段代码解析:
在上面的字节码可以看到:
从上面罗列出来的几个关键语句的字节码可以看出, 直接赋值/读取 和 通过 ​locals()​
赋值/读取 本质是很大不同的. 那么触发 ​NameError异常​
, 是否证明通过 ​locals()[i] = 1​
存储的值, 和真正的局部命名空间 是不同的两个位置?
想要回答这个问题, 我们得先确定一个东西, 就是真正的局部命名空间如何获取? 其实这个问题, 在上面的字节码上, 已经给出了标准答案了!
真正的局部命名空间, 其实是存在 ​STORE_FAST​
这个对应的数据结构里面. 这个是什么鬼, 这个需要源码来解答:
看到这里, 应该就能明确了, 函数内部的局部命名空间, 实际是就是帧对象的f的成员 ​f_localsplus​
, 这是一个数组, 了解函数创建的童鞋可能会比较清楚, 在 ​CALL_FUNCTION​
时, 会对这个数组进行初始化, 将形参赋值什么都会按序塞进去, 在字节码 ​ 18 61 LOAD_FAST 0 (s)​
中, 第四列的0, 就是将 ​f_localsplus​
第 0 个成员取出来, 也就是值 "s".
所以 ​STORE_FAST​
才是真正的将变量存入局部命名空间, 那 ​locals()​
又是什么鬼? 为什么看起来就跟真的一样?
这个就需要分析 ​locals​
, 对于这个, 字节码可能起不了作用, 直接去看内置函数如何定义的吧:
从上面 ​PyFrame_FastToLocals​
已经看出来, ​locals()​
实际上做了下面几件事:
在这简单介绍下上面几个分别是什么鬼:
通过上面的源码, 我们已经很明确知道 ​locals()​
看到的, 的确是函数的局部命名空间的内容, 但是它本身不能代表局部命名空间, 这就好像一个代理, 它收集了A, B, C的东西, 展示给我看, 但是我却不能简单的通过改变这个代理, 来改变A, B, C真正拥有的东西!
这也就是为什么, 当我们通过 ​locals()[i] = 1​
的方式去动态赋值时, ​print a​
却触发了 ​NameError异常​
, 而相反的, ​globals()​
确实真正的全局命名空间, 所以一般会说
locals() 只读, globals() 可读可写
Original: https://blog.51cto.com/u_15722381/5483118
Author: ch3nnn
Title: Python locals() 的陷阱
相关阅读1
Title: python调用HEG工具批量处理MODIS数据
下面的代码主要用于使用python语言调用NASA官方的MODIS处理工具HEG进行投影坐标转换与重采样批量处理
主要参考
- HEG的用户手册:https://newsroom.gsfc.nasa.gov/sdptoolkit/HEG/HEG215/EED2-TP-030_Rev01_HEG_UsersGuide_2.15.pdf
- HEG批处理帮助:https://newsroom.gsfc.nasa.gov/sdptoolkit/HEG/HEG_Batch_job_Help.htm
主要的注意事项如下:
- 首先按照官方指南安装HEG工具,具体安装步骤可参考我的上篇博客:https://www.cnblogs.com/yhpan/p/11298595.html
- 根据HEG用户手册批量生成批处理参数文件,可以在HEG工具中生成一个文件,拿来自己改改用用
- 具体调用哪一个工具,参数文件如何写,请一定仔细阅读用户手册,东西全都在上面。一般常用的是resample.exe和swtif.exe,如果 实在无法判断可以先用HEG的GUI处理一个自己的数据,保存一个prm文件,然后根据这个文件中的参数,对照着用户手册一个一个的找,就可以了。
- 生成参数文件写入时 一定要注意,设定换行符为'\n',fo=open(prmfilename,'w',newline='\n'), 否则由于在windows系统下默认换行符为'\r\n',程序无法运行成功
下面是源码分享
# -*- coding: utf-8 -*-
"""
Created on Sun Feb 16 11:27:19 2020
调用HEG相关工具批处理MODIS数据,主要完成投影坐标转换与重采样
@author: pan
"""
import os
# 设置HEG相关环境变量
os.environ['MRTDATADIR']='D:/MyApps/HEG/HEG_Win/data'
os.environ['PGSHOME']='D:/MyApps/HEG/HEG_Win/TOOLKIT_MTD'
os.environ['MRTBINDIR']='D:/MyApps/HEG/HEG_Win/bin'
# 设置HEG的bin路径
hegpath = 'D:/MyApps/HEG/HEG_Win/bin'
# 指定处理模块的可执行程序文件路径,此处采用resample.exe,可以根据具体的处理问题设置
hegdo = os.path.join(hegpath, 'resample.exe')
hegdo = hegdo.replace('\\', '/') # 全路径以"/"连接
# 指定输入数据的路径
inpath = r'C:\Users\pan\Desktop\Py_ex\data\hdf'
inpath = inpath.replace('\\', '/')
# 指定输出数据的路径
outpath = r'C:\Users\pan\Desktop\Py_ex\data\hdf\out'
outpath = outpath.replace('\\', '/')
# os.chdir(inpath) #改变当前工作目录到输入数据目录
# 获取当前文件夹下的所有hdf文件
allfiles = os.listdir(inpath)
allhdffiles = []
for eachfile in allfiles:
if os.path.splitext(eachfile)[1] =='.hdf':
allhdffiles.append(eachfile)
print('--'*20)
print('文件数量为:', len(allhdffiles),',所有hdf文件如下')
print(' '+'\n '.join(allhdffiles))
print('--'*20)
# prm文件设置模块,需要首先在HEG工具中生成一个参考的prm文件,示例如下
# 设置prm文件存储路径
prmpath = r"C:\Users\pan\Desktop\Py_ex\data\hdf\prm"
prmpath = prmpath.replace('\\', '/')
for eachhdf in allhdffiles:
prm=['NUM_RUNS = 1\n',
'BEGIN\n',
'INPUT_FILENAME = ' + inpath+'/'+eachhdf+'\n',
'OBJECT_NAME = MODIS_Grid_8Day_1km_LST|\n',
'FIELD_NAME = LST_Day_1km\n',
'BAND_NUMBER = 1\n','SPATIAL_SUBSET_UL_CORNER = ( 90.0 -180.0 )\n',
'SPATIAL_SUBSET_LR_CORNER = ( -90.0 180 )\n',
'RESAMPLING_TYPE = BI\n',
'OUTPUT_PROJECTION_TYPE = ALBERS\n',
'ELLIPSOID_CODE = WGS84\n',
'OUTPUT_PROJECTION_PARAMETERS = ( 0.0 0.0 25.0 47.0 105.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 )\n',
'OUTPUT_PIXEL_SIZE = 500.0\n',
'OUTPUT_FILENAME = ' + outpath+'/'+eachhdf+'_out.tif\n',
'OUTPUT_TYPE = GEO\n',
'END\n']
prmfilename=prmpath +'/'+ eachhdf+'.prm'
prmfilename=prmfilename.replace('\\', '/')
#这里一定要注意,设定换行符为'\n',否则由于在windows系统下默认换行符为'\r\n',则无法运行成功
fo=open(prmfilename,'w',newline='\n')
fo.writelines(prm)
fo.close()
for eachhdf in allhdffiles:
prmfilepath=prmpath +'\\'+ eachhdf + '.prm'
prmfilepath=prmfilepath.replace('\\', '/')
try:
resamplefiles = '{0} -P {1}'.format(hegdo, prmfilepath)
os.system(resamplefiles)
print(eachhdf + ' has finished')
except:
# 提示错误信息
print(eachhdf + 'was wrong')
Original: https://www.cnblogs.com/yhpan/p/12324465.html
Author: 岁时
Title: python调用HEG工具批量处理MODIS数据
相关阅读2
Title: python之sort与sorted函数的区别
python之sort与sorted函数的区别
原创
文章标签 sort() sorted() 排序 python 文章分类 Python 后端开发
©著作权归作者所有:来自51CTO博客作者Rickyyan的原创作品,请联系作者获取转载授权,否则将追究法律责任
sort与sorted方法主要区别:
方法
应用对象
是否修改原对象
返回值
sort()
列表
是
None
sorted()
所有可迭代对象
否
返回新列表
sort(self, key, reverse):
reverse默认为False,升序
降序则,reverse=True
l = [9, 4, 2 ,5, 1, 2, 10]re = l.sort(reverse= True)print(l)print(re)#结果[10, 9, 5, 4, 2, 2, 1]None# 集合使用sort()print(set(l).sort())# 报错AttributeError: 'set' object has no attribute 'sort'
sorted(__iterable, key, reverse)
__iterable:可迭代对象,必须
key:排序字段,传入函数,可选
reverse:升序/降序,默认升序
l = [9, 4, 2 ,5, 1, 2, 10]s = set(l)print(s, '类型:',type(s))new_l = sorted(l)new_s = sorted(s)print('返回新列表:', new_l)print('返回新列表:', new_s)print('集合经过sorted()后,返回的是列表', type(new_s))print('原列表不变:', l)print('原集合不变:', s)# 执行结果{1, 2, 4, 5, 9, 10} 类型: 返回新列表: [1, 2, 2, 4, 5, 9, 10]返回新列表: [1, 2, 4, 5, 9, 10]集合经过sorted()后,返回的是列表 原列表不变: [9, 4, 2, 5, 1, 2, 10]原集合不变: {1, 2, 4, 5, 9, 10}
指定key排序
d = dict(z=3, a=9, f=6, e=1)# 以value字段排序,返回key列表new_d1 = sorted(d.keys(), key= lambda x:d[x])print(new_d1)# 以key排序,降序,返回key_value列表new_d2 = sorted(d.items(), key= lambda x:x[0], reverse= True)print(new_d2)# 执行结果['e', 'z', 'f', 'a'][('z', 3), ('f', 6), ('e', 1), ('a', 9)]
- 打赏
- 赞
- 收藏
- 评论
- *举报
下一篇:Linux之find命令详解
Original: https://blog.51cto.com/u_13691477/5563129
Author: Rickyyan
Title: python之sort与sorted函数的区别
相关阅读3
Title: 【Python】开发过程中经常使用到的5种设计模式有哪些?
推荐文章
2023年,摸鱼计划系列活动又跟大家见面了,我们活动规则不变,福利升级! 新的一年,继续把工作学习中的bug处理、碎片知识,统统记录到博客里。留下自己在技术之路的成长足迹。
推荐原创51CTO博客12天前10000+阅读11点赞722评论1收藏
本周精彩博客回顾来啦~
推荐原创51CTO博客9天前10000+阅读2点赞评论收藏
想要在团队中处理代码时有效协作并跟踪更改,版本控制发挥着至关重要的作用。Git是一个版本控制系统,可以帮助开发人员跟踪修订、识别文件版本,并在必要的时候恢复旧版本。Git对于有一定编程经验的用户来说虽然不算太难,但是想要玩转一些高级功能也并不是件容易的事情。在这篇文章中,我将向你展示一些最实用的Git命令,手把手教你成为Git专家。 1.gitconfiggitconfig是你需要熟知的
原创SEAL安全1小时前144阅读点赞评论收藏
本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!作者| 慕课网精英讲师 JdreamZhang在计算机科学与技术领域中,分治法(Divide and Conquer) 是一种常见的算法思想。分治法的理解其实很简单,直接按照字面的意思理解就可以:"分而治之"。分(divide)是将一个大的问题分解成一些小的问题分别求解,治 (conquer)则是将分解的问题答案合并
原创imooc慕课君1小时前136阅读点赞评论收藏
匿名页面的缺页异常
原创luteresa1小时前135阅读点赞评论收藏
Spring-boot-route(十三)整合RabbitMQ
原创HI王小呆1小时前128阅读点赞评论收藏
@TOC1. 初始化列表1. 概念以一个冒号开始,接着是一个以逗号分隔的1数据成员列表,每个成员变量后面跟一个放在括号的初始值或表达式,即成员变量定义的地方2. 用法#include
原创萌新的日常1小时前129阅读点赞评论收藏
JAVA项目中如何实现接口调用?Httpclient Httpclient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持Http协议的客户端编程工具包,并且它支持HTTP协议最新版本和建议。HttpClient相比传统JDK自带的URL Connection,提升了易用性和灵活性,是客户端发送HTTP请求变得容易,提高了开发的效率。Okhttp 一个
原创Seattle小小瓜1小时前140阅读点赞1评论收藏
大家好,我是 CoderBin,本文将带着大家从零实现一个Mini-Vue系统。完成之后应该对vue整体的底层实现有一定的清晰,希望对你有所帮助,谢谢。
原创CoderBin1小时前143阅读点赞评论收藏
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:花家舍文章来源:GreatSQL社区原创前文回顾实现一个简单的Database系列(https://greatsql.cn/search.php?mod=blog&searchid=8&searchsubmit=yes&kw=%E5%AE%9E%E7
原创GreatSQL社区1小时前148阅读点赞评论收藏
Spring-boot-route(十一)数据库配置信息加密+(十二)整合redis做为缓存
原创HI王小呆1小时前142阅读点赞评论收藏
每日一刷之leetcode-day13
原创bug菌1小时前129阅读点赞评论收藏
1、使用echo "密码" | (管道符)使用场景: sudo 命令在使用普通用户执行 root 命令时有时候会需要输入密码,并且在输入密码后一段时间不需要再次输入(但是不影响),这时候可以使用echo "密码" | sudo 命令比如我需要一键清空服务器,则可以创建一个clear.sh文件(假使我的密码是 123456):echo "123456" | sudo rm -rf /*那么在执行的时
原创哭泣的馒头1小时前134阅读点赞评论收藏
1、while循环function while_read_LINE(){ while read LINE do echo $LINE done < $FILENAME}2、重定向法;管道法function While_read_LINE(){ cat $FILENAME | while read LINE do echo $LINE done}3、文件描述符法这种方
原创哭泣的馒头1小时前132阅读点赞评论收藏
微软发布了SQLServer for Linux,但是安装竟然需要3.5GB内存,这让大部分云主机用户都没办法尝试这个新东西,这篇我将讲解如何解决这个内存限制,要看关键的可以直接跳到第6步,只需要替换4个字节就可以解决这个限制。1.首先按照微软的给出的步骤安装和配置https://docs.microsoft.com/zh-cn/sql/linux/sql-server-linux-setup
原创雍州无名1小时前128阅读点赞评论收藏
本文将介绍TiDB数据库中的SQL的执行流程
原创wux_labs1小时前129阅读点赞评论收藏
背景在了解宏任务的时候了解到requestAnimationFrame,cancelAnimationFrame,然后做了实践。方法requestAnimationFrame(callback) 即屏幕刷新率,执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画,回调函数执行次数通常是每秒60次。cancelAnimationFrame 取消一个先前通过调用window.reque
原创不叫猫先生2小时前130阅读点赞评论收藏
本篇文章我们将进一步探讨下Guava Cache 实现层面的一些逻辑与设计策略,让我们可以对Guava Cache整体有个更加明朗的认识,促进实际使用中对其的理解。
原创架构悟道2小时前134阅读点赞评论收藏
MongoDB数据库实战系列,打造精品专栏。
原创哪吒编程3小时前182阅读点赞评论收藏
@toc1、简介1.1Ubuntuhttps://ubuntu.com/download/desktop(https://ubuntu.com/download/desktop)!在这里插入图片描述(https://s2.51cto.com/images/blog/202302/13061650_63e9655287b2c79548.png?xossprocess=image/watermark,
原创爱看书的小沐4小时前168阅读点赞评论收藏
这一讲,我们用ERC721的接口合约为例介绍solidity中的抽象合约(abstract)和接口(interface),帮助大家更好的理解ERC721标准。抽象合约如果一个智能合约里至少有一个未实现的函数,即某个函数缺少主体{}中的内容,则必须将该合约标为abstract,不然编译会报错;另外,未实现的函数需要加virtual,以便子合约重写。拿我们之前的第十讲:插入排序合约为例,如果我们还没想
原创sleep6666小时前227阅读点赞评论收藏
Original: https://blog.51cto.com/u_15052541/5578568
Author: 老男孩IT教育
Title: 【Python】开发过程中经常使用到的5种设计模式有哪些?