函數的命名空間,做用域,閉包等

1、三元表達式

if條件成功的值    if  條件   else else條件成功的值python

#if條件成立的結果 if 條件 else else條件成立的結果
# a = 20
# b = 10
# c = 5 if a>b else 10
# print(c)

2、函數的命名空間

命名空間一共分爲三種:閉包

  全局命名空間app

  局部命名空間函數

  內置命名空間url

*內置命名空間中存放了python解釋器爲咱們提供的名字:input,print,str,list,tuple...它們都是咱們熟悉的,拿過來就能夠用的方法。spa

三種命名空間之間的加載與取值順序:code

加載順序:內置命名空間(程序運行前加載)->全局命名空間(程序運行中:從上到下加載)->局部命名空間(程序運行中:調用時才加載)blog

取值:內存

  在局部調用:局部命名空間->全局命名空間->內置命名空間作用域

x = 1
def f(x):
    print(x)

print(10)

在全局調用:全局命名空間->內置命名空間

def fun(a,b,c):
    return max(a,b,c)#用的是內置命名空間的max
print(fun(1,2,3))


def max(a,b):
    c=a  if a>b else b
    return c
print(max(1,5))#用的1是本身定義的max 全局做用域裏面的

 

3、函數的做用域:

做用域

做用域就是做用範圍,按照生效範圍能夠分爲全局做用域和局部做用域。

全局做用域:包含內置命名空間、全局命名空間,在整個文件的任意位置都能被引用、全局有效

局部做用域:局部命名空間,只能在局部範圍生效

globals和locals方法

print(globals())
print(locals())

a = 20
b = 50
def haha():
x = 1
y = 2
print(globals()) #全局做用域中的名字
print(locals()) #局部做用域中的名字

# haha()
# print(globals()) #全局做用域中的名字
# print(locals()) #全局的局部仍是全局

global關鍵字

a = 10
def func():
    global a
    a = 20

print(a)
func()
print(a)

 

 

#做用域
#命名空間+做用域是分不開的
#兩種
#全局做用域:全局命名空間、內置命名空間
#局部做用域:局部命名空間

#小範圍的能夠用大範圍的
#可是大範圍的不能用小範圍的
#範圍從大到小(圖)
#在小範圍內,若是要用一個變量,是當前這個小範圍有的,就用本身的
#若是在小範圍內沒有,就用上一級的,上一級沒有就用上上一級的,以此類推。
#若是都沒有,報錯


def func(): return max(1,2,3) # print(func()) def max(a,b,c): return 2 # print(max(1,2,3)) #站在全局看: #使用名字: # 若是全局有:用全局的 # 若是全局沒有:用內置的 #爲何要有做用域的概念: #爲了函數內的變量不會影響到全局 # def max(): # a = 10 # b = 20 # # a = 2 # b = 3 # my_max(30,50)

 

4、函數的嵌套和做用域鏈

函數嵌套

def f1():
    def f2():
        def f3():
            print("in f3")
        print("in f2")
        f3()
    print("in f1")
    f2()
    
f1()

函數做用域鏈

def f1():
    a = 1
    def f2():
        def f3():
            print(a)
        f3()
    f2()

f1()
def f1():
    a = 1
    def f2():
        a = 2
    f2()
    print('a in f1 : ',a)

f1()

nonlocal關鍵字

def f():
    a = 3
    def f1():
        a = 1
        def f2():
            nonlocal a
            # 1.外部必須有這個變量
            # 2.在內部函數聲明nonlocal變量以前不能再出現同名變量
            # 3.內部修改這個變量若是想在外部有這個變量的第一層函數中生效

            a = 2
        f2()
        print('a in f1 : ', a)
    f1()
    print('a in f : ',a)

f()

函數名的本質

函數名本質上就是函數的內存地址

1.能夠被引用

def func():
    print('in func')

f = func
print(f)

 

2.能夠被看成容器類型的元素

def f1():
    print('f1')


def f2():
    print('f2')


def f3():
    print('f3')

l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
#調用
l[0]()
d['f2']()

3.能夠看成函數的參數和返回值

__author__ = 'Administrator'
def f():
    print("so good")
    return 1+2
l=f#函數名實際上就是普通的變量名
#print(l())

def g(f):#函數名能夠作參數
    print(f)#結果是函數名所指向的那塊內存地址
    print("so good g")
    return 2+5
print(g(f))



def l():
    return f#函數名可用做返回值

ll=l()
print(ll())

五.閉包

閉包
1.閉 內部的函數
2.包 包含了對外部函數做用域中變量的引用

 

閉包的做用:

就是可以引用外部函數的變量,而且能夠保證外部函數的變量控制在一個局部做用域中

 

#閉包的經常使用形式
def hei():
    x = 20
    def inner():
        print(x)  #局部的
    return inner

# i = hei()
# i()  #全局
__author__ = 'Administrator'
# from urllib.request import urlopen
# def fun():
#     url="http://www.sina.com.cn/"
#     def op():
#         return urlopen(url).read()
#     return op
# l=fun()
# print(l())
from urllib.request import urlopen
def fun(url):
    def op():
        return urlopen(url).read()
    return op
url="http://www.sina.com.cn/"
l=fun(url)
print(l())

 

判斷閉包函數的方法__closure__

#輸出的__closure__有cell元素 :是閉包函數
def func():
    name = 'eva'
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()
f()

#輸出的__closure__爲None :不是閉包函數
name = 'egon'
def func2():
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f2 = func2()
f2()
#閉包嵌套
def wrapper():
    money = 1000
    def func():
        name = 'eva'
        def inner():
            print(name,money)
        return inner
    return func

f = wrapper()
i = f()
i()

  

小節:

命名空間:

  一共有三種命名空間從大範圍到小範圍的順序:內置命名空間、全局命名空間、局部命名空間

做用域(包括函數的做用域鏈):

  調用時,若是在本身的空間內有,就用本身的。若是沒有就使用大範圍的。不能從大範圍中用小範圍的。

函數的嵌套:

  嵌套調用

  嵌套定義:定義在內部的函數沒法直接在全局被調用

函數名的本質:

  就是一個變量,保存了函數所在的內存地址

閉包:

  內部函數包含對外部做用域而非全劇做用域名字的引用,該內部函數稱爲閉包函數

相關文章
相關標籤/搜索