一.字符串的表示方式
- 雙引號或者單引號中的數據,就是字符串
- 如果使用一對引號來定義字符串,當出現符號沖突時可以使用轉義字符
- 使用三個單引號、雙引號定義的字符串可以包裹任意文本
二.字符串的賦值和地址問題
- s1、s2、s3的地址相同 / s4的地址不同
s1 = 'hello'
s2 = s1 #s1將地址賦給s2,這樣s1和s2指向的是常量池中同一個字符串
s3 = "hello" #hello這個字符串在常量池中已經存在,所以將地址給s3,那么s3和s1、s2地址相同
s4 = 'hello1' #常量池中沒有hello1這個字符串,會在常量池中新開辟一個地址,賦給s4
id(變量):id()函數用於將變量的內存地址得到轉化為我們能看懂的地址
變量a is 變量b:is用於比較地址是否相同
- 當沒有任何指針指向字符串,字符串就會被回收
三.字符串的索引機制
-
正向取索引(str = 'abcde')
0 ~ len(str)-1
從左到右索引依次為:0 1 2 3 4
-
反向取索引
-len(str) ~ -1
從右往左索引依次為:-1 -2 -3 -4 -5
有時候字符串長度很長,如果正向去取會很麻煩,但是如果倒着取,那么倒數第一個字符下標就為-1,向左依次為-2、-3、-4...
四.字符串相關操作
1.獲取字符串長度
- len(字符串)
2.截取指定字符串
-
依據字符串索引機制,按索引取
str = 'abcdef' print(str[1]) #b print(str[-2]) #e
3.截取多個字符串(切片)
-
切片用於字符串和列表
-
格式:
字符串變量[start:end:step]
- 步長省略
-
[start:end] #左閉右開
-
正向索引
str = 'abcde' print(str[1:3]) #bc
-
反向索引
str = 'abcde' print(str[-4:-2]) #bc 也是左閉右開
-
正反索引可以混用
str = 'abcde' print(str[1:-2]) #bc
-
-
[:end] #默認從0開始
str = 'abcde' print(str[:3]) #abc print(str[:-1]) #abcd
-
[start:] #從start開始取到最后
str = 'abcde' print(str[2:]) #cde print(str[-2:]) #de
-
[:] #從頭取到尾
str = 'abcde' print(str[:]) #abcde
注意:此時用切片的方式取出全部字符串和原字符串地址一樣
-
list1[1:1] = [2,3] #比較特殊,根據底層原碼大致理解為先看等號后面的列表長度n,然后再1:切片的位置之后含切片位置的所有元素后移n位,然后將等號后面的列表中的元素依次插入
list1 = [1,4] list1[1:1] = [2,3,{1,2},(1,2),{'a':1},'str'] print(list1) #[1, 2, 3, {1, 2}, (1, 2), {'a': 1}, 'str', 4]
注意只有列表的切片才能這樣使用!!
- 加上步長
-
[start : end : step]
str = 'abcdef' print(str[1:-1:2]) #bdf
-
[ : end : step]
str = 'abcdef' print(str[:-1:3]) #ad
-
[start : : step]
str = 'abcdef' print(str[2::2]) #ce
-
[ : : step]
str = 'abcdef' print(str[::-1]) #fedcba print(str[::-2]) #fdb
-
[ : : : ]
str = 'abcdef' print(str[::]) #abcdef
注意:步長如果為正表示從左到右取,如果步長為負數表示從右往左反着取
而且一定注意:當步長為負數時,說明從右往左反着取,那么start的索引值一定要在end索引值的后面!!
-
易錯舉例:
str = 'abcdef' print(str[1:-1:-2]) #這樣會取不到任何值!!!!因為step為-2表示倒着取,起始索引為1,倒着取下一個為 0,這樣就永遠到不了-1索引,所以取不到任何值 print(str[-1:1:-2]) #這樣就可以取到值--fd (還是左閉右開) print(str[5::-1]) #從索引為5開始往前取--fedcba
4.查找(獲取指定字符下標)
-
find:從左向右查找,只要遇到一個符合要求的則返回位置值。如果沒有找到任何符合要求的則返回-1
path = 'https://www.baidu.com/img/dong_e39494cd9293c9d9cc9d0gk303945.gif' i = path.find('_') print(path[i+1:]) #取_后面的字符串 mystr = '今天天氣好晴朗,處處好風光呀好風光' print(mystr.find('好風光')) #10 '好風光'第一次出現時,'好'所在的位置 print(mystr.find('風光',1,10)) #-1 從下標1開始到12查找"風光",未找到,返回 -1
-
rfind:類似於 find()函數,不過是從右邊開始查找。如果沒有找到任何符合要求的則返回-1
mystr = '今天天氣好晴朗,處處好風光呀好風光' print(mystr.rfind('好')) #14
-
index:跟find()方法一樣,只不過,find方法未找到時,返回-1,而str未找到時,會報一個異常
-
rindex:類似於 index(),不過是從右邊開始。
5.判斷
-
startswith:判斷字符串是否以指定內容開始。
mystr = '今天天氣好晴朗,處處好風光呀好風光' print(mystr.startswith('今')) # True
-
endswith:判斷字符串是否以指定內容結束。
mystr = '今天天氣好晴朗,處處好風光呀好風光' print(mystr.endswith('好風光')) #True
-
isalpha:判斷字符串是否是純字母
mystr = 'hello world' print(mystr.isalpha()) # False 因為中間有空格
-
isdigit:判斷一個字符串是否是純數字,只要出現非0~9的數字,結果就是False.
-
isalnum:判斷是否由數字和字母組成。只要出現了非數字和字母,就返回False.
-
isspace:如果 mystr 中只包含空格,則返回 True,否則返回 False.
-
isupper:判斷是否全部是大寫字母
-
islower:判斷是否全部是小寫字母
6.統計出現次數
-
count:返回 str在start和end之間 在 mystr里面出現的次數。
mystr = '今天天氣好晴朗,處處好風光呀好風光' print(mystr.count('好')) #3 '好'字出現三次
7.替換
- replace:替換字符串中指定的內容。如果沒有指定次數則全部替換;如果指定次數count,則替換不會超過count次。
mystr = '今天天氣好晴朗,處處好風光呀好風光'
newstr = mystr.replace('好', '壞')
print(mystr) # 今天天氣好晴朗,處處好風光呀好風光 原字符串未改變!
print(newstr) # 今天天氣壞晴朗,處處壞風光呀壞風光 得到的新字符串里,'好'被修改成了'壞'
newstr = mystr.replace('好','壞',2) # 指定了替換的次數
print(newstr) # 今天天氣壞晴朗,處處壞風光呀好風光 只有兩處的'好'被替換成了'壞'
注意:替換完的新字符串不會覆蓋原字符串
- 疑問:如果要替換多個怎么辦-------1.正則表達式 2.列表加循環 (后面會詳解)
8.切割(分割字符串)
- split:以指定字符串為分隔符切片,如果 maxsplit有指定值,則僅分隔 maxsplit+1 個子字符串。返回的結果是一個列表。
mystr = '今天天氣好晴朗,處處好風光呀好風光'
result = mystr.split() # 沒有指定分隔符,默認使用空格,換行等空白字符進行分隔
print(result) #['今天天氣好晴朗,處處好風光呀好風光'] 沒有空白字符,所以,字符串未被分隔
result = mystr.split('好') # 以 '好' 為分隔符
print(result) # ['今天天氣', '晴朗,處處','風光呀,'風光']
result = mystr.split("好",2) # 以 '好' 為分隔符,最多切割成3份
print(result) # ['今天天氣', '晴朗,處處', '風光呀好風光']
- rsplit:用法和split基本一致,只不過是從右往左分隔。
- splitlines(了解):按照行分隔,返回一個包含各行作為元素的列表。
mystr = 'hello \nworld'
mystr = '''第一行
第二行
第三行
'''
print(mystr.splitlines())
- partition(了解):把mystr以指定str分割成三部分,str前,str和str后,三部分組成一個元組
mystr = '今天天氣好晴朗,處處好風光呀好風光'
print(mystr.partition('好')) # ('今天天氣', '好', '晴朗,處處好風光呀好風光')
- rpartition(了解):類似於 partition()函數,不過是從右邊開始.
9.大小寫轉化
- title:每個單詞的首字母大寫。
mystr = 'hello world'
print(mystr.title()) # Hello World
- capitalize:第一個單詞的首字母大寫。
- upper:所有都變成大寫。
- lower:所有都變成小寫。
10.空格處理
-
strip:刪除兩端的空白字符
str = ' he llo ' print(str.strip()) #he llo
-
lstrip:刪除 mystr 左邊的空白字符
-
rstrip:刪除 mystr 右邊的空白字符
-
ljust:返回指定長度的字符串,並在右側使用空白字符補全(左對齊)。
-
rjust:返回指定長度的字符串,並在左側使用空白字符補全(右對齊)。
-
center:返回指定長度的字符串,並在兩端使用空白字符補全(居中對齊)
str = 'hello' print(str.center(10)) # hello 兩端加空格,讓內容居中
11.字符串拼接
-
join:把參數進行遍歷,取出參數里的每一項,然后再在后面加上mystr
一般用於列表--->返回一個字符串
mystr = 'a' print(mystr.join('hxmdq')) #haxamadaq 把hxmd一個個取出,並在后面添加字符a. 最后的q保留,沒有加a print(mystr.join(['hi','hello','good'])) #hiahelloagood
-
+號:正常拼接字符串
12.字符串format格式化
-
概念
str.format()
方法通過字符串中的大括號{}
來識別替換字段replacement field
,從而完成字符串的格式化。 -
字段名的種類
-
1.省略字段名:
{}
注意:大括號個數可以少於位置參數的個數,反之不然
name = '小明' age = 18 print('我叫{},今年{}歲。'.format(name, age)) # 大括號個數可以少於位置參數的個數 print('我愛吃{}和{}。'.format('香蕉', '蘋果', '大鴨梨')) # 大括號個數多於位置參數的個數則會報錯 # print('我還吃{}和{}。'.format('西紅柿')) """ IndexError: tuple index out of range """
-
2.使用非負十進制整數
{0}
-
數字必須是大於等於 0 的整數。
-
帶數字的替換字段可以重復使用
# 數字形式的簡單字段名可以重復使用。 name = '阿香' age = 17 print('我愛{0}。\n她今年{1}。\n我也愛{0}。'.format(name, age)) """ 我愛阿香。 她今年17。 我也愛阿香。 """
-
數字形式的簡單字段名相當於把 format 中的所有位置參數整體當作一個元組,通過字段名中的數字進行取值。即 {0} 等價於 tuple[0],所以大括號內的數字不能越界。
# 體會把所有位置參數整體當成元組來取值 print('阿香愛吃{1}、{3}和{0}。'.format( '榴蓮', '臭豆腐', '皮蛋', '鯡魚罐頭', '螺獅粉')) """ 阿香愛吃臭豆腐、鯡魚罐頭和榴蓮。 """
-
-
3.變量名{name}
-
使用變量名形式的簡單字段名傳遞關鍵字參數。
-
使用變量名關鍵字參數的位置可以隨意調換。
-
但是注意:變量名做參數時一定要在format中賦值
# 關鍵字參數的順序可以隨意調換 print('我大哥是{name},今年{age}歲。'.format(age=20, name='阿飛')) """ 我大哥是阿飛,今年20歲。 """
-
-
4.簡單字段名的混用
-
混合使用數字形式和變量名形式的字段名,可以同時傳遞位置參數和關鍵字參數。
-
關鍵字參數必須位於位置參數之后。
# 關鍵字參數必須位於位置參數之后 print('這是一個關於{0}、{1}和{girl}的故事。'.format( '小明', '阿飛', girl='阿香')) """ 這是一個關於小明、阿飛和阿香的故事。 """
-
混合使用時可以省略數字。
# 數字也可以省略 print('這是一個關於{}、{}和{girl}的故事。'.format( '小明', '阿飛', girl='阿香'))
-
省略字段名
{}
不能和數字形式的字段名{非負整數}
同時使用。# 但是省略字段名不能和數字形式的字段名同時出現 # print('這是一個關於{}、{1}和{girl}的故事。'.format( # '小明', '阿飛', girl='阿香')) """ ValueError: cannot switch from automatic field numbering to manual field specification """
-
-
例題1:利用切片和字符串方法
- 模擬上傳文件,鍵盤輸入上傳文件的名稱(不帶后綴名),判斷文件名是否大於6位以上,拓展名是否是:jpg、gif、png格式,如果不是則提示上傳失敗,如果名字不滿足條件,而拓展名滿足條件則隨機生成一個6位數字組成的文件名,打印成功上傳xxx.png等
import random
document = input('請輸入上傳文件名稱:')
index = document.rfind('.')
if document.endswith('.jpg') or document.endswith('.gif') or document.endswith('.png'):
if len(document[index - 1::-1]) >= 6: #或者寫[:index]
print('打印成功上傳%s' % document)
else:
newName = random.randint(100000,999999) #randint()是左閉右閉的
print('打印成功上傳%d%s' % (newName,document[index:]))
else:
print('格式不滿足上傳失敗') 1748
改進:
- 隨機生成一個由字母和數字組成的6位文件名 (很牛的方法--驗證碼就是這么來的)
filename = '' #表示filename是空的字符串類型的變量
s = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' #所有可能的情況
for i in range(6):
index = random.randint(0,len(s) - 1) #隨機取一個整數,去表示s中的索引
filename += s[index] #將從s字符串中取出的元素拼接成6位字符串
print(filename)
例題2:字符串判斷
'''
admin123 19182134110 123456
用戶名或者手機號登錄+密碼
用戶名:全部小寫,首字母不能是數字,長度必須6位以上
手機號碼:純數字、長度11
密碼必須是6位數字
以上符合條件則進入下層驗證:
判斷用戶名+密碼 是否正確,成功或失敗
'''
flag = True
error = 0
while flag:
if error < 3:
name = input('請輸入用戶名或手機號:')
if (name.islower() and not name[0].isdigit() and len(name) > 6) or (name.isdigit() and len(name) == 11):
while error < 3:
password = input('請繼續輸入密碼:')
if password.isdigit() and len(password) == 6:
if (name == '19182134110' or name == 'admin123') and password == '123456':
print('登錄成功!')
flag = False
break
else:
print('賬號或密碼錯誤!(還有%d次嘗試機會)' % (2 - error))
error += 1
break
else:
print('密碼必須是6位!(還有%d次嘗試機會)' % (2 - error))
error += 1
break
else:
print('用戶名或手機輸入格式錯誤')
else:
print('賬號鎖定!')
flag = False