python学习笔记:第10天 函数进阶和作用域
1. 函数进阶
动态接收位置参数
之前写的函数都是固定参数的,假设有个函数需要的参数由几十个,一个个写在形参的位置会非常麻烦,因此我们要考虑使用动态参数,使用动态参数时需要在参数前加*,表示接收多个参数:
In [13]: def func5(a, b, c, d, e, f):
...: print(a, b, c, d, e, f)
In [14]: func5(1, 2, ,3 ,4 , 5, 6) # 按照之前的写法是在传参的时候参数的个数都是固定的
1 2 3 4 5 6
In [18]: def func6(*args): # 使用动态接收参数后可以接收任个位置参数
...: print(args)
In [19]:
In [19]: func6(1, 2, 3 ,4 , 5, 6, 7, 8, 9, 10)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
In [20]:
从上面的例子我们可以看出,动态参数可以接收任意个参数,在形参中作为一个元组的形式传递过来;但是此时要注意的是:动态参数必须要在位置参数的后面:
In [20]: def func7(*args, a, b):
...: print(args)
In [21]: func7(1, 2, 3, 4)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-21-8171430efdb6> in <module>
----> 1 func7(1, 2, 3, 4)
TypeError: func7() missing 2 required keyword-only arguments: 'a' and 'b'
In [22]:
位置参数放在后面的时候,所有的参数都被args接收了,即a和b永远接收不到参数,因此动态参数必须在位置参数的后面
In [22]: def func8(a, *args, b=100): # 正确使用方法
...: print(a, args, b)
In [23]: func8(1, 2, 3, 4)
1 (2, 3, 4) 100
In [24]: def func8(a, b=100, *args):
...: print(a, args, b)
In [25]: func8(1, 2, 3, 4)
1 (3, 4) 2
In [26]: func8(1, 2)
1 () 2
In [27]: func8(1)
1 () 100
In [28]:
从上面的例子可以看出,默认参数放在动态传参在之前时,只有在一种情况下才有效,即位置参数不够的情况下,会使用默认参数的值,那此时的动态传参也就没有意义了;所以只有当默认参数放在动态参数后面时,默认参数时永远生效的。
那么我们可以总结出动态传参的要注意的顺序:*位置参数, 动态参数, 默认参数
动态接收关键字参数
在python中使用*可以动态接收位置参数,但是这种方法并无接收关键字参数,在python中应该使用**来接收动态关键字参数
In [28]: def func8(**kwargs):
...: print(kwargs)
In [29]: func8(a='aaa', b='bbb')
{'a': 'aaa', 'b': 'bbb'}
In [30]:
顺序的问题, 在函数调⽤的时候, 如果先给出关键字参数, 则整个参数列表会报错.
def func(a, b, c, d):
print(a, b, c, d)
# 关键字参数必须在位置参数后⾯, 否则参数会混乱
func(1, 2, c=3, 4)
所以关键字参数必须在位置参数后⾯. 由于实参是这个顺序. 所以形参接收的时候也是这个顺序. 也就是说位置参数必须在关键字参数前⾯. 动态接收关键字参数也要在后⾯
最终顺序(*)为:
- 位置参数 > *args > 默认值参数 > **kwargs
这四种参数可以任意的进⾏使⽤.如果想接收所有的参数:
def func(*args, **kwargs):
print(args, kwargs)
func("麻花藤","⻢晕",wtf="胡辣汤")
动态参数的另⼀种传参⽅式:
def fun(*args):
print(args)
lst = [1, 4, 7]
fun(lst[0], lst[1], lst[2])
2. 命名空间
我们用于存放变量名和其值的对应关系的空间,可以给它一个名字叫命名空间,我们的变量存储的时候就是存储在这片空间内的。
命名空间的分类
- 全局命名空间:在单个py文件中,函数声明外的变量都属于全局变量都属于全局命名空间
- 局部命名空间:在函数中声明的变量会存放在局部命名空间
- 内置命名空间:python解释器内置的一些变量(如list,tuple,str,int等等)
命名空间的加载顺序
- 内置命名空间
- 全局命名空间
- 局部命名空间
取值顺序
- 局部命名空间
- 全局命名空间
- 内置命名空间
In[2]: a = 10
In[3]: def func1():
...: a = 20
...: print(a) # 函数内部有变量a,就优先取局部命名空间的变量
...:
In[4]: func1()
20
In[5]: print(a)
10
In[6]:
作⽤域:
- 作⽤域就是作⽤范围, 按照⽣效范围来看分为 全局作⽤域和局部作⽤域
- 全局作⽤域: 包含内置命名空间和全局命名空间. 在整个⽂件的任何位置都可以使⽤(遵循
从上到下逐⾏执⾏). 局部作⽤域: 在函数内部可以使⽤.
作⽤域命名空间:
- 全局作⽤域: 全局命名空间 + 内置命名空间
- 局部作⽤域: 局部命名空间
我们可以通过globals()函数来查看全局作⽤域中的内容, 也可以通过locals()来查看局部作
⽤域中的变量和函数信息
In[7]: a = 10
In[8]: def func():
...: a = 40
...: b = 20
...: def abc():
...: print("哈哈")
...: print(a, b) # 这⾥使⽤的是局部作⽤域 40,20
...: print(globals()) # 打印全局作⽤域中的内容
...: print(locals()) # 打印局部作⽤域中的内容
...:
In[9]: func()
- locals(): 查看当前作用域中的名字
- globals(): 查看全局作用域中的名字
3. 关键字global和nonlocal
首先先介绍一下函数的嵌套:
# 函数的嵌套,即函数里面定义函数,该函数只能在上层函数中使用
def fun2():
print(222)
def fun3():
print(666)
print(444)
fun3()
print(888)
print(33)
fun2()
print(555)
# 打印结果:
# 33
#222
# 444
# 666
# 888
# 555
使用global关键字可以在局部作用域中把全局命名空间的变量拿过来用(可以修改),如果指定的变量不存在则创建。
In[12]: a = 100
In[13]: def func2():
...: global a # 此时这个函数中的a已经是全局变量a了
...: a = 78
...: print(a)
...:
In[15]: func2()
78
In[16]: a # 此时可以看到,a的值已经变成78了
Out[16]: 78
nonlocal关键字表示在局部作用域中,调用父级命名空间中的变量。
In[19]: a = 3
In[20]:
In[20]: def func3():
...: a = 9
...: def func4():
...: nonlocal a # 此时使用的就是func3中的a变量
...: a = 23 # 因此func3中的a被修改成了23
...: print(a)
...: func4()
...: print(a)
...: func3()
23 # 函数func4打印的结果
23 # 函数func3打印的结果
In[21]: print(a)
3 # 最后函数结束打印的结果
- global:把全局的内容引入到局部,如果全局命名空间没有这个变量,则创建这个变量而并不会报错
- nonlocal:在局部, 把上一层的变量引入进内部. 如果上一层没有. 继续上一层;最外层函数中还没有时,会报错(不会再全局命名空间中查找)
python学习笔记:第10天 函数进阶和作用域的更多相关文章
- python学习笔记(10)函数(二)
(函数的参数&递归函数) 一.函数的参数 Python的函数定义非常简单,但灵活度却非常大.除了正常定义的必选参数外,还可以使用默认参数.可变参数和关键字参数,使得函数定义出来的接口,不但能处 ...
- 【python学习笔记】10.充电时刻
[python学习笔记]10.充电时刻 任何python都可以作为模块倒入 *.pyc:平台无关的经过编译的的python文件, 模块在第一次导入到程序中时被执行,包括定义类,函数,变量,执行语句 可 ...
- Deep learning with Python 学习笔记(10)
生成式深度学习 机器学习模型能够对图像.音乐和故事的统计潜在空间(latent space)进行学习,然后从这个空间中采样(sample),创造出与模型在训练数据中所见到的艺术作品具有相似特征的新作品 ...
- Python学习笔记014——迭代工具函数 内置函数enumerate()
1 描述 enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中. 2 语法 enumerate(sequ ...
- python学习笔记十——模块与函数
第五章 模块与函数 5.1 python程序的结构 函数+类->模块 模块+模块->包 函数+类+模块+包=Python pyth ...
- Python学习笔记(九)—— 函数
一.函数调用: 1.python内部函数查询:http://docs.python.org/3/library/functions.html#abs 2.注意调用函数的参数个数和类型. 3.函数名其实 ...
- python学习笔记-(十一)面向对象进阶&异常处理
上篇我们已经了解了一些面向对象的基础知识,本次就了解下面向对象的一些进阶知识(虽然我也不知道有什么卵用). 静态方法 静态方法是一种普通函数,就位于类定义的命名空间中,它不会对任何实例类型进行操作.使 ...
- python学习笔记之迭代器和函数(第三天)
一.collection系列: 1.counter计数器 如果counter(dict)是对字典的一个补充,如果counter(list)则是对列表的补充,初步测试对字典的值进行排序. ####### ...
- Python学习笔记-Day3-python内置函数
python内置函数 1.abs 求绝对值 2.all 判断迭代器中的所有数据是否都为true 如果可迭代的数据的所有数据都为true或可迭代的数据为空,返回True.否则返回False 3.a ...
随机推荐
- C#耗时计算
System.Diagnostics.Stopwatch watch = new Stopwatch(); watch.Start(); //init();计算耗时的方法 watch.Stop(); ...
- ajax实现跨域请求
因为现在一直用的mvc,所以就以mvc来说说ajax跨域提交. 首先说说跨域,简单说就是不同域名访问,比如在aaa.com访问bbb.com. 就拿招聘网站来说,分为两种用户,求职者和企业,求职者端是 ...
- Python学习---迭代器学习1210
可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的generator fun ...
- Xcode中模拟器慢
取消下图中框框打勾
- 真实世界中的 Swift 性能优化
那么有什么因素会导致代码运行缓慢呢?当您在编写代码并选择架构的时候,深刻认识到这些架构所带来的影响是非常重要的.我将首先谈一谈:如何理解内联.动态调度与静态调度之间的权衡,以及相关结构是如何分配内存的 ...
- 【CSS】关于flex
flex 属性用于设置或检索弹性盒模型对象的子元素如何分配空间. 如果元素不是弹性盒模型对象的子元素,则 flex 属性不起作用. 设为Flex布局以后,子元素的float.clear和vertica ...
- 6、Spring Cloud -熔断器Hystrix
6.1.什么是Hystrix 在分布式系统中.服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务 出现故障,导致依赖于它们的其他服务出现远程调度的线程阻塞. Hystrix是Netfli ...
- [Python web开发] Web框架开发基础 (一)
Python WEB框架 WSGI,WEB Server Gateway Interface,可以看做是一种底层协议,它规定了服务器程序和应用程序各自实现上面接口.Python的实现称为wsgiref ...
- mysql存储过程学习(一)
转载 什么是存储过程,存储过程的作用及优点 mysql存储过程详细教程 mysql 使用存储过程批量插数据 一.存储过程介绍: 存储过程(Stored Procedure)是一组为了完成特定功能的 ...
- VS2012与VS2015同时安装用VS2012创建MFC程序时弹出编译错误”fatal error C1083: 无法打开包括文件:“mprapidef.h”: No such file or directory”的解决办法
在WIndows 7操作系统上同时安装VS2012与VS2015并用VS2012创建MFC程序时弹出编译错误”fatal error C1083: 无法打开包括文件:“mprapidef.h”: No ...