Python 中的反轉字串:reversed()、切片等

華為雲開發者社群發表於2021-11-17
摘要:以相反的順序反轉和處理字串可能是程式設計中的一項常見任務。Python 提供了一組工具和技術,可以幫助您快速有效地執行字串反轉。

本文分享自華為雲社群《Python 中的反轉字串:reversed()、切片等》,作者: Yuchuan 。

當您經常在程式碼中使用 Python 字串時,您可能需要以相反的順序使用它們。Python 包含一些方便的工具和技術,可以在這些情況下為您提供幫助。使用它們,您將能夠快速有效地構建現有字串的反向副本。

瞭解這些在 Python 中反轉字串的工具和技術將幫助您提高作為 Python 開發人員的熟練程度。

在本教程中,您將學習如何:

  • 通過切片快速構建反向字串
  • 使用和建立現有字串的反向副本reversed().join()
  • 使用迭代和遞迴手動反轉現有字串
  • 對字串執行反向迭代
  • 使用相反的順序對字串進行排序sorted()

為了最大限度地利用本教程,你應該知道的基本知識串,for以及while迴圈和遞迴。

使用核心 Python 工具反轉字串

在某些特定情況下,可能需要以相反的順序使用 Python字串。例如,假設您有一個字串,並且想要一種快速的方法來反轉它以獲取. 您可以使用哪些 Python 工具來提供幫助?"ABCDEF""FEDCBA"

字串在 Python 中是不可變的,因此不可能原地反轉給定的字串。您需要建立目標字串的反向副本以滿足要求。

Python 提供了兩種直接的方法來反轉字串。由於字串是序列,因此它們是indexable、sliceable和iterable。這些功能允許您使用切片以相反的順序直接生成給定字串的副本。第二個選項是使用內建函式reversed()建立一個迭代器,該迭代器以相反的順序生成輸入字串的字元。

通過切片反轉字串

切片是一種有用的技術,它允許您使用稱為offsets的整數索引的不同組合從給定序列中提取專案。當涉及到切片字串時,這些偏移量定義了切片中第一個字元的索引、停止切片的字元的索引,以及一個定義每次迭代要跳過多少個字元的值。

要對字串進行切片,可以使用以下語法:

a_string[start:stop:step]

你的偏移量start,stop和step。此表示式從startto stop − 1by 中提取所有字元step。稍後您將更深入地瞭解這一切意味著什麼。

所有偏移量都是可選的,它們具有以下預設值:

Python 中的反轉字串:reversed()、切片等

這裡,start表示切片中第一個字元stop的索引,同時儲存停止切片操作的索引。第三個偏移量step允許您決定切片在每次迭代中將跳過多少個字元。

注意:切片操作在達到等於或大於 的索引時完成stop。這意味著它永遠不會在最終切片中包含該索引處的專案(如果有)。

該step偏移允許您微調如何,而跳過其他從字串中提取所需的字元:

>>>
>>> letters = "AaBbCcDd"

>>> # Get all characters relying on default offsets
>>> letters[::]
'AaBbCcDd'
>>> letters[:]
'AaBbCcDd'

>>> # Get every other character from 0 to the end
>>> letters[::2]
'ABCD'

>>> # Get every other character from 1 to the end
>>> letters[1::2]
'abcd'

在這裡,您首先在letters不提供顯式偏移值的情況下進行切片以獲取原始字串的完整副本。為此,您還可以使用省略第二個冒號 ( :)的切片。隨著step等於2,切片會從目標字串中的每個其它字元。您可以使用不同的偏移量來更好地瞭解切片的工作原理。

為什麼切片和第三個偏移量與 Python 中的字串反轉有關?答案在於如何step處理負值。如果為 提供負值step,則切片向後執行,即從右到左。

例如,如果您設定為stepequal -1,那麼您可以構建一個以相反順序檢索所有字元的切片:

>>>
>>> letters = "ABCDEF"

>>> letters[::-1]
'FEDCBA'

>>> letters
'ABCDEF'

此切片返回從字串右端(索引等於 )到len(letters) - 1字串左端(索引為 )的所有字元0。當您使用此技巧時,您會以相反的順序獲得原始字串的副本,而不會影響 的原始內容letters。

建立現有字串的反向副本的另一種技術是使用slice(). 這個內建函式的簽名如下:

slice(start, stop, step)

此函式接受三個引數,與切片運算子中的偏移量具有相同的含義,並返回一個切片物件,表示呼叫range(start, stop, step).

您可以使用slice()來模擬切片[::-1]並快速反轉字串。繼續並slice()在方括號內執行以下呼叫:

>>>
>>> letters = "ABCDEF"

>>> letters[slice(None, None, -1)]
'FEDCBA'

傳遞None給 的前兩個引數slice()告訴函式您要依賴其內部預設行為,這與沒有start和值的標準切片相同stop。換句話說,傳遞None給start和stop意味著您需要從底層序列的左端到右端的切片。

使用.join()和反轉字串reversed()

第二種,可以說是最 Pythonic 的反轉字串的方法是reversed()與str.join(). 如果您將字串傳遞給reversed(),您將獲得一個以相反順序生成字元的迭代器:

>>>
>>> greeting = reversed("Hello, World!")

>>> next(greeting)
'!'
>>> next(greeting)
'd'
>>> next(greeting)
'l'

當您將next()withgreeting作為引數呼叫時,您會從原始字串的右端獲取每個字元。

需要注意的重要一點reversed()是,生成的迭代器直接從原始字串中生成字元。換句話說,它不會建立一個新的反向字串,而是從現有字串反向讀取字元。這種行為在記憶體消耗方面相當有效,並且在某些上下文和情況下(例如迭代)可能是一個根本性的勝利。

您可以使用reversed()直接呼叫獲得的迭代器作為引數.join():

>>>
>>> "".join(reversed("Hello, World!"))
'!dlroW ,olleH'

在這個單行表示式中,您將呼叫的結果reversed()直接作為引數傳遞給.join()。因此,您將獲得原始輸入字串的反向副本。的組合reversed(),並.join()為扭轉字串一個很好的選擇。

手動生成反轉字串

到目前為止,您已經瞭解了快速反轉字串的核心 Python 工具和技術。大多數時候,它們將是您的最佳選擇。但是,您可能需要在編碼冒險的某個時刻手動反轉字串。

在本節中,您將學習如何使用顯式迴圈和遞迴來反轉字串。最後一種技術在 Pythonreduce()函式的幫助下使用函數語言程式設計方法。

反轉迴圈中的字串

您將用於反轉字串的第一種技術涉及for迴圈和連線運算子 ( +)。使用兩個字串作為運算元,此運算子返回一個連線原始字串的新字串。整個操作稱為串聯。

注意:使用.join()是在 Python 中連線字串的推薦方法。它乾淨、高效且Pythonic。

這是一個函式,它接受一個字串並使用串聯在迴圈中反轉它:

>>>
>>> def reversed_string(text):
...     result = ""
...     for char in text:
...         result = char + result
...     return result
...

>>> reversed_string("Hello, World!")
'!dlroW ,olleH'

在每次迭代中,迴圈採用後續字元char, fromtext並將其與 的當前內容連線起來result。請注意,result最初儲存的是一個空字串 ( "")。然後將新的中間字串重新分配給result。在迴圈結束時,result儲存一個新字串作為原始字串的反向副本。

注意:由於 Python 字串是不可變的資料型別,您應該記住本節中的示例使用了一種浪費技術。它們依賴於建立連續的中間字串,只是為了在下一次迭代中將它們丟棄。

如果您更喜歡使用whileloop,那麼您可以執行以下操作來構建給定字串的反向副本:

>>>
>>> def reversed_string(text):
...     result = ""
...     index = len(text) - 1
...     while index >= 0:
...         result += text[index]
...         index -= 1
...     return result
...

>>> reversed_string("Hello, World!")
'!dlroW ,olleH'

在這裡,您首先使用 計算index輸入字串中最後一個字元的len()。迴圈從index下到幷包括0。在每次迭代中,您都使用擴充賦值運算子 ( +=) 建立一箇中間字串,該字串將 的內容result與來自 的相應字元連線起來text。同樣,最終結果是通過反轉輸入字串產生的新字串。

用遞迴反轉字串

您還可以使用遞迴來反轉字串。遞迴是指函式在自己的主體中呼叫自身。為了防止無限遞迴,您應該提供一個無需再次呼叫函式即可生成結果的基本情況。第二個元件是遞迴 case,它啟動遞迴迴圈並執行大部分計算。

下面是如何定義一個遞迴函式,該函式返回給定字串的反向副本:

>>>
>>> def reversed_string(text):
...     if len(text) == 1:
...         return text
...     return reversed_string(text[1:]) + text[:1]
...

>>> reversed_string("Hello, World!")
'!dlroW ,olleH'

在本例中,您首先檢查基本情況。如果輸入字串只有一個字元,則將該字串返回給呼叫者。

最後一個語句,即遞迴情況,呼叫reversed_string()自身。該呼叫使用text[1:]輸入字串的切片作為引數。此切片包含 中的所有字元text,第一個除外。下一步是將遞迴呼叫的結果與text[:1]包含 的第一個字元的單字串 相加text。

在上面的例子中需要注意的一個重要問題是,如果你將一個長字串作為引數傳遞給reversed_string(),那麼你將得到一個RecursionError:

>>>
>>> very_long_greeting = "Hello, World!" * 1_000

>>> reversed_string(very_long_greeting)
Traceback (most recent call last):
    ...
RecursionError: maximum recursion depth exceeded while calling a Python object

達到 Python 的預設遞迴限制是您應該在程式碼中考慮的一個重要問題。但是,如果您確實需要使用遞迴,那麼您仍然可以選擇手動設定遞迴限制。

您可以通過呼叫getrecursionlimit()from來檢查當前 Python 直譯器的遞迴限制sys。預設情況下,此值通常為1000。您可以使用setrecursionlimit()來自同一模組的sys. 使用這些函式,您可以配置 Python 環境,以便您的遞迴解決方案可以工作。來試試看吧!

使用reduce()扭轉字串

如果您更喜歡使用函數語言程式設計方法,則可以使用reduce()fromfunctools來反轉字串。Pythonreduce()將摺疊或歸約函式和可迭代物件作為引數。然後它將提供的函式應用於輸入迭代中的專案並返回單個累積值。

以下是您可以如何利用reduce()反轉字串的方法:

>>>
>>> from functools import reduce

>>> def reversed_string(text):
...     return reduce(lambda a, b: b + a, text)
...

>>> reversed_string("Hello, World!")
'!dlroW ,olleH'

在此示例中,該lambda函式採用兩個字串並以相反的順序連線它們。呼叫在迴圈中reduce()應用lambdatotext並構建原始字串的反向副本。

反向遍歷字串

有時您可能希望以相反的順序遍歷現有字串,這種技術通常稱為反向迭代。根據您的特定需求,您可以使用以下選項之一對字串進行反向迭代:

  • 該reversed()內建功能
  • 切片運算子, [::-1]

反向迭代可以說是這些工具最常見的用例,因此在以下幾節中,您將瞭解如何在迭代上下文中使用它們。

該reversed()內建功能

以相反順序迭代字串的最可讀和 Pythonic 的方法是使用reversed(). 不久前,當您將它與.join()建立反向字串一起使用時,您已經瞭解了該函式。

但是,主要意圖和用例reversed()是支援 Python 可迭代物件的反向迭代。以字串作為引數,reversed()返回一個迭代器,該迭代器以相反的順序從輸入字串中產生字元。

以下是如何以相反的順序迭代字串reversed():

>>>
>>> greeting = "Hello, World!"

>>> for char in reversed(greeting):
...     print(char)
...
!
d
l
r
o
W

,
o
l
l
e
H

>>> reversed(greeting)
<reversed object at 0x7f17aa89e070>

for此示例中的迴圈非常具有可讀性。的名稱reversed()清楚地表達了其意圖並傳達了該函式不會對輸入資料產生任何副作用。由於reversed()返回一個迭代器,迴圈在記憶體使用方面也很有效。

切片運算子, [::-1]

對字串執行反向迭代的第二種方法是使用您之前在a_string[::-1]示例中看到的擴充套件切片語法。即使這種方法不利於記憶體效率和可讀性,它仍然提供了一種快速迭代現有字串的反向副本的方法:

>>>
>>> greeting = "Hello, World!"

>>> for char in greeting[::-1]:
...     print(char)
...
!
d
l
r
o
W

,
o
l
l
e
H

>>> greeting[::-1]
'!dlroW ,olleH'

在本例中,您應用切片運算子greeting來建立它的反向副本。然後你使用那​​個新的反向字串來饋送迴圈。在這種情況下,您正在迭代一個新的反向字串,因此該解決方案的記憶體效率低於使用reversed().

建立自定義可逆字串

如果您曾經嘗試過反轉 Python 列表,那麼您就會知道列表有一個方便的方法,稱為原位.reverse()反轉底層列表。由於字串在 Python 中是不可變的,因此它們不提供類似的方法。

但是,您仍然可以使用.reverse()模仿list.reverse(). 您可以這樣做:

>>>
>>> from collections import UserString

>>> class ReversibleString(UserString):
...     def reverse(self):
...         self.data = self.data[::-1]
...

ReversibleString繼承自UserString,它是collections模組的一個類。UserString是str內建資料型別的包裝器。它是專門為建立str. UserString當您需要建立具有附加功能的自定義字串類時非常方便。

UserString提供與常規字串相同的功能。它還新增了一個稱為.data持有的公共屬性,並允許您訪問包裝的字串物件。

在裡面ReversibleString,你創造.reverse()。此方法反轉包裝的字串.data並將結果重新分配回.data. 從外部看,呼叫的.reverse()工作就像將字串反轉到位。然而,它實際上做的是建立一個新的字串,以相反的順序包含原始資料。

以下是ReversibleString實踐中的工作原理:

>>>
>>> text = ReversibleString("Hello, World!")
>>> text
'Hello, World!'

>>> # Reverse the string in place
>>> text.reverse()
>>> text
'!dlroW ,olleH'

當您呼叫.reverse()on 時text,該方法就像您正在對底層字串進行就地更改一樣。但是,您實際上是在建立一個新字串並將其分配回包裝的字串。請注意,text現在以相反的順序儲存原始字串。

由於UserString提供與其超類相同的功能str,因此您可以reversed()開箱即用地執行反向迭代:

>>>
>>> text = ReversibleString("Hello, World!")

>>> # Support reverse iteration out of the box
>>> for char in reversed(text):
...     print(char)
...
!
d
l
r
o
W

,
o
l
l
e
H

>>> text
"Hello, World!"

在這裡,您呼叫reversed()withtext作為引數來提供for迴圈。此呼叫按預期工作並返回相應的迭代器,因為UserString從str. 請注意,呼叫reversed()不會影響原始字串。

以相反的順序對 Python 字串進行排序

您將學習的最後一個主題是如何以相反的順序對字串的字元進行排序。當您不按特定順序處理字串並且需要按逆字母順序對它們進行排序時,這會很方便。

要解決此問題,您可以使用sorted(). 這個內建函式返回一個列表,其中包含輸入可迭代的所有專案。除了輸入可迭代之外,sorted()還接受reverse關鍵字引數。True如果您希望輸入可迭代物件按降序排序,則可以將此引數設定為:

>>>
>>> vowels = "eauoi"

>>> # Sort in ascending order
>>> sorted(vowels)
['a', 'e', 'i', 'o', 'u']

>>> # Sort in descending order
>>> sorted(vowels, reverse=True)
['u', 'o', 'i', 'e', 'a']

當您sorted()使用字串作為引數呼叫並reverse設定為 時True,您會得到一個包含輸入字串字元的倒序或降序列表。由於sorted()返回一個list物件,您需要一種方法將該列表轉換回字串。同樣,您可以.join()像在前面的部分中一樣使用:

>>>
>>> vowels = "eauoi"

>>> "".join(sorted(vowels, reverse=True))
'uoiea'

在此程式碼片段中,您呼叫.join()了一個空字串,它扮演著分隔符的角色。引數 to.join()是呼叫sorted()withvowels作為引數並reverse設定為 的結果True。

您還可以利用sorted()以排序和反向順序遍歷字串:

>>>
>>> for vowel in sorted(vowels, reverse=True):
...     print(vowel)
...
...
u
o
i
e
a

該reverse給的說法sorted()可以讓你排序iterables,包括字串,按降序排列。因此,如果您需要按逆字母順序排序的字串字元,那麼sorted()適合您。

結論

相反的順序反轉和處理字串可能是程式設計中的一項常見任務。Python 提供了一組工具和技術,可以幫助您快速有效地執行字串反轉。在本教程中,您瞭解了這些工具和技術以及如何在字串處理挑戰中利用它們。

在本教程中,您學習瞭如何:

  • 通過切片快速構建反向字串
  • 使用reversed()和建立現有字串的反向副本.join()
  • 使用迭代和遞迴手動建立反向字串
  • 以相反的順序迴圈遍歷字串
  • 使用降序對字串進行排序 sorted()

儘管本主題本身可能沒有很多令人興奮的用例,但瞭解如何反轉字串對於入門級職位的編碼面試很有用。您還會發現掌握反轉字串的不同方法可以幫助您真正概念化 Python 中字串的不變性,這是該語言的一個顯著特性。

 

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章