python之函數閉包、可迭代對象和迭代器

1、函數名的應用html

 

複製代碼
# 1,函數名就是函數的內存地址,而函數名()則是運行這個函數。
def func():
    return

print(func)  # 返回一個地址

# 2,函數名能夠做爲變量。
def func1():
    print(666)

f1 = func1
f2 = f1
f2()  # 就等於func1() 此時執行函數

# 3,函數名能夠做爲函數的參數。
def func1():
    print(666)

def func2(x):
    x()

func2(func1)  # 輸出666 func1做爲實參傳進func2中,此時在func2中x()等於func1()

# 4,函數名能夠當作函數的返回值。
def wraaper():
    def inner():
        print(666)
    return inner

ret = wraaper()  # 執行函數wraaper(),獲得返回值inner賦值給ret,這個inner是函數名
ret()  # 輸出666,ret()等於inner()
# (注意:這裏要調用inner()只能是用ret(),由於inner()是wraaper()的嵌套函數,在全局命名空間中並無聲明,因此直接用inner()不能執行,)

def func2():
    print('in func2')

def func3(x):
    print('in func3')
    return x

f = func3(func2)  # 給func3傳進一個參數func2,返回func2賦值給f
f()  # f()等於func2()

# 5,函數名能夠做爲容器類類型的元素。
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]()  # 輸出 f1
d['f2']()  # 輸出 f2


def func1():
    print('in func1')

def func2():
    print('in func2')

def func3():
    print('in func3')

def func4():
    print('in func4')

l1 = [func1,func2,func3,func4]

#調用
for i in l1:
    i()

# 像上面的函數名這種,稱爲第一類對象。
# 第一類對象(first-class object)指:
# 1.可在運行期建立
# 2.可用做函數參數或返回值
# 3.可存入變量的實體。
# (若是不明白,那就記住一句話,就當普通變量用)
複製代碼

 

 

 

六、globals()        locals()
globals()    #返回全局變量(包含內置函數)的一個字典。
locals()      #返回當前位置的變量的字典。
例如:閉包

複製代碼
def func1():
    a = 2
    b = 3
    print(globals())  # 此時globals()在局部命名空間中,但也是返回全局命名空間的一個字典
    print(locals())  # 此時locals()在局部命名空間中,因此返回的是局部命名空間的一個字典{'b': 3, 'a': 2}

print(globals())  # 此時globals()在全局命名空間中,返回全局命名空間的一個字典
print(locals())  # 此時locals()在全局命名空間中,因此返回的是全局命名空間的一個字典
func1()

# 結果:

# {'__name__': '__main__', '__doc__': None(後面還有一大推東西,省略)...}

# {'__name__': '__main__', '__doc__': None(後面還有一大推東西,省略)...}

# {'__name__': '__main__', '__doc__': None(後面還有一大推東西,省略)...}

# {'b': 3, 'a': 2}
複製代碼

總結:
globals()不管在哪一個命名空間,返回的都是全局命名空間的一個字典
locals()在哪一個命名空間就返回哪一個命名空間的字典函數

複製代碼
def func1():
    a = 2
    b = 3
    def inner():
        c = 5
        d = 6
        print(globals())    #{'__name__': '__main__', '__doc__': None(後面還有一大推東西,省略)...}
        print(locals())      #{'c': 5, 'd': 6}
    inner()
func1()
複製代碼

 

 

 

 


2、閉包
一、內層函數引用外層函數的變量(非全局變量),這樣該內部函數稱就稱爲閉包函數。
(咱們都知道函數內的變量咱們要想在函數外部用,能夠直接返回這個變量,那麼若是咱們想在函數外部調用函數內部的函數呢?
就把這個函數的名字返回就行了,這是閉包函數最經常使用的用法)post

複製代碼
def wraaper():
    name = '鬼見愁'
    def inner():
        print(name)
    return inner

f = wraaper()
f()
複製代碼

 

二、判斷閉包函數的方法__closure__ this

複製代碼
# 1,是閉包返回值會有cell元素
def wraaper():
    name = '鬼見愁'
    def inner():
        print(name)
    print(inner.__closure__)
    return inner
f = wraaper()
f()


# 2,不是閉包就會返回None
name = '鬼見愁'
def wraaper():
    def inner():
        print(name)
    print(inner.__closure__)  # None
    return inner
f = wraaper()
f()


name = '番薯'
def wraaper(n):
    n = '番薯'
    def inner():
        print(n)
    print(inner.__closure__)  # cell at 0x000002AD93BF76D8
    inner()
    return inner
wraaper(name)
複製代碼

 

'''
閉包做用:
  當程序執行時,遇到了函數執行,他會在內存中開闢一個空間,局部名稱空間,
  若是這個函數內部造成了閉包,
  那麼它就不會隨着函數的結束而消失。
'''url


何時用到閉包?
例如:爬蟲,裝飾器等
下面是一個爬蟲的小案例:spa

複製代碼
from urllib.request import urlopen
def index():
    url = "http://www.xiaohua100.cn/index.html"
    def get():
        return urlopen(url).read()
    return get

xiaohua = index()  # get
content = xiaohua()  # get()
print(content.decode('utf-8'))
複製代碼

 

 


3、可迭代對象
for i in 'abc':
  print(i)code

for i in 123:
  print(i)     # 'int' object is not iterable表示不是可迭代對象htm

對象內部含有__iter__方法就是可迭代對象.
可迭代對象知足可迭代協議。對象

可迭代對象:str list dict,tuple,set,range()
dir() :返回一個列表,列表裏面包含了傳入的參數的屬性、方法

s1 = 'strs'

 

print(dir(s1))

 

判斷一個對象是不是可迭代對象:

複製代碼
# 第一個方法
s1 = 'abc'
dic = {'name':'xiaoming'}
print('__iter__' in dir(s1))
print('__iter__' in dir(dic))


# 第二種方法
from collections import Iterable  #判斷是否爲可迭代對象
from collections import Iterator  #判斷是否爲迭代器

print(isinstance('xiaoming',Iterable))  # True
print(isinstance('xiaoming',Iterator))  # False

print(isinstance('xiaoming',str)) # True
#isinstance() 應用比type()更普遍,isinstance()不只能夠判斷你是否是可迭代對象,
#也可判斷你是否迭代器,還能夠判斷你是什麼類型的數據等等,而#type()只能判斷你是什麼數據類型
複製代碼

 

 

 

 

 

4、迭代器
一、對象內部含有__iter__方法且含有__next__方法就是迭代器。

複製代碼
#文件句柄是迭代器:
f = open('register', encoding='utf-8')
print('__iter__' in dir(f))      #True
print('__next__' in dir(f))      #True

#字典是可迭代對象,不是迭代器。
print('__iter__' in dir(dict))   #True
print('__next__' in dir(dict))   #False
複製代碼


二、可迭代對象與迭代器的區別:
1,可迭代對象不能取值,迭代器是能夠取值的。
(咱們知道字典列表都是可迭代對象,爲何它們能取值呢?這是由於爲了方便咱們操做,咱們設定了
索引(鍵)用來操做字典列表取值,若是沒有人爲爲它們設置的索引(鍵),它們是不能取值的)
2, 迭代器很是節省內存。
3,迭代器每次只會取一個值。
4,迭代器單向的,一條路走到頭。


三、可迭代對象 --->(轉化成)迭代器

lis = [1, 2, 3]  # 可迭代對象
ite1 = lis.__iter__()  # 迭代器  <list_iterator object at 0x0000027A183BFFD0>
ite1 = iter(lis)  # 迭代器  <list_iterator object at 0x0000027A183BFFD0>
print(ite1)

 

四、迭代器如何取值? next一次,取一個值

print(ite1.__next__())
print(ite1.__next__())
print(ite1.__next__())

 

五、while循環模擬for循環機制
1,將可迭代對象轉化成迭代器。
2,調用__next__方法取值。
3,利用異常處理中止報錯。

 

複製代碼
s1 = 'abcdefg'
iter1 = s1.__iter__()
while 1:
    try:
        print(iter1.__next__())
    except StopIteration:
        break
複製代碼
相關文章
相關標籤/搜索