python基础—函数嵌套与闭包

1、名称空间与作用域

1 名称空间分为:

1 内置名称空间   内置在解释器中的名称

2 全局名称空间   顶头写的名称

3 局部名称空间

2 找一个名称的查找顺序:先在局部名称空间找,再到全局名称空间找,再到内置名称空间

3 Globals()  查看全局名称空间的内容

Locals()   查看局部名称空间的内容

4 全局作用域包含内置名称空间和全局名称空间

 局部作用域包含局部名称空间

1 查看内建名称空间的内容:

2 作用域

x=1
def foo():
x=100
print(x)
foo()
print(x)

输出结果:

100
1

3 一定要注意函数要先定义,后使用

def foo():
print("from foo")
bar()
def bar():
print("from bar")
foo()

输出结果:

from foo
from bar

 

def foo():
print("from foo")
bar()
foo()
def bar():
print("from bar")

输出结果:

NameError: name 'bar' is not defined  #报错

4 Globals()  查看全局名称空间的内容

  Locals()   查看局部名称空间的内容

x=1
def func():
print("from func")
x=2
print(globals())
print(locals())
func()
print(globals())
print(locals())

输出结果:

from func
{'x': 1, '__cached__': None...
{'x': 2}
{'x': 1, '__cached__': None...
{'x': 1, '__cached__': None...

2、函数嵌套与静态嵌套域

嵌套调用

嵌套调用作用:将一个大的功能细化成各种小的函数功能并调用

def my_max(x,y):
res=x if x >y else y
return res
print(my_max(10,100))
def my_max4(a,b,c,d):
res1=my_max(a,b)
res2=my_max(res1,c)
res3=my_max(res2,d)
return res3
print(my_max4(1,20,3,4))

输出结果:

100
20

在函数内定义的函数 在外面不能用到

def f1():
def f2():
def f3():
pass
print("---->f1")
f2()
f2()

输出结果:

NameError: name 'f2' is not defined  #报错

#嵌套定义

x找值的过程:先在局部名称空间找,再到上一级的局部名称空间找,再到全局名称空间找,再到内置名称空间

x=0
def f1():
#x=1
print("---f1---",x)
def f2():
#x=2
print("---f2---",x)
def f3():
#x=3
print("---f3---",x)
f3()
f2()
f1()

输出结果:

---f1--- 0
---f2--- 0
---f3--- 0

3、函数对象

函数被称为第一类对象,函数可以被当做数据传递

(1)函数可以被赋值

直接输出函数名的值: 就是函数在内存中的地址

def foo():
print("foo")
print(foo)

输出结果: 

<function foo at 0x000000DD32CAAD90>

函数可以被赋值:将函数名代码的值赋给变量

def foo():
print("foo")
f=foo
print(f)
f()

输出结果:

<function foo at 0x0000003AEBEBAD90>
foo

(2)函数可以作为参数传递

函数可以作为参数传递

def foo():
print("foo")
def bar(func):
print(func)
func()
print(bar(foo))

输出结果:

<function foo at 0x000000A351B4AD90>
foo
None

 

(3)函数可以作为返回值

函数可以作为函数的返回值

def foo():
print("foo")
def bar(func):
print(func)
func()
return func
f=bar(foo)
print(f)
f()

输出结果:

<function foo at 0x000000BFD82CAD90>
foo
<function foo at 0x000000BFD82CAD90>
foo

(4)函数可以作为容器类型的元素

函数作为字典的键的值:

def add():
print("=======>function add")
def search():
print("=======>function search")
def delete():
print("=======>function delete")
def change():
print("=======>function change")
def tell_msg():
msg='''
search:查询
add:添加
delete:删除
change:修改
create:新建
'''
print(msg)
def create():
print('=======>function create') cmd_dic={
'search':search,
'add':add,
'delete':delete,
'change':change,
'create':create
}
while True:
tell_msg()
choice=input("please input your choice:")
cmd_dic[choice]()

4、函数闭包

(1)函数闭定义

闭包:首先必须是内部定义的函数,该函数包含对外部作用域而不是全局作用域名字的引用

定义:内部函数的代码包含对外部函数的代码的引用,但一定不是对全局作用域的引用

闭包的基本形式是:

在函数F1中,定义F2,F2只能引用F1定义的变量,之后F1函数返回F2的函数名字

这样就保证了可以将F1的执行结果赋予给一个变量,该变量可以在之后的任何时刻随时可以运行

使用闭包的好处:自带状态即变量,可以不用传参就用,方便。

闭包(closure)是函数式编程的重要的语法结构。不同的语言实现闭包的方式不同。Python以函数对象为基础,为闭包这一语法结构提供支持的 (我们在特殊方法与多范式中,已经多次看到Python使用对象来实现一些特殊的语法)。Python一切皆对象,函数这一语法结构也是一个对象。在函数对象中,我们像使用一个普通对象一样使用函数对象,比如更改函数对象的名字,或者将函数对象作为参数进行传递。

  

(2)简单闭包举例

x=1000
def f1():
x=1
def f2():
print(x)
return f2
f=f1()
print(f)
x=123
f()

输出结果:

<function f1.<locals>.f2 at 0x000000C02BD1AF28>
1

(3)闭包的__closure__变量

闭包都有__closure__属性

__closure__对象会返回闭包应用外围作用域的变量信息。f.__closure__保存外围作用域的变量内存地址,f.__closure__[0].cell_contents存放的是外围作用域的变量的值。

对于那些不是闭包的函数对象来说,__closure__ 属性值为 None。

x=1
def f1():
x=1000
y=2
def f2():
y
print(x)
return f2
f=f1() #f ---> 内部的函数f2
f()
print(f.__closure__)
print(f.__closure__[0])
print(f.__closure__[0].cell_contents)
print(f.__closure__[1])
print(f.__closure__[1].cell_contents)

输出结果:

1000
(<cell at 0x000000429E165D68: int object at 0x000000429E0A9EB0>, <cell at 0x000000429E165D98: int object at 0x0000000059C0EF50>)
<cell at 0x000000429E165D68: int object at 0x000000429E0A9EB0>
1000
<cell at 0x000000429E165D98: int object at 0x0000000059C0EF50>
2

举例:__closure__ 属性值为 None

x=1
def f1():
def f2():
print(x)
return f2
f=f1() #f ---> 内部的函数f2
f()
print(f.__closure__)

输出结果为:

1
None

(4)闭包应用

Windows中cmd中执行pip install requests 安装requests库件

爬baidu网站的程序

from  urllib.request import urlopen
def get(url):
return urlopen(url).read()
print(get('http://www.baidu.com'))
print(get('http://www/python.org'))

将上面”爬百度”的程序修改成闭包模式:

from  urllib.request import urlopen
def f1(url):
def f2():
print(urlopen(url).read())
return f2
baidu=f1('http://www.baidu.com')
python=f1('http://www.python.org')
baidu()
python()

python基础—函数嵌套与闭包的更多相关文章

  1. python之函数嵌套与闭包

    一:函数的嵌套:在函数内部在定义一个函数,一层套一层 def father(name): print("from father %s" %name) def son(): prin ...

  2. 《Python》 函数嵌套、闭包和迭代器

    一.函数的嵌套: 1.函数的嵌套调用 def max2(x,y): m = x if x>y else y return m def max4(a,b,c,d): res1 = max2(a,b ...

  3. python基础,函数,面向对象,模块练习

    ---恢复内容开始--- python基础,函数,面向对象,模块练习 1,简述python中基本数据类型中表示False的数据有哪些? #  [] {} () None 0 2,位和字节的关系? # ...

  4. python基础—函数装饰器

    python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...

  5. python基础——函数的参数

    python基础——函数的参数 定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了.对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复 ...

  6. Python基础-函数参数

    Python基础-函数参数 写在前面 如非特别说明,下文均基于Python3 摘要 本文详细介绍了函数的各种形参类型,包括位置参数,默认参数值,关键字参数,任意参数列表,强制关键字参数:也介绍了调用函 ...

  7. python基础----函数的定义和调用、return语句、变量作用域、传参、函数嵌套、函数对象、闭包、递归函数

    1.函数的定义: 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可 ...

  8. python中函数嵌套、函数作为变量以及闭包的原理

    嵌套函数: python允许创建嵌套函数.也就是说我们可以在函数里面定义函数,而且现有的作用域和变量生存周期依旧不变. 例子: #encoding=utf-8 def outer():    name ...

  9. day10-Python运维开发基础(函数嵌套、nonlocal声明局部变量、闭包、locals/globals、lambda表达式)

    1. 函数的嵌套与nonlocal 声明局部变量 # ### 函数的嵌套 """ 函数和函数之间可以互相嵌套: 嵌套在内层的叫做内函数 乔涛在外层的叫做外函数 " ...

随机推荐

  1. Java设计模式(一)工厂模式

    一.场景描述 仪器数据文件的格式包含Pdf.Word.Excel等多种,不同种格式的文件其数据的采集方式不同,因此定义仪器数据采集接口,并定义PDF.Excel等不同的数据采集类实现该接口. 通过工厂 ...

  2. python解决图的最短路径问题

    在hihoCoder上遇到一个算法题目,描述如下: 对图结构有了解的不难发现,这是经典的求图的最短路径问题.以下是python代码: def findMin(row): minL = max(row) ...

  3. Ambari Log Search

    文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/8630195.html  转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点, ...

  4. jar包和war包的介绍与区别

    在学习maven的过程中接触到了jar包和war包.之前在写小项目的时候真的遇到过war包,当时为了找到jar包,把war包 的后缀名改成了.rar的压缩文件,在里面提取出来jar包来用.其实jar包 ...

  5. 19.C++-(=)赋值操作符、智能指针编写(详解)

    (=)赋值操作符 编译器为每个类默认重载了(=)赋值操作符 默认的(=)赋值操作符仅完成浅拷贝 默认的赋值操作符和默认的拷贝构造函数有相同的存在意义 (=)赋值操作符注意事项 首先要判断两个操作数是否 ...

  6. markdown语法小结

    引用数学公式1 \[ \begin{equation} \pi^2=x^2+y \label{eq_lab1} \end{equation} \] Here we cite this equation ...

  7. NVL2 这个函数,

    NVL2(expr1,expr2,expr3)     如果参数表达式expr1值为NULL,则NVL2()函数返回参数表达式expr3的值:如果参数表达式expr1值不为NULL,则NVL2()函数 ...

  8. 使用listview空控件展示数据

    1.使用listview控件可以一次性的将有关的全部图像保存在控件中,建立集合图像. 图像列表控件的主要属性 属性                                           ...

  9. python全栈学习--day5

    字典 特点:字典是python中唯一的映射类型,采用键值对(key-value) 的形式存数据. 存储大量的数据,是关系型数据,查询数据快. 字典初始说明: 遍历字典从列表开始,列表是从头便利到尾的. ...

  10. 十个 PHP 开发者最容易犯的错误

    PHP 语言让 WEB 端程序设计变得简单,这也是它能流行起来的原因.但也是因为它的简单,PHP 也慢慢发展成一个相对复杂的语言,层出不穷的框架,各种语言特性和版本差异都时常让搞的我们头大,不得不浪费 ...