String

2023 資訊之芽北區 Py 班
感謝去年講師熊老師育霆讓我抄襲修改他的簡報


Recall: what are strings?

我們來複習第一週教過的東西


一段文字

print(type("Hello, world!")) # <class 'str'>

可以用單引號或雙引號包起來

"I love Python" # 用雙引號包起來 'I love Python' # 用單引號包起來

加法(串接)、乘法(重複接)

name = "Madoka" print("Hello, " + name) # Hello, Madoka print(name * 3) # MadokaMadokaMadoka

如果要用引號怎麼辦

print('Hello. It's me.')
  File "<stdin>", line 1
    print('Hello. It's me.')
          ^^^^^^^^^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?


跳脫字元,例如 \n, \'

print('Hello. It\'s me.') # Hello. It's me. print('Never gonna give you up', 'Never gonna let you down', 'Never gonna run around and desert you', sep='\n') """Never gonna give you up Never gonna let you down Never gonna run around and desert you """

多行字串

print("""這幾行 會被 印出來 :)""")

f-string

name = "Kira Yoshikage" age = 33 print("name=", name, "age=", age) # name= Kira Yoshikage age= 33 print(f"name={name} age={age}") # name=Kira Yoshikage age=33 print(f"{name=} {age=}") # name='Kira Yoshikage' age=33

名詞解釋:字元 char

字元:一個字

'a' 'b' 'c'

字串:由一串字元組成

'a' + 'b' + 'c'

補充:Python 沒有 char

在 C, C++, Java 等程式語言中有 char (字元) 資料型別,但在 Python 中沒有 char 資料型別,只有長度為 1 的字串。

char c = 'a'; // C and C++
c = 'a' # Python # is equivalent to c = "a" print(type(c))

list 差不多一樣的地方

在許多語言,string 就是個 list of chars
但 Python 是個特例


加法和乘法運算

加法(串接)、乘法(重複接)

name = "Madoka" print("Hello, " + name) # Hello, Madoka print(name * 3) # MadokaMadokaMadoka

回憶一下 list 的對應操作

print(['c'] + [8, 7] + [6, 3]) # ['c', 8, 7, 6, 3] print([8, 7] * 3) # [8, 7, 8, 7, 8, 7]

比較運算

兩字串是否相等

print("abc" == "abc") # True print("abc" != "abc") # False

比較兩字串字典序

print("abc" < "abd") # True print("abc" < "abcd") # True print("abc" > "def") # False

字典序
簡單來說就是從頭比到尾、都一樣比長度


in, not in

text = 'abc' print('a' in text) # True print('ab' in text) # True print('ac' in text) # False print('ac' not in text) # True

回憶一下 list 的對應操作

list1 = ['a', 'b', 'c'] print('a' in list1) # True print('ab' in list1) # False <---- 注意這個

問題:怎麼比較 'a', 'b' 連續地出現在 list 中?


len

greeting = "Hello" print(greeting) print(len(greeting)) # 5

取第 i 個

greeting = "Hello" print(greeting[0]) # H print(greeting[1]) # e print(greeting[3]) # l print(greeting[-1]) # o print(greeting[5]) # IndexError: string index out of range

這跟 greeting = ['H', 'e', 'l', 'l', 'o'] 的差別是?


Slicing

greeting = "Hello" print(greeting[2:4]) # ll print(greeting[:3]) # Hel print(greeting[2:]) # llo print(greeting[::-1]) # olleH print(greeting[:-3:-1]) # ol

這跟 greeting = ['H', 'e', 'l', 'l', 'o'] 的差別是?


可迭代 Iterable

如果你忘記什麼是 iterable,就是一句話:可以 for 它

greeting = "Hello" for c in greeting: print(c)

小補充 iterable

還不錯的教學文件

我們來看一下 definition 和一些花式用法


跟 list 不一樣的地方


Immutable 不能改值

text = "abcde" text[2] = 'f' # TypeError: 'str' object does not support item assignment

如果要改掉某個字的話只能很麻煩地這樣做

text = "abcde" new_text = text[:2] + "f" + text[3:] print(new_text) # abfde

遠超過範圍的補充:為什麼 string 是 immutable


沒有 immutability 的話可能會發生一些怪事

a = [8, 7, 6, 3] b = a a[2] = 5 print(f"{a=}") # a=[8, 7, 5, 3] print(f"{b=}") # b=[8, 7, 5, 3] # Remark: use id print(f"{id(a)=}") print(f"{id(b)=}")

回憶一下為何我們會看到 a, b 會同時被改值
這是因為他們 reference 到同一個物件


Why is immutability so important (or needed) in JavaScript?

雖然不是 Python 但是核心精神差不多,可以參考看看


課間練習:
輸入一行字,輸出第 \(i\) 行把第 \(i\) 個字元取代成 * 後印出

Input:

abcdefg

Output:

*bcdefg
a*cdefg
ab*defg
abc*efg
abcd*fg
abcde*g
abcdef*

範例解答

text = input() for i in range(len(text)): print(text[:i] + '*' + text[i+1:])

String 的各種操作 (method)


String 的操作有這麼多,我們只能帶到幾個常用的


如果你想知道有沒有什麼簡單的方法達成你想要做的事情,可以試著搜尋看看

  • Python turn string uppercase (把每個字元轉成大寫)
  • Python string first capital (把第一個字轉成大寫)
  • Python string remove blank (把空白拿掉)

replace

就是搜尋與取代

lyrics = """Never gonna give you up Never gonna let you down Never gonna run around and desert you """ modified_lyrics = lyrics.replace("Never", "Always") print(modified_lyrics) print(lyrics)

注意:原本的字串不會被改動


練習一下

  1. 把前面範例中的 "gonna" 取代成 "wanna"
  2. 把前面範例中的 "gonna" 取代成 "wanna",並且把 "you" 取代成 "me"

範例解答

new_lyrics = lyrics.replace("gonna", "wanna")
new_lyrics = lyrics.replace("gonna", "wanna").replace("you", "me")

isdigit & isalpha & isalnum

判斷字串中是否全為數字/字母/數字與字母


print("119".isdigit()) # True print("Hello".isalpha()) # True print("Hello, it's me".isalpha()) # False print("C8763".isalnum()) # True

當然還有很多其他的 is 家族,可以慢慢查


當然,我們可以不用 isdigit 暴力做到這些事情

s = "271828" flag = True for ch in s: if not "0" <= ch <= "9": # if ch not in "0123456789": flag = False print(flag)

但這樣很累欸


練習時間

搭配 isdigitlen 判斷一串數字是否為合法的手機號碼

  1. 十個數字
  2. 前兩位是 09
text = input() # 請開始你的練習

範例解答

text = input() print(len(text) == 10 and text[:2] == "09" and text.isdigit())

strip

new_text = " aaaaa ".strip() print(f"{new_text=}") # new_text='aaaaa'

把字串頭尾的空白拿掉,並且回傳新的字串


lower & upper

將字串中的英文字母全變成小寫或大寫

print("Ko no Dio da!".upper()) # KO NO DIO DA! print("Ko no Dio da!".lower()) # ko no dio da!

一些使用情境:不分大小寫搜尋某個字串,例如說

want_to_search = "Iso" text = "Isometry, isomorphism, isolated" text.lower().find(want_to_search.lower()) # 下一小節是 find

這可以搭配後面的其他東西做練習


find

尋找

lyrics = """Never gonna give you up""" print(lyrics.find("gonna")) # 6

用法

string.find(value, start, end)
  • value: 欲尋找的東東
  • start: 從哪裡開始找,預設是 0
  • end: 找到哪裡結束,預設是到字串結尾

把所有 gonna 找到

lyrics = """Never gonna give you up Never gonna let you down Never gonna run around and desert you """ positions = [] start = 0 value = "gonna" while True: ret = lyrics.find(value, start) if ret == -1: break positions.append(ret) start = ret + len(value) print(positions)

split

把字串切成一堆字串用 list 包起來

text = "Never gonna give you up" splitted = text.split() print(splitted) # ['Never', 'gonna', 'give', 'you', 'up']

範例:計算你輸入了幾個英文單字

words = input().split() print(len(words))

範例:計算一堆數字的平均

numbers = list(map(float, input().split())) print(sum(numbers) / len(numbers))

更詳細的用法

string.split(separator, maxsplit)

separator: 用什麼來切,預設是空白
maxsplit: 最多切幾個


a = "1 2 3 4 5".split() b = "1 2 3 4 5".split(' ') c = "1 2 3 4 5".split('3') print(f"{a=}\n{b=}\n{c=}")

split()split(' ') 其實有一些微妙的差異,細節需要注意一下


這樣會噴錯,為什麼?

d = list(map(int, "1 2  3 4  5".split(' ')))
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_409726/410874544.py in <module>
----> 1 d = list(map(int, "1 2  3 4  5".split(' ')))

ValueError: invalid literal for int() with base 10: ''

因為空字串不能被轉成 int


下面這個就不會出事

d = list(map(int, "1 2  3 4  5".split()))

join

把一堆用 list 包起來的字串合成一個字串

words = ['Never', 'gonna', 'give', 'you', 'up'] print(' '.join(words)) # Never gonna give you up

就是把 split 反過來


用法

string.join(iterable)

stringiterable 裡面的東西全部接起來
iterable 裡面必須是一些字串


''.join(['1', '2', '3']) # 123 ''.join(map(str, range(10))) # 123456789 ', '.join(map(str, range(10))) # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ''.join([1, 2, 3]) # 會噴錯,為什麼?

綜合練習


計算一個英文句子中有幾個字

例如 "Hello, it's me." 有三個, "Never gonna give you up" 有五個字


判斷一個字是否是回文

例如 "ada", "racecar" 是,"sprout" 不是


你有另一個不打標點符號的檳友
總是用一些空白代替逗號,用 XD 代替句號
請你用 Python 幫他改成正確的標點符號

s = '我..熬夜...做..簡報.. 累死..了...XD' \ '熬夜..真的..會...變智障 我該..去睡覺XD' # Ans: '我熬夜做簡報,累死了。熬夜真的會變智障,我該去睡覺。'

感謝竹區講師 Sean64 想出的優質題目


作業

3109
3046


End

Select a repo