1. 程式人生 > >第三章 Python基礎——文件操作&函數 續

第三章 Python基礎——文件操作&函數 續

全局變量 python基礎 set iterable auth 們的 而且 應該 提前

3.6函數進階

名稱空間:name space

例:若變量X=1,1存放於內存中,那存放X與1綁定關系的地方就叫做名稱空間。

名稱空間共三種,分別如下:

  • locals:是函數內名稱空間,包括局部變量和形參
  • globals:全局變量,函數定義所在模塊的名字空間
  • builtins:內置模塊的名字空間

不同變量的作用域不同就是由於這個變量所在的命名空間決定的。

作用域即範圍:

  • 全局範圍:全局存活,全局有效
  • 局部範圍:臨時存活,局部有效

註:查看作用域方法 globals(),locals()

作用域查找順序:

level=L0
n=22

def func():
      leval
=L1 n=33 print(locals()) def outer(): n=44 level=L2 print(locals(),n) def inner():#此處打印n是多少? level=L3 print(locals(),n) inner() outer() func()

問題:在inner()裏的打印n的值是多少?

LEGB代表名字查找順序:locals->enclosing function->globals->__builtins__

  • locals是函數內的名字空間,包括局部變量和形參
  • enclosing外部嵌套函數的名字區間
  • globals全局變量,函數定義所在模塊的名字空間
  • builtins內置模塊的名字空間

閉包

關於閉包,即函數定義和函數表達式位於另一個函數的函數體內(嵌套函數)。

詳解:而且,這些內部函數可以訪問他們所在外部函數中聲明的所有局部變量、參數。當其中一個這樣的內部函數在包含他們的外部函數被調用時,就會形成閉包。也就是說,內部函數會在外部函數返回後被執行。而當這個內部函數執行時,它仍然必須訪問其外部函數的局部變量、參數以及其他內部函數。這些局部變量、參數和函數聲明(最初時)的值是外部函數返回時的值,但也會會受到內部函數的影響。

def outer():
      name=alex

      def inner():
           print("在inner裏打印外層函數的變量“,name)

        return inner

f=outer()
f()

閉包的意義:返回的函數對象,不僅僅是一個函數對象,在函數外還包裹了一層作用域,這使得該函數無論在何處調用,優先使得自己外層包裹的作用域

裝飾器

例1:

#_*_coding:utf-8_*_

user_status = False #用戶登錄了就把這個改成True

def login():
    _username = "alex" #假裝這是DB裏存的用戶信息
    _password = "abc!23" #假裝這是DB裏存的用戶信息
    global user_status
    if user_status == False:
        username = input("user:")
        password = input("pasword:")
        if username == _username and password == _password:
            print("welcome login....")
            user_status = True
        else:
            print("wrong username or password!")
    else:
        print("用戶已登錄,驗證通過...")

def home():
    print("---首頁----")

def america():
    login() #執行前加上驗證
    print("----歐美專區----")

def japan():
    print("----日韓專區----")

def henan():
    login() #執行前加上驗證
    print("----河南專區----")

home()
america()
henan()

註:在軟件開發中有一個原則“開放-封閉”原則,簡單來說,它規定已經實現的代碼不允許被修改,但可以被擴展,即:

封閉:已實現的功能代碼不應該被修改

開放:對現有功能的擴展開放

def login(func): #把要執行的模塊從這裏傳進來

    def inner():#再定義一層函數
        _username = "alex" #假裝這是DB裏存的用戶信息
        _password = "abc!23" #假裝這是DB裏存的用戶信息
        global user_status

        if user_status == False:
            username = input("user:")
            password = input("pasword:")

            if username == _username and password == _password:
                print("welcome login....")
                user_status = True
            else:
                print("wrong username or password!")

        if user_status == True:
            func() # 看這裏看這裏,只要驗證通過了,就調用相應功能

    return inner #用戶調用login時,只會返回inner的內存地址,下次再調用時加上()才會執行inner函數

簡化上邊的代碼——去掉下邊這行

america=login(america)#你在這裏相當於把america這個函數替換了

最終簡化為:

#_*_coding:utf-8_*_

user_status = False #用戶登錄了就把這個改成True

def login(func): #把要執行的模塊從這裏傳進來

    def inner(*args,**kwargs):#再定義一層函數
        _username = "alex" #假裝這是DB裏存的用戶信息
        _password = "abc!23" #假裝這是DB裏存的用戶信息
        global user_status

        if user_status == False:
            username = input("user:")
            password = input("pasword:")

            if username == _username and password == _password:
                print("welcome login....")
                user_status = True
            else:
                print("wrong username or password!")

        if user_status == True:
            func(*args,**kwargs) # 看這裏看這裏,只要驗證通過了,就調用相應功能

    return inner #用戶調用login時,只會返回inner的內存地址,下次再調用時加上()才會執行inner函數


def home():
    print("---首頁----")

@login
def america():
    #login() #執行前加上驗證
    print("----歐美專區----")

def japan():
    print("----日韓專區----")

# @login
def henan(style):
    ‘‘‘
    :param style: 喜歡看什麽類型的,就傳進來
    :return:
    ‘‘‘
    #login() #執行前加上驗證
    print("----河南專區----")

home()
# america = login(america) #你在這裏相當於把america這個函數替換了
henan = login(henan)

# #那用戶調用時依然寫
america()

henan("3p")

帶參數裝飾器:

#_*_coding:utf-8_*_
user_status = False #用戶登錄了就把這個改成True

def login(auth_type): #把要執行的模塊從這裏傳進來
    def auth(func):
        def inner(*args,**kwargs):#再定義一層函數
            if auth_type == "qq":
                _username = "alex" #假裝這是DB裏存的用戶信息
                _password = "abc!23" #假裝這是DB裏存的用戶信息
                global user_status

                if user_status == False:
                    username = input("user:")
                    password = input("pasword:")

                    if username == _username and password == _password:
                        print("welcome login....")
                        user_status = True
                    else:
                        print("wrong username or password!")

                if user_status == True:
                    return func(*args,**kwargs) # 看這裏看這裏,只要驗證通過了,就調用相應功能
            else:
                print("only support qq ")
        return inner #用戶調用login時,只會返回inner的內存地址,下次再調用時加上()才會執行inner函數

    return auth

def home():
    print("---首頁----")

@login(qq)
def america():
    #login() #執行前加上驗證
    print("----歐美專區----")

def japan():
    print("----日韓專區----")

@login(weibo)
def henan(style):
    ‘‘‘
    :param style: 喜歡看什麽類型的,就傳進來
    :return:
    ‘‘‘
    #login() #執行前加上驗證
    print("----河南專區----")

home()
# america = login(america) #你在這裏相當於把america這個函數替換了
#henan = login(henan)

# #那用戶調用時依然寫
america()

# henan("3p")

3.6生成器,叠代器

列表生成式:

例:把列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表裏的每個值都加1

>>> a = [i+1 for i in range(10)]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10列表生成式]

這種寫法就叫做生成式

生成式

在python中一邊循環一邊計算的機制稱為生成器:generator

要創建一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]改成(),就創建了一個generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

Lg的區別僅在於最外層的[]()L是一個list,而g是一個generator。

我們可以直接打印出list的每一個元素,想要打印書generator的每一個元素有哦兩種方法:

第一種用next()

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

第二種for循環,generator也是可叠送的對象

>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)
...
0
1
4
9
16
25
36
49
64
81

叠送器

可以直接作用於for循環的數據類型有以下幾種:

一類是集合數據類型,如listtupledictsetstr等;

一類是generator,包括生成器和帶yield的generator function。

這些可以直接作用於for循環的對象統稱為可叠代對象:Iterable

可以使用isinstance()判斷一個對象是否是Iterable對象:

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance(abc, Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

而生成器不但可以作用於for循環,還可以被next()函數不斷調用並返回下一個值,直到最後拋出StopIteration錯誤表示無法繼續返回下一個值了。

*可以被next()函數調用並不斷返回下一個值的對象稱為叠代器:Iterator。

可以使用isinstance()判斷一個對象是否是Iterator對象:

>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance(abc, Iterator)
False

生成器都是Iterator對象,但listdictstr雖然是Iterable,卻不是Iterator

listdictstrIterable變成Iterator可以使用iter()函數:

>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter(abc), Iterator)
True

Python的Iterator對象表示的是一個數據流,Iterator對象可以被next()函數調用並不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤。可以把這個數據流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數實現按需計算下一個數據,所以Iterator的計算是惰性的,只有在需要返回下一個數據時它才會計算。

Iterator甚至可以表示一個無限大的數據流,例如全體自然數。而使用list是永遠不可能存儲全體自然數的。

第三章 Python基礎——文件操作&函數 續