中文字幕一区二区人妻电影,亚洲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ù)的三個常見原因。

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

本教程使用Python 3.4.1版。

封裝

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

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

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)

嘗試調用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()調用并取消外部函數(shù)調用的注釋,outer(10),作為參數(shù)傳入:

10 11

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

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

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))

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


保持干燥

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

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ù),但如果您希望將其作為內(nèi)部函數(shù)隱藏,則可以。一個實際的例子怎么樣?假設您想知道紐約市WiFi熱點的數(shù)量。是的,這個城市有原始數(shù)據(jù)告訴我們。訪問站點并下載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)

運行函數(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ù),只是碰巧嵌套在另一個函數(shù)中。換句話說,我們可以用另一種方式定義這些函數(shù)(如前所述)。沒有具體的理由說明為什么需要嵌套它們。

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

什么是閉包?

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

一個例子

這里有一個例子:

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ā)生了什么

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

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

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

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

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

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

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

  • 將該快照傳遞到中generate_power()。

  • 返回nth_power()。

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

結論

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

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

我給您留下最后一個示例:

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具有列視圖。)

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

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