python 第四天

來源:互聯網
上載者:User

標籤:python   裝飾器   迭代器   

第一、

1、函數的嵌套的調用:在調用函數的過程中又調用了其他的函數。代碼簡潔、可讀性較高。

例1:

def foo():

    print(‘from foo‘)


def bar():

    print(‘from bar‘)

    foo()

bar()


#結果:

from bar

from foo


例2:

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)

    res4 = max2(res2,d)

    return res4


print(max4(1,4,2,5))


2、函數的嵌套定義:在一個函數的內部、又定義另外一個函數。


第二、

1、名稱空間:存放名字的地方、準確的說是存放名字和變數值綁定關係的地方。

python中的名稱空間有:

1、內建名稱空間:在py啟動的時候產生、存放一些python內建的名字。

print(),len(),max()……


2、全域名稱空間:在執行檔案時、檔案層級定義的名字。

x=1、

3、局部名稱空間:在執行檔案的過程中、如果調用了函數、則會產生該函數的局部名稱空間、用來存放該函數內定義的名字。在函數調用時生效,函數調用結束後失效。


三個名稱空間的載入順序:

內建-->全域-->局部

從上到下。


三個名稱空間的查詢順序:

局部-->全域-->內建

從下往上。


2、範圍:作用的應用範圍

全域範圍:全域有效、任何位置都能訪問得到。

全域包含:globals

1、內建名稱

2、全域名稱

例:

def f1():

    def f2():

        def f3():

            print(max)


        f3()

    f2()

f1()

<built-in function max>


局部範圍:臨時有效、局部有效。

局部包含:locals

1、局部名稱

全域範圍的局部依然是全域範圍。


dir 查看對象下有哪些方法。


#global 關鍵字

global

x=1

def f1():

    global x

    x=2

f1()

print(x)

2


#不加global 也可以修改可變類型的資料

l = []

def f2():

    l.append(‘f2‘)

f2()

print(l)l = []

def f2():

    l.append(‘f2‘)

f2()

print(l)


[‘f2‘]


x=0

def f1():

    x=3

    def f2():

        x=2

        def  f3():

            global x

            x=3

        f3()

    f2()

f1()


print(x)


3


x=0

def f1():

    x=3

    def f2():

        x=2

        def  f3():

            global x

            x=3

        f3()

        print(x)

    f2()

f1()


2


x=0

def f1():

    x=3

    def f2():

        x=2

        def  f3():

            nonlocal x

            x=3

        f3()

        print(x)

    f2()

f1()

3


#優先掌握:範圍關係在函數定義時就已經定義了,與調用的位置無關。需要回到原來定義函數的位置去找範圍關係


x= 1

def f1():

    def f2():

        print(x)

    return f2


def foo(func):

    x=100

    func()


foo(f1())

1


#此處值為1是因為範圍的定義在上面。

3、閉包函數:閉合、包裹。

定義:

1、定義在函數內部的函數

2、包含對外部範圍名字的引用,而不是全域範圍名字得引用,那麼該內建函式就稱為閉包函數。

def f1():

    x=2

    def f2():

        print(x)

    return f2


res=f1()

res()

2


#此處的f2函數就是閉包函數、此時他不是獨立存在的他的外圍包一層範圍。

def deco():

    x=123123

    def wrapper():

        print(x)

    return wrapper

    wrapper()


func=deco()

func()


123123


#查看外部變數

import requests

def index(url):

    def get():

        print(requests.get(url).text)

    return get


python_web=index(‘http://www.python.org‘)

baidu_web=index(‘http://www.baidu.com‘)


print(python_web.__closure__)


(<cell at 0x0000007E65EA55E8: str object at 0x0000007E66035DF8>,)


import requests

def index(url):

    def get():

        print(requests.get(url).text)

    return get


python_web=index(‘http://www.python.org‘)

baidu_web=index(‘http://www.baidu.com‘)


print(python_web.__closure__[0].cell_contents)


http://www.python.org


當閉包內建函式沒有被範圍包住的時候,他的範圍為None

4、為什麼要用裝飾器?

1、開發封閉原則:對擴充是開放的、對修改是封閉的。

 裝飾器:目的為其他人添加新功能、

 裝飾器可以是任意可調用對象、被裝飾的對象可以是任意可調用對象。


 2、裝飾器需要遵循的原則:

 2.1 不修改裝飾對象的原始碼

 2.2 不修改被調用對象的功能

 其目的就是滿足1和2條件添加新功能


例1:

import time

def index():

    time.sleep(3)

    print(‘welcome to index‘)


def home():

    time.sleep(3)

    print(‘welcome to home‘)


def timmer(func):

    def wrapper():

        start=time.time()

        func()

        stop=time.time()

        print(‘run time is %s‘ %(stop-start))

    return wrapper


index=timmer(index)

home=timmer(home)


index()

home()


簡寫裝飾器:

import time

def timmer(func):

    def wrapper():

        start=time.time()

        func()

        stop=time.time()

        print(‘run time is %s‘ %(stop-start))

    return wrapper


@timmer#裝飾器需要在調用的上面

def index():

    time.sleep(3)

    print(‘welcome to index‘)

@timmer#@等價 home=timmer(home)

def home():

    time.sleep(3)

    print(‘welcome to home‘)


index()

home()


#@裝飾器名、必須寫在被裝飾對象的正上方、而且是單獨一行


例2:、對被修飾對象加參數

import time

def timmer(func):

    def wrepper(*args,**kwargs):

        start=time.time()

        func(*args,**kwargs)

        stop=time.time()

        print(‘run time is %s‘ %(stop-start))

    return wrepper


@timmer

def index():

    time.sleep(2)

    print(‘welcome to index‘)

@timmer

def home(name):

    time.sleep(2)

    print(‘welcome to %s‘ %name)


index()

home(‘home‘)


例3:傳回值

#對被修飾對象加參數

import time

def timmer(func):

    def wrepper(*args,**kwargs):

        start=time.time()

        res=func(*args,**kwargs)

        stop=time.time()

        print(‘run time is %s‘ %(stop-start))

        return res

    return wrepper


@timmer

def index():

    time.sleep(2)

    print(‘welcome to index‘)

    return  123

@timmer

def home(name):

    time.sleep(2)

    print(‘welcome to %s‘ %name)

    return 456


res=index()

print(res)

res1=home(‘home‘)

print(res1)


>>

welcome to index

run time is 2.00014328956604

123

welcome to home

run time is 2.0002007484436035

456


例3:用裝飾器實現使用者登入認證的功能

cust_dic={‘user‘:None}

def auth(func):

    def auth_toke(*args,**kwargs):

        if cust_dic[‘user‘]:

            return func(*args, **kwargs)

        user_inp = input(‘user>> ‘).strip()

        pass_inp = input(‘pass>> ‘).strip()

        with open(‘db‘,‘r‘,encoding=‘utf-8‘) as use_f:

            use_list=eval(use_f.read())

            if user_inp == use_list[0][‘user‘] and pass_inp == use_list[0][‘password‘]:

                cust_dic[‘user‘] = user_inp

                return func(*args,**kwargs)

            else:

                print(‘log in error‘)

    return auth_toke


@auth

def access():

    print(‘login sessfull‘)


@auth

def error(name):

    print(‘welcome to is %s‘ %name)


access()

error(‘json‘)


>>:

user>> json

pass>> 123123

login sessfull

welcome to is json


#閉包函數只需要用到3層就能滿足一切函數的傳參。

#裝飾器補充

import time

def foo():

    ‘‘‘這是index函數‘‘‘

    time.time()

    print(‘access‘)

    return 123

# print(help(foo))


print(foo.__doc__)


    這是index函數

#多個裝飾器

誰在上面誰先生效。

5、迭代器:

迭代:重複的過程、每一次重複都是基於上一次的結果而來。

取出序列類型的元素就是迭代

例1:

l = [‘a‘,‘b‘,‘c‘,‘d‘]

count=0

while  count < len(l):

    print(l[count])

    count+=1


>>

a

b

c

d


5.1、迭代器:取出非序列資料、不按索引。

5.2、可迭代對象:凡是對象有__iter__方法:對象.__iter__,該對象就是可迭代對象。

可迭代對象有:字串、列表、元組、字典。

例2:

dic={‘name‘:‘egon‘}

res=dic.__iter__()

print(res)  #iterator 迭代器

例3:

dic={‘name‘:‘egon‘,‘age‘:11}

res=dic.__iter__()

print(next(res))

print(next(res)

>>

name

age

#StopIteration 提示迭代器沒有值了,應該停止了

迭代器本身也是可迭代的對象。

dic={‘name‘:‘egon‘,‘age‘:11}

# res=dic.__iter__()

res=iter(dic)

print(next(res))

print(next(res))

>>

name

age

#當迭代器遇到stopiteration的時候會停止運行。

s=‘hello‘

l=[‘a‘,‘b‘,‘c‘,‘d‘]

iter_l=iter(l)

while True:

    try:

        print(next(iter_l))

    except StopIteration:

        break

>>

a

b

c

d

6、迭代器對象:

6.1、有__iter__,執行結果仍然是迭代器本身

6.2、有__next__,執行一次取一個值

迭代器對象的優點:

1、提供統一的(不依賴於索引的)迭代方式

2、迭代器本身、比其他資料類型更省記憶體

3、迭代器可以存放無窮無盡個值。


例1、

with open(‘db‘,encoding=‘utf-8‘) as f:

    print(next(f))

    print(next(f))

    print(next(f))

    print(next(f))


>>

111111111111111111111

11111111111111

11111111111

1111111

迭代器缺點:

1、一次性的、只能往後不能回退、不如索引取值更靈活。

占記憶體大的環境不能用索引方式。

2、無法預知什麼時候結束、即無法預知長度。

for迴圈就是一個迭代器。

for迴圈的對象就是可迭代對象。


判斷一個對象是否是可迭代對象的方法就是?看該對象是否有iter方法。

檔案是迭代器。****

7、產生器

產生器:在函數內部包含yield關鍵字、那麼該函數的執行結果是產生器

產生器就是迭代器。

#yield的功能:

1、把函數的結果做產生器(以一種優雅的方式封裝__iter__,__next__)

2、函數暫停與繼續啟動並執行狀態是由yield 

例1、手動實現rang函數。

def my_rang(start,stop):

    while True:

        if start == stop:

            raise StopIteration

        yield start

        start+=1

for i in my_rang(1,3):

    print(i)

7.1、yield 與 return的比較?

相同:都有傳回值的功能

不同:return只能返回一次、


例2、taif -f |grep 實現

import time

def tail(filepath):

    with open(filepath,‘r‘) as f:

        f.seek(0,2)

        while True:

            line = f.readline()

            if line:

                yield line

            else:

                time.sleep(0.2)


def grep(patten,lines):

    for line in lines:

        if patten in line:

            print(line,end=‘‘)

grep(‘error‘,tail(‘db‘))

8、三元運算式:

為真時的結果 if 判定條件 else 為假時的結果  

1 if 5>3 else 0

輸出為1、如果5大於3、否則輸出0

9、列表解析

根據已有列表,高效建立新列表的方式。

列表解析是Python迭代機制的一種應用,它常用於實現建立新的列表,因此用在[]中。


例1:傳統方式

l=[]

for n in range(11):

    l.append(n)

print(l)

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


例2:列表解析

l=[ n for n in range(10)]

print(l)

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


例3:取出10內大於4的數字

傳統方法:

l=[]

for n in range(10):

    if n >= 4:

        l.append(n)

print(l)

[4, 5, 6, 7, 8, 9]


列表解析:

l=[ n for n in range(10) if n >=4 ]

print(l)

[4, 5, 6, 7, 8, 9]

10、產生器運算式:

產生器運算式並不真正的建立數字列表,而是返回一個產生器對象,此對象在每次計算出一個條目後,把這個條目"產生"(yield)出來。產生器運算式使用了"惰性計算"或稱作"延時求值"的機制。

序列過長,並且每次只需要擷取一個元素時,應該考慮產生器運算式而不是列表解析。


N=(i**2 for i in range(11))

print(N)

<generator object <genexpr> at 0x000000A5BE8A1D00>#此處返回的是一個產生器的地址


產生器取值通過next方法:


N=(i**2 for i in range(11))

# print(N)

print(next(N))

print(next(N))

print(next(N))

print(next(N))


0

1

4

9


產生器取值到元素遍曆完畢之後,拋出StopIteration

N=(i**2 for i in range(11))

# print(N)

while True:

    try:

        print(next(N))

    except StopIteration:

        break


本文出自 “男兒該自強” 部落格,請務必保留此出處http://nrgzq.blog.51cto.com/11885040/1951622

python 第四天

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.