Python 基礎面試第三彈

来源:https://www.cnblogs.com/beyond-tester/archive/2023/08/30/17668475.html
-Advertisement-
Play Games

1. 獲取當前目錄下所有文件名 import os def get_all_files(directory): file_list = [] # os.walk返回一個生成器,每次迭代時返回當前目錄路徑、子目錄列表和文件列表 for root, dirs, files in os.walk(dire ...


1. 獲取當前目錄下所有文件名

import os

def get_all_files(directory):
    file_list = []
# os.walk返回一個生成器,每次迭代時返回當前目錄路徑、子目錄列表和文件列表 for root, dirs, files in os.walk(directory): for file in files: file_list.append(os.path.join(root, file)) return file_list # 獲取當前目錄下的所有文件名 current_directory = os.getcwd() files = get_all_files(current_directory) # 列印所有文件名 for file in files: print(file)

 

2. Python中生成器和迭代器區別

迭代器(Iterator)是一種實現了迭代協議的對象,它必須提供一個__iter__()方法和一個__next__()方法。通過調用__iter__()方法,迭代器可以返回自身,並且通過調用__next__()方法,迭代器可以依次返回下一個元素,直到沒有更多元素時拋出StopIteration異常。迭代器是一種惰性計算的方式,每次只在需要時生成一個元素,從而節省記憶體空間。可以使用iter()函數將可迭代對象轉換為迭代器。

生成器(Generator)是一種特殊的迭代器,它使用了更為簡潔的語法來定義迭代器。生成器可以通過函數中的yield關鍵字來實現,當函數執行到yield語句時,會暫停執行並返回一個值,保存當前狀態,下次調用時從上次暫停的位置繼續執行。生成器函數可以像普通函數一樣接收參數,並且可以包含迴圈、條件語句等邏輯。生成器是一種非常方便和高效的迭代器實現方式。

下麵是生成器和迭代器的區別總結:

  1. 語法:生成器使用yield關鍵字來定義,而迭代器需要實現__iter__()__next__()方法。
  2. 實現:生成器可以使用函數來定義,而迭代器可以由類來實現。
  3. 狀態保存:生成器在yield語句處暫停執行並保存當前狀態,下次調用時從上次暫停的位置繼續執行;迭代器通過內部的狀態和指針來保存迭代的位置。
  4. 簡潔性:生成器的語法更加簡潔,可以使用普通的函數定義和控制流語句;迭代器需要實現多個特殊方法,代碼相對較多。
  5. 惰性計算:生成器是惰性計算的,每次只在需要時生成一個元素;迭代器也可以實現惰性計算,但需要手動控制。

總之,生成器是一種特殊的迭代器,它提供了更簡潔和方便的語法。生成器可以通過函數中的yield語句來實現迭代過程,並且可以像普通函數一樣編寫邏輯。迭代器是一種更通用的概念,可以通過類來實現,需要顯式地定義__iter__()__next__()方法。無論是生成器還是迭代器,它們都能夠實現按需生成和處理大量數據的能力,提高了代碼的效率和可讀性。

 一個小慄子:

當我們需要遍歷一個很大的數據集時,生成器可以幫助我們按需生成數據,而不是一次性載入整個數據集到記憶體中。

下麵是一個簡單的例子,我們使用生成器來按需生成斐波那契數列的前n個元素:

def fibonacci_generator(n):
    a, b = 0, 1
    count = 0
    while count < n:
        yield a
        a, b = b, a + b
        count += 1

# 使用生成器按需生成斐波那契數列的前10個元素
fibonacci = fibonacci_generator(10)

# 逐個列印生成的元素
for num in fibonacci:
    print(num)

  

  在上述代碼中,我們定義了一個生成器函數fibonacci_generator,它使用了yield語句來生成斐波那契數列的元素。每次調用生成器的__next__()方法時,它會執行到yield語句處,

返回當前的斐波那契數並暫停執行,保存當前狀態。然後,下次調用生成器的__next__()方法時,它會從上次暫停的位置繼續執行,生成下一個斐波那契數。這樣,我們可以通過迭代生成器

來按需獲取斐波那契數列的元素。當我們遍歷生成器對象時,它會依次生成斐波那契數列的元素並列印出來。由於生成器是按需生成數據的,它只在需要時生成一個元素,而不是一次性生成整

個數列。這樣可以節省記憶體空間,特別是當斐波那契數列很大時。總結起來,生成器可以看作是一種特殊的函數,它能夠按需生成數據,節省記憶體空間,並且提供了一種簡潔和方便的方式來

實現迭代器。通過使用生成器,我們可以避免一次性載入大量數據到記憶體中,而是在需要時逐個生成數據,從而提高代碼的效率和可擴展性。

3. 什麼是可迭代對象,其原理又是什麼

  可迭代對象(Iterable)是指可以被迭代遍歷的對象。在許多編程語言中,迭代是指按照一定的順序逐個訪問集合中的元素的過程。在Python中,可迭代對象是指實現了迭代器協議(Iterator Protocol)的對象。

迭代器協議包含兩個方法:

  1. __iter__()方法:該方法返回一個迭代器對象。迭代器對象用於實現具體的迭代邏輯,並且必須包含__next__()方法。

  2. __next__()方法:該方法返回迭代器中的下一個元素。如果沒有元素可供返回,它應該引發StopIteration異常。

當我們使用可迭代對象進行迭代時,實際上是通過迭代器對象來完成的。迭代器對象負責追蹤當前的迭代狀態,並提供下一個元素。迭代器對象會在每次迭代時調用__next__()方法,並返回下一個元素,直到遍歷完所有元素或者引發StopIteration異常為止。

Python中許多內置的數據類型和容器都是可迭代對象,例如列表(List)、元組(Tuple)、字典(Dictionary)、集合(Set)等。此外,我們也可以通過自定義類來實現可迭代對象,只需在類中定義__iter__()方法,併在該方法中返回一個迭代器對象即可。

以下是一個示例,展示瞭如何使用可迭代對象和迭代器對象進行迭代:

# 創建一個可迭代對象
my_list = [1, 2, 3, 4, 5]

# 獲取迭代器對象
my_iter = iter(my_list)

# 使用迭代器對象進行迭代
try:
    while True:
        item = next(my_iter)
        print(item)
except StopIteration:
    pass

  在上述示例中,我們通過調用iter()函數獲取了my_list的迭代器對象my_iter,然後使用next()函數從迭代器對象中獲取下一個元素並列印,直到遍歷完所有元素或引發

StopIteration異常為止。可迭代對象的原理是基於迭代器協議的實現,通過迭代器對象的__next__()方法來提供序列中的下一個元素。這種機制使得我們可以方便地對集合中的元素

進行逐個訪問和處理,提供了一種統一的迭代介面

自己實現可迭代對象小慄子

 
class MyIterable:
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        self.index = 0
        return self

    def __next__(self):
        if self.index < len(self.data):
            item = self.data[self.index]
            self.index += 1
            return item
        else:
            raise StopIteration

# 創建一個可迭代對象實例
my_iterable = MyIterable([1, 2, 3, 4, 5])

# 使用迭代器進行迭代
for item in my_iterable:
    print(item)

4. Python2 和 Python3主要的區別有哪些:

Python 2.x 和 Python 3.x 之間的一些主要區別:

  1. 列印函數:在 Python 2.x 中,列印語句是一個關鍵字,使用類似於 print "Hello" 的語法。而在 Python 3.x 中,print 被改造為一個內置函數,需要使用括弧,例如 print("Hello")

  2. 整數除法:在 Python 2.x 中,整數除法的結果會被截斷為整數,例如 5 / 2 的結果是 2。而在 Python 3.x 中,整數除法的結果將保留小數部分,得到浮點數結果,例如 5 / 2 的結果是 2.5。如果想要執行截斷整數除法,可以使用 // 運算符。

  3. Unicode 字元串:在 Python 2.x 中,字元串類型分為普通字元串和 Unicode 字元串(以 u 首碼表示),這導致字元串處理的一些混亂和困惑。而在 Python 3.x 中,所有字元串都是 Unicode 字元串,普通字元串是以位元組表示的,需要使用 b 首碼表示。

  4. xrange 替代 range:在 Python 2.x 中,range 函數返回的是一個列表,如果需要生成大範圍的整數序列,會占用大量記憶體。而在 Python 3.x 中,range 函數的實現類似於 Python 2.x 中的 xrange,返回一個迭代器對象,節省了記憶體。

  5. 異常語法:在 Python 2.x 中,捕獲異常時使用的語法是 except Exception, e,將異常對象存儲在變數 e 中。而在 Python 3.x 中,使用 except Exception as e 的語法,將異常對象存儲在變數 e 中。

  6. input 函數:在 Python 2.x 中,input 函數會將用戶輸入的內容作為 Python 代碼進行解析,存在安全風險。而在 Python 3.x 中,input 函數始終將用戶輸入的內容作為字元串返回,不進行解析。

除了上述主要區別之外,Python 3.x 還進行了一些其他改進,包括改進的類定義語法、更好的模塊管理和導入機制、更一致的異常處理和錯誤機制等。然而,這也導致了 Python 2.x 代碼無法直接在 Python 3.x 中運行,需要進行一些修改和調整。

 

5. 說說Python中多線程和多進程

  1. 多線程(Multithreading):

    • 多線程是指在一個進程內創建多個線程,每個線程獨立執行不同的任務。多線程共用進程的記憶體空間,因此線程之間可以方便地共用數據。
    • 在 Python 中,可以使用 threading 模塊來創建和管理線程。通過創建 Thread 類的實例,指定要執行的函數或方法,並調用 start() 方法,可以啟動一個線程。
    • Python 的多線程由於全局解釋器鎖(Global Interpreter Lock,GIL)的存在,同一時刻只允許一個線程執行 Python 位元組碼。這意味著多線程並不能充分利用多核處理器,併發性能受限。多線程適用於 I/O 密集型任務,如網路請求、文件讀寫等,但對於 CPU 密集型任務,多線程並不能提升性能。
  2. 多進程(Multiprocessing):

    • 多進程是指創建多個獨立的進程,每個進程都有自己的記憶體空間和系統資源。多個進程之間相互獨立,可以並行執行不同的任務。每個進程都有自己的 Python 解釋器,因此可以充分利用多核處理器,提高併發性能。
    • 在 Python 中,可以使用 multiprocessing 模塊來創建和管理進程。通過創建 Process 類的實例,指定要執行的函數或方法,並調用 start() 方法,可以啟動一個進程。
    • 多進程可以通過進程間通信(Inter-Process Communication,IPC)來實現進程之間的數據共用。Python 提供了多種 IPC 機制,如隊列(Queue)、管道(Pipe)和共用記憶體等。

總結:

  • 多線程適合處理 I/O 密集型任務,可以提高程式的響應能力和效率。
  • 多進程適合處理 CPU 密集型任務,可以充分利用多核處理器提高併發性能。
  • 在 Python 中,多線程受到 GIL 的限制,多進程可以繞過 GIL,實現真正的並行執行。
  • 使用多線程或多進程時需要註意線程安全和進程安全的問題,避免數據競爭和共用資源的衝突。

6. Python中GIL鎖:

  全局解釋器鎖(Global Interpreter Lock,簡稱 GIL)是在 CPython 解釋器中存在的一個特性。它是一種機制,用於保證同一時刻只有一個線程執行 Python 位元組碼。雖然 GIL 的存在確保了 CPython 解釋器的線程安全性,但也對多線程併發執行帶來了一些限制。

以下是對 GIL 的一些詳細解釋和理解:

  1. GIL 的作用:

    • GIL 的主要作用是保護 CPython 解釋器內部的數據結構免受併發訪問的影響,確保線程安全。
    • CPython 使用引用計數(Reference Counting)作為記憶體管理的主要機制。GIL 保證了在修改引用計數時的原子性,避免了競態條件(Race Condition)和記憶體泄漏問題。
    • GIL 還可以簡化 CPython 解釋器的實現,使其更加簡單高效。
  2. GIL 的影響:

    • 由於 GIL 的存在,同一時刻只有一個線程可以執行 Python 位元組碼,其他線程被阻塞。這意味著多線程並不能充分利用多核處理器,無法實現真正的並行執行。
    • 對於 CPU 密集型任務,由於 GIL 的限制,多線程並不能提升性能。實際上,由於線程切換的開銷,可能導致多線程執行速度比單線程還要慢。
    • GIL 對於 I/O 密集型任務的影響相對較小,因為線程在進行 I/O 操作時會主動釋放 GIL,允許其他線程執行。因此,多線程在處理 I/O 操作時仍然可以提供一定的性能優勢。
  3. 解決 GIL 的方法:

    • 採用多進程:由於每個進程都有獨立的 Python 解釋器和 GIL,多進程可以充分利用多核處理器,實現並行執行。
    • 使用擴展模塊:某些擴展模塊,如 NumPy、Pandas 等,使用 C/C++ 編寫,可以釋放 GIL,允許多線程並行執行。
    • 使用多線程庫:一些第三方庫,如 multiprocessing 模塊、concurrent.futures 模塊等,提供了替代方案,使得在某些情況下可以繞過 GIL 的限制。

需要註意的是,GIL 只存在於 CPython 解釋器中,而其他實現(如 Jython、IronPython)可能沒有 GIL。此外,對於許多類型的應用程式,如 I/O 密集型、併發處理不頻繁的應用程式,GIL

的影響較小,可以繼續使用多線程來實現併發。然而,對於 CPU 密集型任務和需要充分利用多核處理器的應用程式,考慮使用多進程或其他解決方案來規避 GIL。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本章提供了 HarmonyOS 的基礎知識,包括定義、發展歷程、特點、架構和與其他操作系統的比較。這為後續的開發工作打下了堅實的基礎。 ...
  • # 背景 通常情況下,當我們需要從父組件向子組件傳遞數據時,會使用 **props**。想象一下這樣的結構:有一些多層級嵌套的組件,形成了一顆巨大的組件樹,而某個深層的子組件需要一個較遠的祖先組件中的部分數據。在這種情況下,如果僅使用 props 則必須將其沿著組件鏈逐級傳遞下去,這會非常麻煩: ! ...
  • BFC作為前端面試佈局方面的重要考點,開發者有必要進行深入的瞭解,通過對BFC的深入理解,也能幫助我們解決佈局中的很多問題。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 在我們項目開發中,經常會有佈局拉伸的需求,接下來 讓我們一步步用 vue指令 實現這個需求 動手開發 線上體驗 codesandbox.io/s/dawn-cdn-… 常規使用 解決拉伸觸發時機 既然我們使用了指令的方式,也就是犧牲 ...
  • chrome 手機端網頁如何調試 在Chrome手機端,你可以使用Chrome開發者工具來調試網頁。下麵是一些步驟: 1. 首先,確保你的手機已經開啟開發者模式。打開USB調試功能或可以通過USB連接或無線連接。 2. 在電腦上打開Chrome瀏覽器,並輸入地址 "chrome://inspect" ...
  • 原子化 CSS 框架 我記得很久之前有時候為了少寫些css,我們通常會有如下的樣板代碼 .block { display: block; } .flex { display:flex } .flex-center { align-items: center; justify-content: cen ...
  • 前言 前面說了很多Kafka的性能優點,有些童鞋要說了,這Kafka在企業開發或者企業級應用中要怎麼用呢?今天咱們就來簡單探究一下。 1、 使用 Kafka 進行消息的非同步處理 Kafka 提供了一個可靠的消息傳遞機制,使得企業能夠將不同組件之間的通信解耦,實現高效的非同步處理。在企業級應用中,可以通 ...
  • ## 2023年8月23日 ### #include `cstdio` 有兩個函數 printf,scanf 用於輸出和輸入 ```txt int : %d float : %f double : %lf char : %c long long : %lld ``` `iostream` 有 cin ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...