Python學習筆記四

一.裝飾器html

    1.知識儲備python

       函數對象數據結構

    函數能夠被引用閉包

              函數能夠當參數傳遞dom

              返回值能夠是函數函數

              能夠看成容器的元素url

def func1():
    print (666)
def func2():
    print (666)
def func3():
    print (666)
list1=[func1,func2,func3]
for i in list1:
    i()

       *args:接收溢出的位置參數spa

  **kwargs:接收溢出的關鍵字參數code

       名稱空間與做用域htm

     2.閉包函數

        閉包函數的定義:定義在函數內部的函數,特色是:包含對外部做用域而不是全局做用域名字的引用。這個函數就稱爲閉包函數。

  閉包函數的兩個特徵:內部函數要引用外部函數的變量,外部函數的返回值是內部函數。

  例子:

  

  當函數內部須要一個變量的時候,有兩種方式給函數傳入變量,

  第一種:爲函數添加一個參數。

  第二種:把這個函數變成閉包函數,也就是在函數外部添加一個函數。把變量寫在外部函數內,或者看成參數傳給外部函數。將內部函數的函數名return一下,這樣內部函數就被外部函數包起來了。

   閉包特性:python遇到閉包,不會釋放名稱空間。

     3.裝飾器

         爲何要用裝飾器?

         開放封閉原則:對擴展是開放的,對修改是關閉的

                   1. 不修改被裝飾對象的源代碼           2. 不修改被裝飾對象的調用方式。

         裝飾器的目標:在遵循1和2的前提下,爲被裝飾器對象添加上新功能

         什麼是裝飾器?

    裝飾他人的器具,自己能夠任意可調用對象,被裝飾者也能夠是任意可調用對象。

         

   帶參數的裝飾器,怎麼寫?

 

       4.練習題:

          一,編寫函數,(函數的執行時間是隨機的)

import time
def a():
    x = time.strftime('%Y-%m-%d %X')
    print(x)
a()

結果:

D:\Python36\python.exe F:/python/第一課/while-lianxi.py
2017-10-14 08:40:11

          二,編寫裝飾器,爲函數加上統計時間的功能。

 
 
#這種是採用傳參的方式,雖然沒有修改index和home函數的源代碼,可是修改了它們的調用方式。因此須要採用裝飾器。
import time
def timmer(tongji_hanshu):
# tongji_hanshu=home
def inner():
start_time=time.time()
tongji_hanshu()
stop_time=time.time()
print("函數執行時間: %s" %(stop_time-start_time))
return inner
@timmer #語法糖
def index():
time.sleep(3)
print("welcome to index page!")
index()
@timmer
def home():
time.sleep(5)
print("welcome to home page!")
home()

結果:

D:\Python36\python.exe F:/python/第一課/while-lianxi.py
welcome to index page!
函數執行時間: 3.0001718997955322
welcome to home page!
函數執行時間: 5.000285863876343

       三. 編寫裝飾器,爲函數加上認證的功能。

import time
def outter(func):
    def auth():
        username=input("輸入用戶名: ").strip()
        password=input("輸入密碼: ").strip()
        if username=='yangjianbo' and password=='123':
            print ("登陸成功!")
            func()  #這麼寫死了
        else:
            print("登陸失敗!")
    return auth
@outter
def index():
    time.sleep(3)
    print("welcome to index page!")
index()

結果:

D:\Python36\python.exe F:/python/第一課/while-lianxi.py
輸入用戶名: yangjianbo
輸入密碼: 123
登陸成功!
welcome to index page!

 

四:編寫裝飾器,爲多個函數加上認證功能(用戶的帳號密碼來源於文件),要求登陸成功一次,後續的函數都無需再輸入用戶名和密碼。

#這種狀況是針對index,沒有參數的函數,若是被裝飾的函數有參數,如何修訂裝飾器。
import time
def outter(func):
    def auth(*args,**kwargs):
        username=input("輸入用戶名: ").strip()
        password=input("輸入密碼: ").strip()
        if username=='yangjianbo' and password=='123':
            print ("登陸成功!")
            func(*args,**kwargs)  #這麼寫死了
        else:
            print("登陸失敗!")
    return auth
@outter
def index():
    time.sleep(3)
    print("welcome to index page!")
index()
@outter  #home=outter(home)
def home(username):
    time.sleep(2)
    print("welcome %s to home page!" %username)
home('yangjianbo')

結果:

D:\Python36\python.exe F:/python/第一課/while-lianxi.py
輸入用戶名: yangjianbo
輸入密碼: 123
登陸成功!
welcome to index page!
輸入用戶名: yangjianbo
輸入密碼: 123
登陸成功!
welcome yangjianbo to home page!

 根據題目要求:只要登陸成功,之後就不須要再登陸。因此上面的代碼還須要修改。

import os
import time
login_status=False
def outter(func):
    def auth(*args,**kwargs):
        if  login_status is True:
            return func(*args,**kwargs)
        else:
            username=input("輸入用戶名: ").strip()
            password=input("輸入密碼: ").strip()
            with open('account.txt','r',encoding='utf-8') as accout:
                    accout=accout.read().strip('\r\n').split('|')
                    if username==accout[0] and password==accout[1]:
                        print ("登陸成功!")
                        login_status=True
                        func(*args,**kwargs)
                    else:
                        print("登陸失敗!")
    return auth
@outter  #index=outter(index)
def index():
    time.sleep(3)
    print("welcome to index page!")
index()

@outter
def home(username):
    time.sleep(2)
    print("welcome %s to home page!" %username)
home('yangjianbo')

結果:

D:\Python36\python.exe F:/python/第一課/while-lianxi.py
Traceback (most recent call last):
File "F:/python/第一課/while-lianxi.py", line 158, in <module>
index()
File "F:/python/第一課/while-lianxi.py", line 140, in auth
if login_status is True:
UnboundLocalError: local variable 'login_status' referenced before assignment

上面報錯的分析:說局部變量login_status在引用以前沒有指定.

我明明定義在全局做用域了,爲何報錯?

解決方法:在函數內,添加一個關鍵字global,表示引用全局變量。

修改後的代碼:

import os
import time
login_status=False
def outter(func):
    def auth(*args,**kwargs):
        global login_status
        if  login_status is True:
            return func(*args,**kwargs)
        else:
            username=input("輸入用戶名: ").strip()
            password=input("輸入密碼: ").strip()
            with open('account.txt','r',encoding='utf-8') as accout:
                    accout=accout.read().strip('\r\n').split('|')
                    if username==accout[0] and password==accout[1]:
                        print ("登陸成功!")
                        login_status=True
                        func(*args,**kwargs)
                    else:
                        print("登陸失敗!")
    return auth
@outter  #index=outter(index)
def index():
    time.sleep(3)
    print("welcome to index page!")
index()

@outter
def home(username):
    time.sleep(2)
    print("welcome %s to home page!" %username)
home('yangjianbo')

結果:沒有報錯了。

 第四個裝飾器最後版本:

import time
user_status={"user":None,"login_status":False}
def outter(func):
    def auth(*args,**kwargs):
        if user_status['user'] and user_status['login_status']:
            res=func(*args, **kwargs)
            return res
        username=input("輸入用戶名: ").strip()
        password=input("輸入密碼: ").strip()
        if username=='yangjianbo' and password=='123':
            print ("登陸成功!")
            user_status['user']=username
            user_status['login_status']=True
            res=func(*args, **kwargs)
            return res
        else:
            print("登陸失敗!")
    return auth
@outter
def index():
    time.sleep(3)
    print("welcome to index page!")
    # return 123
index()
@outter
def home(username):
    time.sleep(2)
    print("welcome to %s home page" % username)
    # return 456

home('yangjianbo')

 練習五  編寫裝飾器,爲多個函數加上認證功能,要求登陸成功一次,在超時時間內無需重複登陸,超過了超時時間,則必須從新登陸

import time
import random
user={"user":None,"login_time":None,'timeout':0.03}

def timmer(func):
    def inner(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('%s' %(stop_time-start_time))
        return res
    return inner
def outter(func):
    def auth(*args,**kwargs):
        if user['user']:
            timeout=time.time()-user['login_time']
            if timeout<user['timeout']:
                res=func(*args, **kwargs)
                return res
        username=input("輸入用戶名: ").strip()
        password=input("輸入密碼: ").strip()
        if username=='yangjianbo' and password=='123':
            user['user']=username
            user['login_time']=time.time()
            res=func(*args, **kwargs)
            return res
        else:
            print("登陸失敗!")
    return auth
@outter
def index():
    time.sleep(random.randrange(3))
    print("welcome to index page!")

index()


@outter
def home(username):
    time.sleep(random.randrange(3))
    print("welcome to %s home page" % username)


home('yangjianbo')

  練習六:編寫下載網頁內容的函數,要求功能是:用戶傳入一個url,函數返回下載頁面的結果

from urllib.request import urlopen

def outer(url):
    def get():
        f=urlopen(url).read()
        return f
    return get
baidu=outer('http://www.baidu.com')
sohu=outer('http://www.sohu.com')
baidu=baidu()
sohu=sohu()

  練習七:拿到下載的頁面,保存到一個文件中。

from urllib.request import urlopen

def outer(url):
    def get():
        f=urlopen(url).read()
        return f
    return get
baidu=outer('http://www.baidu.com')
sohu=outer('http://www.sohu.com')
baidu=baidu()
sohu=sohu()
with open('baidu.html','w',encoding='utf-8') as f:
    f.write(baidu.decode('utf-8'))

  

六. 迭代器

      可迭代對象

    內部含有'__iter__'方法的數據就是可迭代對象

    s1='abcdef'

    print (dir(s1))

    print('__iter__' in dir(s1))

      迭代器對象

    內部含有'__iter__'方法而且含有'__next__'方法就是迭代器

  如何將可迭代對象轉換爲迭代器對象

    list1=[1,2,3,4]

    iter1=iter(list1)  #可迭代對象轉換爲迭代器

    print(iter1)

    print(iter1.__next__())

  迭代器的特色

    1.  很是節省內存

    2.  他知足惰性機制

    3.  一條走到黑

  利用while循環模擬for循環

    list1=[1,2,3,4]

    iter1=iter(list1)

    while 1:

      try:

        print(iter1.__next__())

      except StopIteration:

        break

七. 生成器

  本身用python代碼寫的迭代器

  生成器的定義:

    1.  函數式寫法,構建生成器

    2.  只要函數中出現yield,那麼他就不是函數了,它是生成數函數。

八.列表推導式

  凡是用列表推導式構建的數據,python代碼均可以構建,列表推導式均可以構建。

  循環模式

  list1=[i for i in range(1,200)]

       print (list1)

  篩選模式

九.生成器表達式

十.列表推導式與生成器表達式

  優勢:構造簡單,一行完成。

  缺點:不能排錯

     不能構建複雜的數據結構

相關文章
相關標籤/搜索