函数对象、嵌套、名称空间与作用域以及闭包函数

目录:

  函数对象

  函数嵌套

  名称空间/作用域

  闭包函数

  global

一、函数对象

函数是第一类对象:指的是函数的内存地址可以像一个变量值一样去使用。(函数的内存地址指向的就是变量值)

def foo(): #foo=函数的内地址
    print('from foo')

1.变量值可以被引用

x=1    #foo=函数的内存地址
y=x    #将变量值1的地址给y

f=foo
print(f)       #打印函数的内存地址       
f()              #调用函数    

2.变量值可以当做参数传给另外一个函数

def bar(x):
    print(x)     #打印地址
    x()            #调用foo函数

#foo=函数的内存地址
bar(foo)  #将foo的内存地址传入bar函数

3.变量值可以当做函数的返回值

def func(x):
    return x

f=func(foo)
print(f)

4.变量值可以当做容器类型的元素

l=[foo,]
print(l)      #[<function foo at 0x0000000002061E18>]
l[0]()        #调用foo函数

dic={'1':foo}
print(dic)   #{'1': <function foo at 0x0000000001D11E18>}
dic['1']()   #调用foo函数 

变量值当做容器类型元素的应用:

 1 def register():
 2     print('注册....')
 3 
 4 def login():
 5     print('登录....')
 6 
 7 def pay():
 8     print('支付....')
 9 
10 def transfer():
11     print('转账....')
12 
13 func_dic={
14     '1':register,
15     '2':login,
16     '3':pay,
17     '4':transfer
18 }
19 
20 # func_dic['1']()
21 
22 while True:
23     print("""
24     0 退出
25     1 注册
26     2 登录
27     3 支付
28     4 转账
29     """)
30     choice=input('请输入你的操作: ').strip()
31     if choice == '0':break
32 
33     if choice not in func_dic:
34         print('输错的指令不存在')
35         continue
36 
37     func_dic[choice]()
View Code

 二、函数的嵌套

 

1.函数的嵌套调用:在一个函数的内部又调用其他函数

#比较1,2,3,4的大小
def max2(x,y):
    if x > y:
        return x
    else:
        return y

def max4(a,b,c,d):
    res1=max2(a,b)
    res2=max2(res1,c)
    res3=max2(res2,d)
    return res3
print(max4(1,2,3,4))

 2.函数的嵌套定义:在函数的内部又定义了其他函数

def func():
    def foo():
        print('from foo')
    print(foo)   #打印foo的地址
    foo()         #调用内部函数
    x=1
    print(x)
func()

3.函数嵌套的应用:

#定义一个关于圆的函数,可以计算面积和周长
from math import pi
def circle(radius,action):
    def cal_perimeter():
        return 2 * pi * radius

    def cal_area():
        return pi * (radius ** 2)

    if action == 1:
        res=cal_perimeter()
    elif action == 2:
        res=cal_area()
    return res

res=circle(10,1)
print(res)

 三、名称空间与作用域

 

1.名称空间Namespaces:指的就是存放名字与值内存地址绑定关系的地方(在内存)

  

 2.名称空间分为三大类

(1).内置命名空间:存放的是Python解释器自带的名字(变量名和函数名

    产生:python解释器的启动则产生

    销毁:Python解释器关闭则销毁

(2).全局名称空间:在顶级定义的名字
x=1    #全局
if True:
    y=2#全局
while True:
    while True:
        while True:
            z=3
def func():
    pass

    产生:执行Python程序时产生

    销毁:Python程序执行完毕则销毁

(3).局部名称空间:在函数内定义的名字
def foo():
    m=100     #局部
foo()

     产生:在函数调用时临时产生

    销毁:在函数调用完毕后则销毁

3.三种名称空间的产生的先后顺序:内置-->全局-->局部

   查找名字的顺序:从当前位置往外一层一层的查找

      如果当前在局部名称空间:局部-->全局-->内置

      如果当前在全局名称空间:全局-->内置

len=111
def foo():
    len=222
    print(len)
len=111
foo()    #结果为222

 

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

def foo1():
    def foo2():
        def foo3():
            print(x)    #x=0
     foo3()
  foo2()
foo1()

 4.作用域:指的是作用范围

全局作用域:包含内置与全局名称空间的名字

   特点:全局存活,全局有效

局部作用域:包含局部名称空间的名字

   特点:临时存活,局部有效

******作用域的关系在函数定义阶段就已经固定死了,与调用位置无关

 示范一:

#作用域在定义阶段就已经确定f1找的是全局名称
def f1():
    print(xxx)
xxx=111
def f2():
    xxx=222
    f1()
f2()

#在定义阶段,f1在局部名称空间找到xxx.运行时候也只会在局部找,但是代码执行时逐行执行,先引用,后定义,所以报错
def f1():
    print(xxx)#报错
    xxx=111
def f2():
    xxx=222
    f1()
f2()

 示范二:

xxx=111
def f1():
    print(xxx)#报错,定义时决定了作用域,不会去全局找。执行代码时逐行执行,先引用,后定义,所以报错
    xxx=222
f1()

四、闭包函数

闭包函数=函数对象+函数嵌套定义+作用域

闭:封闭,指的是该函数时定义一个函数内部的函数

包:该内部函数包含对外层函数名字的引用

闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

应用领域:延迟计算(原来我们是传参,现在我们是包起来)

例如:
    从纽约向上海以寄快递的形式邮寄一个人,需要将人放在集装箱内(相当于闭),但是由于时间久,就必然要在集装箱内部提供水,食物等(相当于包)

 示例代码:

def outter():
    x=1
    def inner():
        print('from inner',x)
    return inner
f=outter() #相当于 f=inner

def foo():
    # print(f)
    x=111111111111111111111111111111111111
    f()
foo()    #结果为1

为函数传值的两种方式:

def foo():
print('hello %s' %name)

方式一:直接以参数形式传入

def foo(name):
    print('hello %s' %name)
foo('egon')
foo('egon')
foo('egon')

方式二:闭包函数

def outter(name):
    # name='egon'
    def foo():
        print('hello %s' %name)
    return foo

f=outter('egon')
# print(f)
f()
f()

f1=outter('alex')
f1()
f1()

爬取数据应用:

pip3 install requests
import requests

问题
def get():
    response=requests.get(url)
    if response.status_code == 200:
        print(response.text)

解决方案一:
def get(url):
    response=requests.get(url)
    if response.status_code == 200:
        print(response.text)

get('https://www.baidu.com')
get('https://www.baidu.com')
get('https://www.baidu.com')

解决方案二:
def outter(url):
    # url='https://www.baidu.com'
    def get():
        response=requests.get(url)
        if response.status_code == 200:
            print(response.text)
    return get
baidu=outter('https://www.baidu.com')
cnblogs=outter('https://www.cnblogs.com')
baidu()
baidu()
baidu()
cnblogs()
cnblogs()
cnblogs()

 五、global

x=1
def func():
   x=2    #从内存角度来说,函数内部的局部变量在内存中的地方和全局变量不在一个地方,所以不会发生变量值覆盖
func()
print(x)  #结果为1

x=[]
def func():
   x.append(1)  #从全局找x,x位可变类型,追加
   x.append(2)
   x.append(3)
func()
print(x)#结果[1,2,3]

# global: 在局部声明变量是全局变量 x=1 def func(): global x x=2 func() print(x)#结果为2
# nonlocal:在局部声明变量是外层函数的变量 x=333 def f1(): x=222 def f2(): x=111 def f3(): nonlocal x x=0 f3() print('f2内部的x: ',x)#0 f2() print('这是f1内部的x: ',x)#222 f1() print(x)#333

 

posted @ 2018-09-26 19:40  ChuckXue  阅读(199)  评论(0编辑  收藏  举报