中文字幕一区二区人妻电影,亚洲av无码一区二区乱子伦as ,亚洲精品无码永久在线观看,亚洲成aⅴ人片久青草影院按摩,亚洲黑人巨大videos

Python內(nèi)部函數(shù)它們有什么好處?

發(fā)布于:2021-01-19 16:43:18

0

320

0

Python 內(nèi)部函數(shù)

讓我們看看編寫內(nèi)部函數(shù)的三個(gè)常見原因。

注意:在Python中,函數(shù)是“一等公民”。這意味著它們與任何其他對(duì)象(整數(shù)、字符串、列表、模塊等)相當(dāng)。您可以動(dòng)態(tài)地創(chuàng)建或銷毀它們、將它們傳遞給其他函數(shù)、將它們作為值返回等等。

本教程使用Python 3.4.1版。

封裝

您使用內(nèi)部函數(shù)來保護(hù)它們不受函數(shù)外部發(fā)生的任何事情的影響,這意味著它們被隱藏在全局范圍之外。

這里有一個(gè)簡單的例子突出了這個(gè)概念:

def outer(num1):
   def inner_increment(num1):  # Hidden from outer code
       return num1 + 1
   num2 = inner_increment(num1)
   print(num1, num2)

inner_increment(10)
# outer(10)

嘗試調(diào)用inner_increment()

Traceback (most recent call last):
 File "inner.py", line 7, ininner_increment()
NameError: name 'inner_increment' is not defined

現(xiàn)在注釋掉inner_increment()調(diào)用并取消外部函數(shù)調(diào)用的注釋,outer(10),作為參數(shù)傳入:

10 11

注意:請(qǐng)記住這只是一個(gè)示例。盡管這段代碼確實(shí)達(dá)到了預(yù)期的效果,但是最好使用前導(dǎo)下劃線將inner_increment()變成頂級(jí)的“私有”函數(shù):_inner_increment()。

下面的遞歸示例是嵌套函數(shù)的一個(gè)稍微好一點(diǎn)的用例:

def factorial(number):

   # Error handling
   if not isinstance(number, int):
       raise TypeError("Sorry. 'number' must be an integer.")
   if not number >= 0:
       raise ValueError("Sorry. 'number' must be zero or positive.")

   def inner_factorial(number):
       if number <= 1:
           return 1
       return number*inner_factorial(number-1)
   return inner_factorial(number)

# Call the outer function.
print(factorial(4))

也測試一下。使用此設(shè)計(jì)模式的一個(gè)主要優(yōu)點(diǎn)是,通過在外部函數(shù)中執(zhí)行所有參數(shù)檢查,可以安全地跳過內(nèi)部函數(shù)中的錯(cuò)誤檢查。


保持干燥

也許您有一個(gè)巨大的函數(shù),它在許多地方執(zhí)行相同的代碼塊。例如,您可能編寫了一個(gè)處理文件的函數(shù),并且希望接受打開的文件對(duì)象或文件名:

def process(file_name):
   def do_stuff(file_process):
       for line in file_process:
           print(line)
   if isinstance(file_name, str):
       with open(file_name, 'r') as f:
           do_stuff(f)
   else:
       do_stuff(file_name)

注意:同樣,通常只將do_stuff()設(shè)為私有頂級(jí)函數(shù),但如果您希望將其作為內(nèi)部函數(shù)隱藏,則可以。一個(gè)實(shí)際的例子怎么樣?假設(shè)您想知道紐約市WiFi熱點(diǎn)的數(shù)量。是的,這個(gè)城市有原始數(shù)據(jù)告訴我們。訪問站點(diǎn)并下載CSV:

def process(file_name):

   def do_stuff(file_process):
       wifi_locations = {}

       for line in file_process:
           values = line.split(',')
           # Build the dict and increment values.
           wifi_locations[values[1]] = wifi_locations.get(values[1], 0) + 1

       max_key = 0
       for name, key in wifi_locations.items():
           all_locations = sum(wifi_locations.values())
           if key > max_key:
               max_key = key
               business = name

       print(f'There are {all_locations} WiFi hotspots in NYC, '
             f'and {business} has the most with {max_key}.')

   if isinstance(file_name, str):
       with open(file_name, 'r') as f:
           do_stuff(f)
   else:
       do_stuff(file_name)

運(yùn)行函數(shù):

>>> process('NAME_OF_THE.csv')
There are 1251 WiFi hotspots in NYC, and Starbucks has the most with 212.

閉包和工廠函數(shù)

現(xiàn)在我們來討論使用內(nèi)部函數(shù)的最重要原因。到目前為止,我們看到的所有內(nèi)部函數(shù)示例都是普通函數(shù),只是碰巧嵌套在另一個(gè)函數(shù)中。換句話說,我們可以用另一種方式定義這些函數(shù)(如前所述)。沒有具體的理由說明為什么需要嵌套它們。

但是當(dāng)涉及到閉包時(shí),情況并非如此:必須使用嵌套函數(shù)。

什么是閉包?

閉包只會(huì)使內(nèi)部函數(shù)在調(diào)用時(shí)記住其環(huán)境的狀態(tài)。初學(xué)者通常認(rèn)為閉包是內(nèi)部函數(shù),但它實(shí)際上是由內(nèi)部函數(shù)引起的。閉包“關(guān)閉”堆棧上的局部變量,在堆棧創(chuàng)建完成后,這個(gè)問題仍然存在。

一個(gè)例子

這里有一個(gè)例子:

def generate_power(number):
   """
   Examples of use:

   >>> raise_two = generate_power(2)
   >>> raise_three = generate_power(3)
   >>> print(raise_two(7))
   128
   >>> print(raise_three(5))
   243
   """

   # Define the inner function ...
   def nth_power(power):
       return number ** power
   # ... that is returned by the factory function.

   return nth_power

示例中發(fā)生了什么

讓我們看看這個(gè)例子中發(fā)生了什么:

  1. generate_power()是工廠函數(shù),僅表示每次調(diào)用它都會(huì)創(chuàng)建一個(gè)新函數(shù),然后返回新創(chuàng)建的函數(shù)。因此,raise_two()和raise_three()是新創(chuàng)建的功能。

  2. 這個(gè)新的內(nèi)部函數(shù)有什么作用?它只接受一個(gè)參數(shù)power,然后返回number**power。

  3. 內(nèi)部函數(shù)從哪里獲得價(jià)值number?這就是閉包起作用的地方:從外部函數(shù)(工廠函數(shù))nth_power()獲取值power。讓我們逐步完成此過程:

  • 調(diào)用外部函數(shù):generate_power(2)。

  • Build nth_power(),它接受一個(gè)參數(shù)power。

  • 拍攝的狀態(tài)快照nth_power(),其中包括number=2。

  • 將該快照傳遞到中g(shù)enerate_power()。

  • 返回nth_power()。

換句話說,閉包“初始化”其中的數(shù)字欄nth_power(),然后將其返回?,F(xiàn)在,無論何時(shí)調(diào)用該新返回的函數(shù),它都將始終看到其自己的私有快照,其中包括number=2。

結(jié)論

閉包和工廠函數(shù)的使用是內(nèi)部函數(shù)的最常見和最強(qiáng)大的用法。在大多數(shù)情況下,當(dāng)您看到修飾的函數(shù)時(shí),修飾器是一個(gè)工廠函數(shù),它將一個(gè)函數(shù)作為參數(shù)并返回一個(gè)新函數(shù),該新函數(shù)在閉包內(nèi)部包括舊函數(shù)。停止。深吸一口氣。喝杯咖啡。再讀一遍。

換句話說,裝飾器只是用于實(shí)現(xiàn)generate_power()示例中概述的過程的語法糖。

我給您留下最后一個(gè)示例:

def generate_power(exponent):
   def decorator(f):
       def inner(*args):
           result = f(*args)
           return exponent**result
       return inner
   return decorator


@generate_power(2)
def raise_two(n):
   return n

print(raise_two(7))


@generate_power(3)
def raise_three(n):
   return n

print(raise_two(5))

如果您的代碼編輯器允許,并排查看generate_power(exponent)generate_power(number)以說明所討論的概念。(例如,Sublime Text具有列視圖。)

如果尚未對(duì)這兩個(gè)函數(shù)進(jìn)行編碼,請(qǐng)打開“代碼編輯器”并開始編碼。對(duì)于新程序員來說,編碼是一項(xiàng)實(shí)踐活動(dòng):就像騎自行車一樣,你只需要自己動(dòng)手,自己動(dòng)手。所以回到手頭的任務(wù)!

鍵入代碼后,您現(xiàn)在可以清楚地看到,它的相似之處在于產(chǎn)生相同的結(jié)果,但也存在差異。對(duì)于那些從未使用過decorators的人來說,如果你冒險(xiǎn)沿著這條路走下去,注意這些差異將是理解它們的第一步。