函数进阶

命名空间和作用域

命名空间

命名空间 有三种
内置命名空间 —— python解释器
  就是python解释器一启动就可以使用的名字存储在内置命名空间中
  内置的名字在启动解释器的时候被加载进内存里
全局命名空间 —— 我们写的代码但不是函数中的代码
  是在程序从上到下被执行的过程中依次加载进内存的
  放置了我们设置的所有变量名和函数名
局部命名空间 —— 函数
  就是函数内部定义的名字
  当调用函数时 才会产生这个名称空间 随着函数执行的结束 这个命名空间随之消失

在局部:可以使用全局、内置命名空间中的名字
在全局:可以使用内置命名空间中的名字,但是不能用局部中使用
在内置:不能使用局部和全局的名字的

如下面的例子

  1. #局部命名空间的名字 不可以在全局空间中被调用
  2. def func():
  3. a = 1
  4. func()
  5. print(a) #报错——NameError: name 'a' is not defined

命名空间的使用原则:

  1、在正常情况下,直接使用内置的名字
  2、当我们在全局定义了和内置命名空间中同名的名字时,会使用全局的名字
  3、在嵌套中,当自己的这一级中有所需的名字时,就不去找上一级找了
  4、在嵌套中,如果自己没有 就找上一级要 上一级没有再找上一级 如果内置的名字空间也没有 就报错
  5、多个函数应该拥有多个独立的局部名字空间,不互相共享

作用域

作用域 有两种
  全局作用域 —— 作用在全局 —— 内置和全局命名空间中的名字都属于全局作用域 —— globals()
  局部作用域 —— 作用在局部 —— 函数(局部命名空间中的名字属于局部作用域) —— locals()

我们接着来看下面  global 的例子

  1. #global 声明过得变量,让在函数外部的 print() 可以进行打印
  2. a = 1
  3. def func():
  4. global a #使用 global 进行声明
  5. a = 2
  6. func()
  7. print(a) #输出结果为 2
  8.  
  9. b=1
  10. def func():
  11. #global b
  12. b = 2
  13. func()
  14. print(b) #此时结果还是 1,因为在内部的任何操作 不影响外部的

对于不可变数据类型 在局部可以查看全局作用域中的变量,但是不能直接修改
如果想要修改,需要在程序的一开始添加 global 声明
如果在一个局部(函数)内声明了一个 global 变量,那么这个变量在局部的所有操作将对全局的变量有效

接着我们对比着 global() 变量来看 locals() 变量

  1. #可以看出两个打印的内容一个为局部一个为全局
  2. a = 1
  3. b = 2
  4. def func():
  5. x = 'aaa'
  6. y = 'bbb'
  7. print(locals()) #输出局部的变量,根据 locals 所在的位置
  8. print(globals()) #永远打印全局的名字,可以看到打印出了好多内容
  9.  
  10. func()

你一定会觉得 globals 函数在很多时候很好用(我也是这么觉得着)
可以 globals 这个函数涉及到代码的安全性 不推荐使用
可以通过传参和接收返回值 来完成原本使用 global 完成的事情

  1. #通过传参和接收返回值来时实现调用全局变量
  2. a = 1
  3. def func():
  4. global a
  5. a = 3
  6.  
  7. func()
  8. print(a)
  9.  
  10. #改为:
  11.  
  12. a = 2
  13. def func(a):
  14. a += 1
  15. return a
  16.  
  17. print(func(a)) #此时返回 3

函数的嵌套与调用

  1. #求两个数字的最大值
  2. def max(a,b):
  3. return a if a > b else b
  4. print(max(15,98))

  5. #求三个数的最大值
  6. def the_max(a,b,c):
  7. e = max(a,b) #把其中的两个值 丢给 max 去解决了
  8. return max(e,c)
  9. print(the_max(56,85,65))

不能直接调用函数内层的函数名

  1. def outer():
  2. def inner():
  3. print('inner')
  4.  
  5. #outer() #没有结果
  6. #inner() #报错
  7. #outer(inner()) #报错

可以使用 nonlocal 实现函数嵌套调用

  1. # nonlocal
  2. # 对全局无效
  3. # 对局部 也只是对 最近的 一层 有影响
  4. def outer():
  5. a = 1
  6. def inner():
  7. b = 2
  8. print(a) #内部函数可以使用外部函数的变量
  9. print('inner')
  10. def inner2():
  11. print(a,b)
  12. print('inner2')
  13. nonlocal a #声明了上面第一次出现 a 局部变量,没找到 则报错(不常用)
  14. #global #在此处使用不能达到要求,因为此时 a = 1 为局部变量
  15. a += 1 #在这里操作是想修改上面 a = 1 的这个值(不可变数据类型的修改)
  16. inner2() #函数必须是先定义后调用
  17. print('局部变量 a:',a)
  18. inner()
  19. outer()
  20.  
  21. #输出结果
  22. '''
  23. 1
  24. inner
  25. 1 2
  26. inner2
  27. 局部变量 a: 2 #这里可以看到外部函数的变量在内部函数中被修改了
  28. '''

函数的赋值

函数名可以用于:赋值、容器类型的元素、返回值、参数

  1. #函数名的赋值与作为容器类型的元素使用
  2. def func():
  3. print(123)
  4.  
  5. #func()    #函数名就是内存地址
  6. func2 = func #函数名可以用于赋值
  7. func2()    #所以结果为 123
  8.  
  9. l = [func,func2] #函数名可以作为容器类型的元素 如下面 for 循环
  10. print(l) #可以看出赋值后的内存地址是一致的
  11. for i in l:
  12. i()
  1. #函数名作为返回值与参数
  2. def func():
  3. print(123)
  4.  
  5. def func2(f):
  6. f()
  7. return f #函数名可以作为函数的返回值
  8. func2(func) #函数名可以作为函数的参数
  9. func3 = func2(func) #用于接收返回值
  10. func3()

闭包

定义:

必须符合:是嵌套函数,且内部函数调用外部函数的变量

  1. def outer():
  2. a = 1
  3. def inner():
  4. print(a) #到这里就是一个闭包了
  5. print(inner.__closure__) #可以使用 __closure__ 来检测是否是闭包
  6. #返回 (<cell at : int object at ,) 这些就表示是一个闭包了
  7. inner()
  8. outer()

闭包常用形式:接收返回值

在一个函数的内部去使用它外部的变量

  1. #不过下面并不是闭包常用的形式
  2. def outer():
  3. a = 1
  4. def inner():
  5. print(a)
  6. inner()
  7. outer()
  8.  
  9. #而下面的才是(采用接收返回值的形式)
  10. def outer():
  11. a = 1
  12. def inner():
  13. print(a)
  14. return inner
  15. inn = outer()
  16. inn()
  17. #在这里 a = 1 不会因为 outer() 函数的结束而消失,因为 inn() 后面可能会用到,所以才不会消失
  18. #使用闭包的好处在于 我保护了 a = 1 这个变量,它既不是全局变量,我又可以在使用它时,去使用它
  19. #延长了 a = 1 的声命周期 节省了创建和删除变量 a = 1 的时间

闭包的应用

  1. ##获取网站信息
  2. #现在已经可以拿到网页了,但是我们一般都要把它封装成一个函数
  3. from urllib.request import urlopen
  4. ret = urlopen('https://fanyi.baidu.com/translate#en/zh/inter').read()print(ret)
  5. print(ret)
  6.  
  7. #我们使用闭包来封装它
  8. from urllib.request import urlopen
  9. def get_url():
  10. url = 'https://fanyi.baidu.com/translate#en/zh/inter'
  11. def inner():
  12. ret = urlopen(url).read()
  13. print(ret)
  14. return inner
  15. get_func = get_url()
  16. get_func()
  17. #这样的好处在于 就算在外部调用了 n 次 get_func() 而创建 n 次 url 这个变量

day 10 - 1 函数进阶的更多相关文章

  1. python学习笔记:第10天 函数进阶和作用域

    目录 1. 函数进阶 2. 命名空间 3. 关键字global和nonlocal 1. 函数进阶 动态接收位置参数 之前写的函数都是固定参数的,假设有个函数需要的参数由几十个,一个个写在形参的位置会非 ...

  2. 巨蟒python全栈开发-第10天 函数进阶

    一.今日主要内容总览(重点) 1.动态传参(重点) *,** *: 形参:聚合 位置参数*=>元组 关键字**=>字典 实参:打散 列表,字符串,元组=>* 字典=>** 形参 ...

  3. Python【day 10】函数进阶-小结

    本节主要内容1.动态参数 *args **kwargs 形参:*args将多个位置参数聚合打包成元组 **kwargs将多个关键字参数聚合打包成字典 实参:*li1将列表进行解包打散成多个位置参数 * ...

  4. Python【day 10】函数进阶-动态函数

    形参小结 1.位置参数2.默认值参数3.动态参数 1.*args 位置参数的动态传参. 系统会自动的把所有的位置参数聚合成元组 2.**kwargs 关键字参数的动态传参. 系统会自动的把所有的关键字 ...

  5. 10.Python初窥门径(函数进阶)

    Python(函数进阶) 一.函数的传参(接上期) 形参角度(一共四种,后两种) 动态参数(万能参数)* # 定义一个函数时,*所有的位置参数聚合到一个元组中 def func(*args): # * ...

  6. python基础 (初识函数&函数进阶)

    函数基础部分 .什么是函数? 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率. 2.定义函数 定义:def 关键词开头,空格之后接函数名 ...

  7. python基础之 初识函数&函数进阶

    函数基础部分 1.什么是函数? 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率. 2.定义函数 定义:def 关键词开头,空格之后接函数名 ...

  8. python函数进阶(函数参数、返回值、递归函数)

    函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形 ...

  9. python大法好——递归、内置函数、函数进阶

    1.递归(自己干自己) def fun(n): n=n/2 print(n) if(n>2) fun(n) #函数调用 fun(10) 结果是5 2 1 0 递归的执行过程:递归执行到最里面一层 ...

随机推荐

  1. 在views中引用UserProfile报错RuntimeError: Model class apps.users.models.UserProfile doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

    如图报错,在settings中,该加的也加了啊! 显然类似于网上最容易遇到的解决方案如下图,是没有任何意义的 只要在view中有 from .models import UserProfile,Ver ...

  2. Druid 配置及内置监控,Web页面查看监控内容 【我改】

    转: Druid 配置及内置监控,Web页面查看监控内容 1.配置Druid的内置监控 首先在Maven项目的pom.xml中引入包 1 2 3 4 5 <dependency>      ...

  3. 安装webpack-dev-server始终不成功

    先安装了webpack,后来安装webpack-dev-server会一直出现这个问题,我把webpack提示的1.0.0 , 2.0.0 ,3.0.0全都在全局装了一遍都没用,还是会出现这个问题.最 ...

  4. hihocoder图像算子(高斯消元)

    描述 在图像处理的技术中,经常会用到算子与图像进行卷积运算,从而达到平滑图像或是查找边界的效果. 假设原图为H × W的矩阵A,算子矩阵为D × D的矩阵Op,则处理后的矩阵B大小为(H-D+1) × ...

  5. JavaEE正常开发怎么做

    如果不使用第三方框架,用JavaEE的内容怎么去开发呢? 例如这里有一个需求: 最传统的方案如下:

  6. java io系列23之 BufferedReader(字符缓冲输入流)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_23.html 更多内容请参考:java io系列01之 "目录" Buffere ...

  7. 9.组合模式(Composite Pattern)

    动机(Motivate):    组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素 ...

  8. centos 6.5 安装jdk1.8

    1.源码包准备: 首先到官网下载jdk-8u66-linux-x64.tar.gz, http://www.oracle.com/technetwork/java/javase/downloads/j ...

  9. 【英文文档】Solidifier for Windows Installation Guide

    Page 1Solidifier for Windows  Installation Guide Page 2McAfee, Inc.McAfee® Solidifier for Windows In ...

  10. Shell编程(三)Shell特性

    !$:显示上一条命令最后一个参数 $?: 上个命令的退出状态,或函数的返回值. alias xxx="命令":给命令取别名 xxx 通过 vim ~/.bashrc 里编辑,可以来 ...