Python列表解析式到底該怎麼用

来源:https://www.cnblogs.com/123456feng/archive/2022/05/07/16210403.html
-Advertisement-
Play Games

Python 是一種極其多樣化和強大的編程語言!當需要解決一個問題時,它有著不同的方法。在本文中,將會展示列表解析式 (List Comprehension)。我們將討論如何使用它?什麼時候該或不該使用它? 列表解析式的優勢 •比迴圈更節省時間和空間。 •需要更少的代碼行。 •可將迭代語句轉換為公式 ...


Python 是一種極其多樣化和強大的編程語言!當需要解決一個問題時,它有著不同的方法。在本文中,將會展示列表解析式

(List Comprehension)。我們將討論如何使用它?什麼時候該或不該使用它?

在這裡插入圖片描述

列表解析式的優勢

•比迴圈更節省時間和空間。

•需要更少的代碼行。

•可將迭代語句轉換為公式。

如何在 Python 中創建列表

列表解析式是一種基於現有列表創建列表的語法結構。讓我們來看看創建列表的不同實現

迴圈

迴圈是創建列表的傳統方式。不管你使用什麼樣的迴圈。要以這種方式創建列表,您應該:

1.實例化一個空列表。

2.迴圈遍歷一個可迭代的(如 range)的元素。

3.將每個元素附加到列表的末尾。

Python學習交流Q群:906715085####
numbers = []
for number in range(10):
    numbers.append(number)
    
print(numbers)

 

輸出:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

在此示例中,您實例化了一個空列表 numbers。然後使用 for 迴圈迭代 range(10) 並使用 append() 方法將每個數字附加到列表的末尾。

map() 對象

map() 是創建列表的另一種方法。您需要向 map() 傳遞一個函數和一個可迭代對象,之後它會創建一個對象。該對象包含使用指定函數執行每個迭代元素所獲得的輸出。

例如,我們將呈現在某些產品的價格中增加增值稅的任務。

Python學習交流Q群:903971231###
VAT_PERCENT = 0.1  # 10%


def add_vat(price):
    return price + (price * VAT_PERCENT)
    

prices = [10.03, 8.6, 32.85, 41.5, 22.64]
grand_prices = map(add_vat, prices)
print(grand_prices)
grand_prices = list(grand_prices)
print(grand_prices)

 

您已經構建了 add_vat() 函數並創建了 prices 可迭代對象。您將這兩個參數都傳遞給 map() 並收集生成的 map 對象

grand_prices,或者您可以使用 list() 輕鬆地將其轉換為列表。

輸出:

<map object at 0x7f18721e7400>  # map(add_vat, prices)
[11.03, 9.46, 36.14, 45.65, 24.9]  # list(grand_prices)

 

列表解析式

現在,讓我們看一下列表解析式方法!這確實是 Python 風格,並且是創建列表的更好方法。為了弄清楚這種方法有多強大,我們

用一個單行代碼來重寫那個迴圈示例。

numbers = [number for number in range(10)]
print(numbers)

 

輸出

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

正如您所見,這是一種不可思議的方法!列表解析式看起來足夠可讀,您不需要編寫更多代碼,而只需一行。

為了更好地理解列表,請查看以下語法格式:

new_list = [expression for member in iterable]

 

在這裡插入圖片描述

哪種方法更有效

好的,我們已經學習瞭如何使用迴圈、map() 和列表解析式來創建列表,在您的腦海中可能會提出“哪種方法更有效”的問題。我們

來分析一下吧!

Python學習交流Q群:903971231####
import random
import timeit

```python



VAT_PERCENT = 0.1
PRICES = [random.randrange(100) for x in range(100000)]


def add_vat(price):
    return price + (price * VAT_PERCENT)
    

def get_grand_prices_with_map():
    return list(map(add_vat, PRICES))
    

def get_grand_prices_with_comprehension():
    return [add_vat(price) for price in PRICES]
    

def get_grand_prices_with_loop():
    grand_prices = []
    for price in PRICES:
        grand_prices.append(add_vat(price))
    return grand_prices
    

print(timeit.timeit(get_grand_prices_with_map, number=100))
print(timeit.timeit(add_grand_prices_with_comprehension, number=100))
print(timeit.timeit(get_grand_prices_with_loop, number=100))


輸出:
0.9833468980004909  # with_map
1.197223742999995   # with_comprehension
1.3564663889992516  # with_loop

 

正如我們現在所看到的,創建列表的最優的方法是 map(),排在第二位的是列表解析式,最後是迴圈。

但是,方法的選擇應取決於您想要實現的目標。

•使用 map() 可以使你的代碼更高效。

•使用迴圈可以使代碼的思路展現更加清晰。

•使用列表解析式可以您使代碼更加緊湊,且較高效。這是創建列表的最佳方式,因為這種方式可讀性最強。
在這裡插入圖片描述

高級解析式

條件邏輯

早些時候,我向您展示了這個公式:

new_list = [expression for member in iterable]

 

公式可能有些不完整。對解析式的更加完整描述增加了對可選條件的支持。將條件邏輯添加到列表解析式的最常見方法是在表達式的末尾添加條件:

new_list = [expression for member in iterable (if conditional)]

 

在這裡,您的條件語句正好位於右邊的括弧中。

條件很重要,因為它們允許列表解析式過濾掉不需要的值,這在一般情況下也可以調用 filter():

numbers = [number for number in range(20) if number % 2 == 0]
print(numbers)

 

輸出:

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

 

正如您所看到的那樣,這個解析式收集了可被 2 整除且沒有餘數的數字。

如果您需要更複雜的過濾器,那麼您甚至可以將條件邏輯移動到單獨的函數中。

def is_prime(number):
    if number > 1:
        for el in range(2, int(number/2)+1):
            if (number % el) == 0:
                return False 
        else:
            return True
          

numbers = [number for number in range(20) if is_prime(number)]
print(numbers)

 

輸出:

[2, 3, 5, 7, 11, 13, 17, 19]

 

您構建 is_prime(number) 以確定是否是素數並返回布爾值。接下來,您應該將函數添加到解析式的條件中。

該公式允許您使用條件邏輯從幾個可能的輸出選項中進行選擇。例如,您有一個產品價格表,若有負數,您應將其轉換為正數:

price_list = [1.34, 19.01, -4.2, 6, 8.78, -1,1]
normalized_price_list = [price if price > 0 else price*-1 for price in price_list]
print(normalized_price_list)

 

輸出:

[1.34, 19.01, 4.2, 6, 8.78, 1,1]

 

在這裡,您的表達式 price 有一個條件語句,如果 price > 0 else price*-1。這會告訴 Python,如果價格為正,則輸出價格值;但

如果價格為負,則將價格轉換為正值。該功能很強大,考慮將條件邏輯視為其自身的函數的確是很有用的:

def normalize_price(price):
    return price if price > 0 else price*-1
    

price_list = [1.34, 19.01, -4.2, 6, 8.78, -1,1]
normalized_price_list = [normalize_price(price) for price in price_list]
print(normalized_price_list)

 

輸出:

[1.34, 19.01, 4.2, 6, 8.78, 1,1]

 

集合解析式

您還可以創建一個集合解析式!它基本與列表解析式相同。不同之處在於集合解析式不包含重覆項。您可以通過使用花括弧取代方括弧來創建集合解析式:

string = "Excellent"
unique_string = {letter for letter in string}
print(unique_string)

 

輸出:

{"E", "e", "n", "t", "x", "c", "l"}

 

你的集合解析式只包含唯一的字母。這與列表不同,集合不保證項目將以特定順序存儲數據。這就是為什麼集合輸出的第二個字

母是 e,即使字元串中的第二個字母是 x。

字典解析式

字典解析式也是是類似的,但需要定義一個鍵:

string = "Words are but wind"
word_order = {el: ind+1 for ind, el in enumerate(string.split())}
print(word_order)

 

輸出:

{"Words": 1, "are": 2, "but": 3, "wind": 4}

 

要創建 word_order 字典,請在表達式中使用花括弧 ({}) 以及鍵值對 (el: ind+1)。

在這裡插入圖片描述

海象運算符

Python 3.8 中引入的海象運算符允許您一次解決兩個問題:為變數賦值,返回該值。

假設您需要對將返回溫度數據的 API 應用十次。您想要的只是 100 華氏度以上的結果。而每個請求可能都會返回不同的數據。在

這種情況下,沒有辦法在 Python 中使用列表解析式來解決問題。可迭代成員(如果有條件)的公式表達式無法讓條件將數據分配

給表達式可以訪問的變數。

海象運算符解決了這個問題。它允許您在執行表達式的同時將輸出值分配給變數。以下示例顯示了這是如何實現的,使用

get_weather_data() 生成偽天氣數據:

import random


def get_weather_data():
    return random.randrange(90, 110)
    

hot_temps = [temp for item in range(20) if (temp := get_weather_data()) >= 100]
print(hot_temps)

 

輸出:

[108, 100, 106, 103, 108, 106, 103, 104, 109, 106]

 

什麼時候不要使用解析式

列表解析式非常有用,它可以幫助您編寫清晰且易於閱讀和調試的代碼。但在某些情況下,它們可能會使您的代碼運行速度變慢

或使用更多記憶體。如果它讓您的代碼效率更低或更難理解,那麼可以考慮選擇另一種方式。

在這裡插入圖片描述

註意嵌套的解析式

可以通過嵌套解析式以創建列表、字典和集合的組合集合(譯者註:這個集合不是指 set 對象類型,而是 collection,泛指容

器)。例如,假設一家公司正在跟蹤一年中五個不同城市的收入。存儲這些數據的完美數據結構可以是嵌套在字典解析式中的列

表解析式。

cities = ['New York', 'Oklahoma', 'Toronto', 'Los Angeles', 'Miami']
budgets = {city: [0 for x in range(12)] for city in cities}
print(budgets)

 

輸出:

{
    "NewYork": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Oklahoma": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Toronto": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "LosAngeles": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Miami": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}

 

您使用字典解析式創建了 budgets 容器。該表達式是一個鍵值對,其中包含另一個解析式。此代碼將快速生成城市中每個 city 的

數據列表。

嵌套列表是創建矩陣的常用方法,通常用於數學目的。查看下麵的代碼塊:

matrix = [[x for x in range(7)] for y in range(6)]
print(matrix)

 

輸出:

[
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 4, 5, 6]
]

 

在這裡插入圖片描述

外部列表解析式 [… for y in range(6)] 創建了六行,而內部列表解析式 [x for x in range(7)] 將用值填充這些行中的每一行。

到目前為止,每個嵌套解析式的目標都是真正且直觀的。但是,還有一些其他情況,例如創建扁平化的嵌套列表,其中的邏輯可

以使您的代碼非常難以閱讀。讓我們看下麵的例子,使用嵌套列表解析式來展平一個矩陣:

matrix = [
    [0, 1, 0],
    [1, 0, 1],
    [2, 1, 2],
]
flat = [num for row in matrix for num in row]
print(flat)

 

輸出:

[0, 1, 0, 1, 0, 1, 2, 1, 2]

 

扁平化矩陣的代碼確實很簡潔,但是太難理解了,您應該花點時間弄清楚它是如何工作的。另一方面,如果您使用 for 迴圈來展

平相同的矩陣,那麼您的代碼將更加簡單易讀:

matrix = [
    [0, 1, 0],
    [1, 0, 1],
    [2, 1, 2],
]
flat = []
for row in matrix:
    for num in row:
        flat.append(num)
print(flat)

 

輸出:

[0, 1, 0, 1, 0, 1, 2, 1, 2]

 

現在,您可以看到代碼一次遍歷矩陣的一行,在移動到下一行之前取出該行中的所有元素。

雖然嵌套列表解析式可能看起來更具有 Python 風格,但對於能夠編寫出您的團隊可以輕鬆理解和修改的代碼來才是更加最重要

的。當選擇一個方法時,您應該根據解析式是有助於還是有損於可讀性來做出相應的判斷。
在這裡插入圖片描述

為大型數據集使用生成器

Python 中的列表解析式通過將整個列表存儲到記憶體中來工作。對於小型至中型列表這通常很好。如果您想將前一千個整數相加,

那麼列表解析式將輕鬆地解決此任務:

summary = sum([x for x in range(1000)])
print(summary)

 

輸出:499500

但是,如果您需要對十億個數字求和呢?您可以嘗試執行此操作,但您的電腦可能不會有響應。這是可能因為電腦中分配大

量記憶體。也許您是因為電腦沒有如此多的記憶體資源。

例如,你想要一些第一個十億整數,那麼讓我們使用生成器!這可能多需要一些時間,但電腦應該可以剋服它:

summary = sum((x for x in range(1000000000)))
print(summary)

 

輸出:

499999999500000000

 

讓我們來對比一下哪種方法是更優的!

import timeit


def get_sum_with_map():
    return sum(map(lambda x: x, range(1000000000)))


def get_sum_with_generator():
    return sum((x for x in range(1000000000)))


print(timeit.timeit(get_sum_with_map, number=100))
print(timeit.timeit(get_sum_with_generator, number=100))

 

輸出:

4940.844053814  # get_sum_with_map
3464.1995523349997  # get_sum_with_generator

 

正如您所見,生成器比 map() 高效得多。

在這裡插入圖片描述

總結

本文向您介紹了列表解析式,以及如何使用它來解決複雜的任務,而不會使您的代碼變得過於困難。

現在你:

•學習了幾種創建列表的替代方法。

•找出每種方法的優點。

•可以簡化迴圈和 map() 調用列表解析式。

•理解了一種將條件邏輯添加到解析式中的方法。

•可以創建集合和字典解析式。

•學會了何時不使用解析式。

最後

如果你看到這裡,相信列表解析式的用法你已經完全掌握了,喜歡這篇文章的記得點贊收藏,有不懂的地方記得點贊評論,我看

見都會回覆的。

在這裡插入圖片描述


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

-Advertisement-
Play Games
更多相關文章
  • 首先先介紹三個性質 可見性 可見性代表主記憶體中變數更新,線程中可以及時獲得最新的值。 下麵例子證明瞭線程中可見性的問題 由於發現多次執行都要到主記憶體中取變數,所以會將變數緩存到線程的工作記憶體,這樣當其他線程更新該變數的時候,該線程無法得知,導致該線程會無限的運行下去。 public class te ...
  • 寫在前面,本文主要介紹Python基礎排序和自定義排序的一些規則,如果都比較熟悉,可以直接翻到第三節,看下實際的筆試面試題中關於自定義排序的應用。 一、基礎排序 排序是比較基礎的演算法,與很多語言一樣,Python也提供了對列表的排序方法和內建排序函數。 1、兩種排序方式 方式一: li = [1, ...
  • 第一個Python程式 每個編程語言的學習,第一個程式都是先向世界問好,Python 也不例外,這節我們先寫下第一個Python 程式 —— Hello World 。 一、Python 簡介 Python 是著名的“龜叔” Guido van Rossum 在 1989 年聖誕節期間,為了打發無聊 ...
  • Spring Ioc源碼分析系列--Ioc源碼入口分析 本系列文章代碼基於Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源碼分析系列--Ioc的基礎知識準備介紹了Ioc的基礎概念以及Spring Ioc體系的部分基礎知識。那麼這一篇就會真正通過一個例子,啟動Ioc ...
  • 前言 有時候我們些代碼是總發此疑惑? 為什麼別人採集 xx 網站的時候能成功,而我卻總是不返回給數據 出現這種原因時往往是我們沒有給夠偽裝, 被識別了出來~ 就像人,你出門肯定是要穿衣服的對不,如果你不穿! 走在外面,肯定是最顯眼的一個,不抓你抓誰 還有一種就是明明我之前運行成功了,為什麼我現在再次 ...
  • 用python的pandas庫進行數據分析,分析對象是老番茄B站數據。 pandas常用基礎數據分析代碼。 ...
  • 給開源項目尤其是Spring這種知名度高的項目貢獻代碼是比較難的,起碼胖哥是這麼認為的。有些時候我們的靈感未必契合作者的設計意圖,即使你的代碼十分優雅。 我曾經給Spring Security提交了一個我認為非常重要的一項優化,和作者溝通了幾十個來回無法說服他。人家說留了抽象介面,你覺得不對自己實現 ...
  • 作者:CadeCode 地址:https://juejin.cn/post/7043403364020781064 斷言 斷言是一個邏輯判斷,用於檢查不應該發生的情況 Assert 關鍵字在 JDK1.4 中引入,可通過 JVM 參數-enableassertions開啟 SpringBoot 中提 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...