day7-基礎函數的學習(二)

過了元旦,加油鴨,衝鴨!!!閉包

閒話不說,開始今日份學習整理。函數

今日目錄,今天的學習內容不是不少!學習

1.函數名的運用spa

2.閉包(重要)code

3.迭代器(重要)對象

 

 

開始今日份總結blog

1.函數名的運用內存

1.1函數名是一個特殊的變量utf-8

def func():
    print(666)   
print(func)
#結果
<function func at 0x000001C2D44E7F28>
#返回函數的內存地址

1.2函數名能夠當作變量賦值it

def func():
    print(666)

func2 = func
f1 = func2
f2 = f1
f3 = f2
print(f3)
#結果,返回函數的內存空間
<function func at 0x0000020FA58B7F28>

1.3函數名能夠當作容器類數據類型的元素

def func1():
    print('func1')

def func2():
    print('func2')

def func3():
    print('func3')

li =[func1,func2,func3]
for i in li:
    i()
#這樣就能夠一個一個的去調用函數了

1.4函數名能夠當作函數的參數

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

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

func(func1)
#結果
in func1
in func

1.5函數名能夠當作函數的返回值

def func(x):  # x ---> func1
    return x  # func1

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

ret = func(func1)  # func1
ret()
#結果
in func1

2.閉包(重要)

定義:

  • 內層函數對於外層函數(非全局)變量的引用
  • 閉包值存在於內層函數內
  • 函數都要逐層返回,最終返回最外層的函數
  • (我的理解)在函數外部能夠調用函數內部,同時可使用內部的值

閉包的肯定

#不是閉包
name = 'test'
def func1():
    def inner():
        print(name)
    return inner()

f = func1()
print(f.__closure__[0].cell_contents)

#結果
AttributeError: 'NoneType' object has no attribute '__closure__'
#表示函數內沒有閉包的參數

#是閉包
# 閉包
def func():
    age =18
    name ='test'
    def inner():
        print(age)
        print(name)
    return inner
f = func()

# 獲取閉包引用的外層變量
print(f.__closure__[0].cell_contents)
print(f.__closure__[1].cell_contents)
#結果
18
test

閉包的用法

需求,輸入一個數,連續自加這個數五次,有可能會寫成這樣

def func(step):
    sum = 1
    sum += step
    print(sum)
i =0
while i <5:
    func(3)
    i+=1
#結果
4
4
4
4
4

閉包:解釋器執行程序時,若是遇到函數,隨着函數的結束而關閉臨時名稱空間,可是!!!
            若是遇到閉包,有一個機制:那麼閉包的空間不會隨着函數的結束而關閉。

從新寫一下上面這個需求

def func(step):
    sum1 = 1
    def inner():
        nonlocal sum1
        sum1 += step
        print(sum1)
    return inner
i =0
f =func(3)
while i <5:
    f()
    i+=1
#結果
4
7
10
13
16

須要注意的是,若是將f =func(3)放入下面循環內部,就會發現打印的都是4,緣由呢,就是生產了五個閉包,每一個閉包執行了一次。

閉包的經常使用使用環境

  • 裝飾器
  • 爬蟲的一些使用環境(對一個網頁重複抓取,以前抓取的內容已經放在內存中)

3.迭代器(重要)

3.1可迭代對象

經常使用可迭代對象爲:str  list tuple set range() 文件句柄

可迭代對象:內部含有__iter__方法的就是可迭代對象,遵循可迭代協議,可迭代對象不能直接取值

判斷是不是可迭代對象

# 方法一:

s1 = 'barry'
# print('__iter__' in dir(s1))
# print('__iter__' in dir(range(10)))

3.2迭代器

迭代器:內部含有'__iter__'而且含有'__next__'方法的就是迭代器,遵循迭代器協議。

可迭代對象轉化成迭代器

可迭代對象.__iter__() 或者 iter(可迭代對象)

s1 = 'abcd'
obj = iter(s1)
print(obj)
print(obj.__next__())
print(obj.__next__())
print(obj.__next__())
print(obj.__next__())
print(obj.__next__())
#  一個next 對應一個值,一一對應。
#結果
a
b
c
d
    print(obj.__next__())
StopIteration

判斷

一個對象是是迭代器

#方法一:判斷一個對象內有沒有指定的方法
li =[1,2,3,4]
obj = iter(li)
print('__iter__'in dir(obj) and '__next__'in dir(obj))
#結果
True
#方法二:引入其餘模塊,進行判斷
from collections import Iterable
from collections import Iterator
li =[1,2,3,4]
obj = iter(li)
print(isinstance(obj,Iterable))#判斷是不是可迭代對象
print(isinstance(obj,Iterator))#判斷是不是迭代器
#結果
True
True
#這個也能夠用於判斷上面是不是可迭代對象

type() isinstance()區別?
type()只是判斷該對象的數據類型
isinstance()不只能夠判斷該對象的數據類型,並且能夠判斷其餘不少

迭代器的做用:
1,節省內存.
2,惰性機制.
3, 一條路走到黑,不走回頭路.
s2 = [1, 2, 3, 4, 5]
obj2 = iter(s2)
print(next(obj2))
print(next(obj2))

練習

 

# 練習
# 判斷一個對象是不是可迭代對象,迭代器
# str list tuple set dict range() 文件句柄
# f = open('file',encoding='utf-8',mode='w')
# print(isinstance(f,Iterator))

# s2 = [1, 2, 3]
# # 將s2轉化成迭代器 進行取值
# obj2 = iter(s2)
# # print(obj2.__next__())
# print(next(obj2))

#while循環模擬for循環機制
相關文章
相關標籤/搜索