函数 (二) 名称空间与作用域
一、什么是名称空间
我们写一段代码,里面肯定会定义一些变量名,函数名,而一旦我们运行代码,python解释器在加载这些代码的时候,会在内存中开辟一片空间专门用来存放这些名字以及这些名字所绑定的值的关系,
这块内存就被称为名称空间。
二、名称空间分类
名称空间分为三种:
△内置名称空间
内置名称空间是用来存放python解释器的一些内置方法明以及变量名的。这些名称是在解释器启动的时候就加载好的,我们随时可以调用。比如常见的 print( )、input( )、len( )等都是内置方法,我们在写代码的时候直接调用就行。而存放他们的名字的地方就叫做内置名称空间。
△全局名称空间
我们在写一段代码的时候,除了函数内所定义的变量以及函数外,其他的变量名以及函数名所存放的地方就叫做全局名称空间。一旦我们定义好这个变量或者函数,那么我们可以在代码的任意地方调用。
△局部名称空间
存放函数内定义的变量名以及函数内嵌套的函数名的地方叫做局部名称空间。他们只能在函数内部(包括函数内嵌套的函数内部)被调用。
三、名称的加载顺序
当我们打开解释器的时候内置变量以及函数就立即被加载,当我们执行一段代码的时候,全局变量以及函数才被加载,但是函数内部并不会被执行,只有在函数被调用的时候才会加载它内部的变量以及内嵌函数,所以,名称的加载顺序是:内置名称---->全局名称---->局部名称
四、名字的查找顺序
与名称的加载顺序刚好相反,python解释器在用到一个变量或者函数的时候,它会优先从局部名称空间去查找,如果没有,再到全部名称空间去查找,如果还没有,才会去内置名称空间去查找。
示例如下:
1 x = 0
2 def input():
3 x = 1
4 print(x)
5 input()
#大家都知道python内置的一个方法叫做input( ),他是用来做用户交互的,但是如果我们自己定义一个input函数,
#那么再调用 input( )这个方法的时候,它会先从全局命名空间找input这个名字,如果找得到,那么它就不会再去
#内置名称空间去调用内置的input()方法了。而这个我们自定义的input方法内部有一个变量x,全局里还有一个变
#量也叫x,这个时候我们在函数内部调用x,那么解释器就会先从局部名称空间去找,很显然,它能找到,那么将不会再
#去全部或者内置名称空间里去找了,所以最后打印的x的值为1
五、作用域
作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
局部作用域:局部名称空间,只能在局部范围内生效
六、global关键字和nonlocal关键字
△global
虽然在局部作用域内可以调用全局作用域的变量,但是它是没有权限修改,如果非要修改,那么就要用到global这个关键字了,如下:
1 a = 10
2 def func():
3 global a
4 a = 20
5
6 print(a) #调用函数之前a的值为10
7 func()
8 print(a) #调用函数之后a的值就被修改为20了
△nonlocal
nonlocal关键字是用来改变外部离自己最近的局部变量
七、函数的嵌套
函数里面可以嵌套另外一个函数:
1 def outer():
2 def inner():
3 pass
八、闭包
满足一下两种情况的函数就成为闭包:
①有函数的嵌套
②内部函数调用外部函数的变量(不是指全局变量)
如下:
1 def outer():
2 a = 1
3 def inner():
4 print(a)
九、闭包的应用
下面的例子是写一个简单的爬网页函数,将指定网页的源代码打印出来:
1 from urllib.request import urlopen
2
3 def get_url():
4 url = 'http://www.xiaohua100.cn/index.html'
5 def get_html():
6 res = urlopen(url).read()
7 print(res)
8 get_html()
9 get_url()
- 【java.lang.UnsupportedClassVersionError】版本不一致出错
- Yeoman 官网教学案例:使用 Yeoman 构建 WebApp
- JSP与JavaBeans
- Log4j官方文档翻译(四、如何在java中输出日志消息)
- 展望未来:使用 PostCSS 和 cssnext 书写 CSS
- Java多线程之Runable与Thread
- 关于 devbridge-autocomplete 插件多选操作的实现方法
- node-sass 安装失败的解决措施
- JavaMelody监控SQL
- 关于jboss的线程问题+java.lang.outofmemoryError
- 《了不起的 nodejs》中 TwitterWeb 案例 bug 解决
- java.lang.ClassNotFoundException与java.lang.NoClassDefFoundError的区别
- 【java开发系列】—— Tomcat编译报错
- java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 博客由Hexo转向Hugo
- 屏蔽掉向日葵的有效方法
- 帝国cms在防止内容采集方面做的工作
- 记录一次有意思的溯源
- 个人博客图片的解决方案
- types 和 @types 是什么?
- 一次绕过waf进行xss的经历
- opencv+python制作硬核七夕礼物
- 身份验证器是如何验证我们的身份?
- 谷歌开源NLP模型可视化工具LIT,模型训练不再「黑箱」
- MongoDB 案例:Document failed validation 错误
- 利用GoogleAppsScript自动回复短信实现保号
- 用php来查询graphql
- 利用树莓派的摄像模块实现“扫码枪”
- n ../../node_modules/@storybook/channels/dist/index.d.ts:25:9 - error TS1086: An accessor cannot ...