天天看點

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

摘要:以相反的順序反轉和處理字元串可能是程式設計中的一項常見任務。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]

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

以相反順序疊代字元串的最可讀和 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()傳回一個疊代器,循環在記憶體使用方面也很有效。

對字元串執行反向疊代的第二種方法是使用您之前在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 中字元串的不變性,這是該語言的一個顯着特性。

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