爬蟲 (二十四) 或許這樣認識 python 函數會更有趣 (十五)

做爲一個Python的初學者來講,深刻理解Python中函數的概念是一件重要的事情。python

重點1:如何理解函數是第一類對象(一等公民)
函數是第一類對象的概念:sql

第一:函數的名字是對函數的引用數據庫

第二:函數做爲第一類對象能夠賦值給其餘的變量async

第三:能夠做爲函數的參數傳遞給其餘的函數函數

第四:能夠做爲函數的返回值優化

第五:函數能夠做爲容器類型的一個元素ui

簡單來講,在python當中,函數能夠當作數據來進行傳遞,即變量有什麼特性,函數就有什麼特性。函數名字實際上就是一個指針變量,裏面存放着函數體內存空間的地址url

def foo():
    """
    關鍵:foo就是C語言當中的指針變量,裏面存放着內存空間的地址
    """
    print('我愛吃大刀肉')
    print('我愛吃涮羊肉')
    print('我愛吃土豆肉')

fun = foo
print(fun,foo)
#此時此刻fun和foo這兩個指針變量指向同一塊的內存空間
fun()
def foo():
    """
    關鍵:foo就是C語言當中的指針變量,裏面存放着內存空間的地址
    """
    print('我愛吃大刀肉')
    print('我愛吃涮羊肉')
    print('我愛吃土豆肉')

def g(func):
    #咱們將func做爲一個函數的參數進行傳遞
    print(func)
    func()

g(foo) 
def foo():
    """
    關鍵:foo就是C語言當中的指針變量,裏面存放着內存空間的地址
    """
    print('我愛吃大刀肉')
    print('我愛吃涮羊肉')
    print('我愛吃土豆肉')

def g(func):
    #咱們將func做爲函數的返回值進行使用
    print(func)
    return func

f = g(foo)
print(f)
f()

接下來咱們將對最後一個進行深刻講解:spa

示例1:普通版程序指針

def select(sql):
    print('=========>select')

def insert(sql):
    print('=========>insert')

def update(sql):
    print('=========>update')

def delete(sql):
    print('=========>delete')


if __name__ == '__main__':
    while True:
        sql = input('>>').strip()
        if not sql:continue
        l = sql.split()
        cmd = l[0]
        if cmd == 'select':
            select(sql)
        elif cmd == 'insert':
            insert(sql)
        elif cmd == 'update':
            update(sql)
        elif cmd == 'delete':
            delete(sql)
        else:
            pass

上面的這個程序看似沒有什麼問題,可是若是有20個類型的話,難道你要寫20個if....else...嗎?

修改版:

def select(sql):
    print('=========>select')

def insert(sql):
    print('=========>insert')

def update(sql):
    print('=========>update')

def delete(sql):
    print('=========>delete')


if __name__ == '__main__':
    #做爲第一類對象,函數能夠做爲容器類型的元素
    dict_func = {
        'select':select,
        'insert':insert,
        'update':update,
        'delete':delete,
    }

    while True:
        sql = input('>>').strip()
        if not sql:continue
        l = sql.split()
        cmd = l[0]
        if cmd in dict_func:
            dict_func[cmd](sql)

通過上面一折騰,是否是代碼上升了一個檔次。

實際業務版:普通版程序

def handle_async(tag_id,tag_type):
    """
    :param tag_id: DDL id 
    :param tag_type: 具體類型 
    content:if...else...後續這裏要繼續優化
    """
    if '數據庫自助化上線' in tag_type:
        handle_service(tag_id,tag_type)
    elif '普通上線申請流程' in tag_type:
        handle_common(tag_id, tag_type)
    elif '空庫初始化' in tag_type:
        handle_empty(tag_id, tag_type)
    elif 'DBChange確認流程' in tag_type:
        handle_dbchange(tag_id, tag_type)
    elif 'DDL變動申請流程' in tag_type:
        handle_ddl(tag_id, tag_type)
    else:
        pass

改進版:

def handle_async(tag_id,tag_type):
    dict_func = {
       '數據庫自助化上線':handle_service,
       '普通上線申請流程':handle_common,
       '空庫初始化':handle_empty,
       'DBChange確認流程':handle_dbchange,
       'DDL變動申請流程':handle_ddl,
    }
    
    for key in dict_func:
        if key in tag_type:
            dict_func[key](tag_id,tag_type)

後來由於代碼我又改了一次:普通版以下

def handle_async(tag_id,tag_type):
    """
    :param tag_id: DDL id 
    :param tag_type: 具體類型 
    content:if...else...後續這裏要繼續優化
    """
    if '數據庫自助化上線' in tag_type:
        url = url_list['service'] + tag_id
        handle_service(tag_id,tag_type,url=url)
    elif '普通上線申請流程' in tag_type:
        url = url_list['common'] + tag_id
        handle_common(tag_id, tag_type,url=url)
    elif '空庫初始化' in tag_type:
        url = url_list['empty'] + tag_id
        handle_empty(tag_id, tag_type,url=url)
    elif 'DBChange確認流程' in tag_type:
        handle_dbchange(tag_id, tag_type)
    elif 'DDL變動申請流程' in tag_type:
        url = url_list['ddl'] + tag_id
        handle_ddl(tag_id, tag_type,url=url)
    else:
        pass

改進版以下:

def handle_async(tag_id,tag_type):
    dict_func = {
       '數據庫自助化上線':['service',handle_service],
       '普通上線申請流程':['common',handle_common],
       '空庫初始化':['empty',handle_empty],
       'DBChange確認流程':['dbchange',handle_dbchange],
       'DDL變動申請流程':['ddl',handle_ddl],
    }
    
    for key,value in dict_func.items():
        if key in tag_type:
            url = url_list[item[0]]+tag_id
            item[1](tag_id,tag_type,url=url)

OK,基本上就是這麼一個套路。

重點2:函數的嵌套

函數嵌套調用和嵌套定義的概念:

函數的嵌套調用:在一個函數的內部調用另一個函數,叫作函數的嵌套調用

函數的嵌套定義:在一個函數的內部定義另一個函數,叫作函數的嵌套定義

示例程序1:

def max2(x1,x2):
    max_value =  x1 if x1 > x2 else x2
    return max_value


def max4(x1,x2,x3,x4):
    x12 = max2(x1,x2)
    x34 = max2(x3,x4)
    max_value = x12 if x12 > x34 else x34
    return max_value


print(max4(130,20,30,40))

示例程序2:

def fun1():
    """
    contention:函數的定義至關於變量的定義,是沒有任何實際打印效果的
    """
    print('大刀肉....')
    def fun2():
        print('涮羊肉....')
        def fun3():
            print('土豆肉....')
        fun3()
    fun2()


fun1()

 重點3:Python中名稱空間與做用域的概念

在python當中,名稱空間與做用域是一個比較難理解的概念,但願在這裏給你們講清楚。

名稱空間與做用域的概念:

名稱空間:描述的就是名字與數值的綁定關係,能夠理解爲存放名字(標識符)的地方;做用域:名字起做用的區域,範圍

注意:

一、名稱空間與名稱空間彼此之間是互相隔離的

二、不一樣namespace的建立/銷燬時間也不一樣

三、兩個不一樣namespace中的兩個相同名字的變量之間沒有任何聯繫

Python中名稱空間的分類:

在Python當中,名稱空間分爲3種:局部名稱空間(locals)、全局名稱空間(globals)和內置名稱空間(builtins)

局部名稱空間:即在函數內部定義的名稱空間,包括局部變量和形式參數以及在函數內部定義的函數

全局名稱空間:即在文件級別定義的名稱空間,在文件級別定義的名字都會放入該空間

內置模塊的名稱空間:builtins

簡單來講:

局部名稱空間:存函數內部定義的名字

全局名稱空間:存文件級別定義的名字

內置名稱空間:存內置的名字

Python中名稱空間的加載順序以及名字的查找順序:

加載順序:

內置模塊的名稱空間====>全局名稱空間====>局部名稱空間

名字的查找順序:

 局部名稱空間=====>全局名稱空間====>內置模塊的名稱空間

Python中名稱空間與做用域 的關係:

做用域:全局做用域和局部做用域

其中全局做用域包括內置名稱空間與全局名稱空間定義的名字;局部做用域包括在局部名稱空間定義的名字。

 注意:默認狀況下在局部做用域內不能修改全局做用域範圍內的變量,只能調用數值,若是想修改,只能經過global關鍵字進行修改。

 示例程序1:

def outer():
    a = 0
    b = 1

    def inner():
        print(a)
        print(b)

    inner()
    return 20

outer()

示例程序2:

def outer():
    a = 0
    b = 1

    def inner():
        print(a)
        print(b)

        b = 4

    inner()

outer()

錯誤信息:變量b在賦值前被引用。

0
Traceback (most recent call last):
  File "D:/Python Work Location/Core2/Test3.py", line 16, in <module>
    outer()
  File "D:/Python Work Location/Core2/Test3.py", line 14, in outer
    inner()
  File "D:/Python Work Location/Core2/Test3.py", line 10, in inner
    print(b)
UnboundLocalError: local variable 'b' referenced before assignment

請繼續關注我

相關文章
相關標籤/搜索