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]:

作⽤域:

  • 作⽤域就是作⽤范围, 按照⽣效范围来看分为 全局作⽤域和局部作⽤域
  • 全局作⽤域: 包含内置命名空间和全局命名空间. 在整个⽂件的任何位置都可以使⽤(遵循

    从上到下逐⾏执⾏). 局部作⽤域: 在函数内部可以使⽤.

    作⽤域命名空间:
  1. 全局作⽤域: 全局命名空间 + 内置命名空间
  2. 局部作⽤域: 局部命名空间

    我们可以通过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天 函数进阶和作用域的更多相关文章

  1. python学习笔记(10)函数(二)

    (函数的参数&递归函数) 一.函数的参数 Python的函数定义非常简单,但灵活度却非常大.除了正常定义的必选参数外,还可以使用默认参数.可变参数和关键字参数,使得函数定义出来的接口,不但能处 ...

  2. 【python学习笔记】10.充电时刻

    [python学习笔记]10.充电时刻 任何python都可以作为模块倒入 *.pyc:平台无关的经过编译的的python文件, 模块在第一次导入到程序中时被执行,包括定义类,函数,变量,执行语句 可 ...

  3. Deep learning with Python 学习笔记(10)

    生成式深度学习 机器学习模型能够对图像.音乐和故事的统计潜在空间(latent space)进行学习,然后从这个空间中采样(sample),创造出与模型在训练数据中所见到的艺术作品具有相似特征的新作品 ...

  4. Python学习笔记014——迭代工具函数 内置函数enumerate()

    1 描述 enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中. 2 语法 enumerate(sequ ...

  5. python学习笔记十——模块与函数

    第五章 模块与函数 5.1 python程序的结构 函数+类->模块              模块+模块->包                 函数+类+模块+包=Python pyth ...

  6. Python学习笔记(九)—— 函数

    一.函数调用: 1.python内部函数查询:http://docs.python.org/3/library/functions.html#abs 2.注意调用函数的参数个数和类型. 3.函数名其实 ...

  7. python学习笔记-(十一)面向对象进阶&异常处理

    上篇我们已经了解了一些面向对象的基础知识,本次就了解下面向对象的一些进阶知识(虽然我也不知道有什么卵用). 静态方法 静态方法是一种普通函数,就位于类定义的命名空间中,它不会对任何实例类型进行操作.使 ...

  8. python学习笔记之迭代器和函数(第三天)

    一.collection系列: 1.counter计数器 如果counter(dict)是对字典的一个补充,如果counter(list)则是对列表的补充,初步测试对字典的值进行排序. ####### ...

  9. Python学习笔记-Day3-python内置函数

    python内置函数 1.abs    求绝对值 2.all 判断迭代器中的所有数据是否都为true 如果可迭代的数据的所有数据都为true或可迭代的数据为空,返回True.否则返回False 3.a ...

随机推荐

  1. 【Oracle】查看被锁的表和解锁

    --以下几个为相关表SELECT * FROM v$lock;SELECT * FROM v$sqlarea;SELECT * FROM v$session;SELECT * FROM v$proce ...

  2. 解决Android sdk manager无法访问google服务器的问题

    开发Android应用,使用最广泛的开发工具应该就是ADT了,但是ADT默认只带了Android 4.3(API 18),如果需要安装其他版本的SDK,就需要启动Android SDK Manager ...

  3. August 18th 2017 Week 33rd Friday

    If you shed tears when you miss the sun, you also miss the stars. 如果你因为错过太阳而哭泣,你也将会错过繁星. If you have ...

  4. Jarsigner签名使用

    转载请标明出处: http://www.cnblogs.com/why168888/p/6548544.html 本文出自:[Edwin博客园] 如何签名: jarsgner-verbose-keys ...

  5. 英语的各种 n. adj. vt. vi. 等词性解释

    n. 名词 v. 动词(既可作及物动词,也可作不及物动词的就用这个表示) pron. 代词 adj. 形容词(后接名词) adv. 副词(修饰动词.形容词或其他副词) abbr. (这是一个缩写符号) ...

  6. 1、关于python第三方工具操作xls和xlsx格式的excel文档选型的吐血经历

    首先,最近看了python的一本书,其中第7章是关于文章操作的,就计划把python操作excel,word,txt,xml,html,json等格式的文档做个总结,并实现一些功能,但是,第一步就要把 ...

  7. python新建以时间命名的目录

    1.新建三级目录,第一级是去年的年份,第二级是去年的月,第三级为去年的日,在日的文件中写入今年的时分秒 import os import time import shutil def create_f ...

  8. 使用jenkins SonarQube gitlab 构建自动化发布系统

    目前持续集成的生态越来越完善,工具也有很多,开源的或商业的.如: 最最流行的,也是使用最多的 Jenkins 有着持续集成DNA的ThoughtWorks GO.理念:"Deployment ...

  9. JavaScript脚本的执行原理?

    JavaScript是一种动态.弱类型.基于原型的语言,通过浏览器可以直接执行. 当浏览器遇到\<script>标记的时候,浏览器会执行之间的JavaScript代码.嵌入的js代码是顺序 ...

  10. spring boot +druid数据库连接池配置

    1.启动应用入口修改 增加servlet注解 import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFacto ...