一、數(shù)據(jù)類型和變量
數(shù)據(jù)類型
Python3中有六個(gè)標(biāo)準(zhǔn)的數(shù)據(jù)類型:
- Number(數(shù)字):int收夸、float肩祥、bool、complex(復(fù)數(shù))
- String(字符串)
- List(列表)
- Tuple(元組)
- Set(集合)
- Dictionary(字典)
不可變數(shù)據(jù):Number躯护、String、Tuple丽涩。
可變數(shù)據(jù):List棺滞、Set、Dictionary矢渊。
布爾值可以用and继准、or和not運(yùn)算。
and(和運(yùn)算):都為True矮男,運(yùn)算結(jié)果才為True移必。
or(或運(yùn)算):其中一個(gè)為True,運(yùn)算結(jié)果就為True毡鉴。
not(非運(yùn)算):是一個(gè)單目運(yùn)算崔泵,把True變?yōu)镕alse秒赤,F(xiàn)alse變?yōu)門rue:not True
輸出 False
注:字符串可以用'''...'''的格式表示多行。
變量
變量不僅可以是數(shù)字憎瘸,也可以是任何數(shù)據(jù)類型入篮。
變量名必須是大小寫英文、數(shù)字和_的組合幌甘,且不能是數(shù)字開(kāi)頭潮售。
同一個(gè)變量可以反復(fù)賦值,可以是不同類型的變量锅风。
a = "abc"
python解釋器做的事情:
1.在內(nèi)存中創(chuàng)建了一個(gè)"abc"的字符串酥诽;
2.在內(nèi)存中創(chuàng)建了一個(gè)名為a的變量,并指向'abc'皱埠。
把變量a賦值給另一個(gè)變量b:
常量
就是不能變的變量肮帐,例如數(shù)學(xué)常數(shù)Π。在Python中漱逸,通常全部大寫的變量名表示常量:
PI = 2.14159265339
但PI仍然是一個(gè)變量
整數(shù)的除法為什么也是精確的泪姨。在Python中有兩種觸發(fā),一種是/
/
除法計(jì)算結(jié)果是浮點(diǎn)數(shù)饰抒,即使是兩個(gè)整數(shù)恰好整除肮砾,結(jié)果也是浮點(diǎn)數(shù)。
還有一種是//
,稱為地板除袋坑,兩個(gè)整數(shù)的除法仍然是整數(shù)仗处,永遠(yuǎn)都整數(shù),不管除不除得盡枣宫。所以要做精確除法使用/
婆誓,因?yàn)?code>//只取整數(shù)部分。
余數(shù)運(yùn)算%
注:對(duì)于變量x = y
是把x
指向真正得對(duì)象也颤,該對(duì)象是變量y
所指向的洋幻。隨后對(duì)變量y
的賦值不影響變量x
的指向。
Python的整數(shù)沒(méi)有大小限制翅娶。Python的浮點(diǎn)數(shù)也沒(méi)有大小限制文留,但是超出一定范圍就直接表示為inf
(無(wú)限大)
二、字符串和編碼
字符編碼
字符串是數(shù)據(jù)類型竭沫,但是字符串比較特殊的是有一個(gè)編碼問(wèn)題燥翅。
因?yàn)橛?jì)算機(jī)只能處理數(shù)字,如果處理文本蜕提,就必須先把文本轉(zhuǎn)換為數(shù)字才能處理森书。最早的計(jì)算機(jī)在設(shè)計(jì)時(shí)采用8個(gè)比特(bit)作為一個(gè)字節(jié)(byte),所以,一個(gè)字節(jié)能表示的最大的整數(shù)就是255(二進(jìn)制11111111=十進(jìn)制255)凛膏,如果要表示更大的整數(shù)杨名,就必須用更多的字節(jié)。比如兩個(gè)字節(jié)可以表示的最大整數(shù)是65535译柏,4個(gè)字節(jié)可以表示的最大整數(shù)是4294967295镣煮。
在計(jì)算機(jī)內(nèi)存中,統(tǒng)一使用Unicode編碼鄙麦,當(dāng)需要保存到硬盤或需要傳輸?shù)臅r(shí)候,就轉(zhuǎn)換為UTF-8編碼镊折。
用記事本編輯的時(shí)候胯府,從文件讀取的UTF-8字符被轉(zhuǎn)換成Unicode字符到內(nèi)存中,編輯完成后恨胚,保存的時(shí)候再把Unicode轉(zhuǎn)換為UTF-8保存到文件骂因。
Python的字符串
在最新的Python 3
版本中,字符串是以Unicode
編碼的赃泡,也就是說(shuō)寒波,Python
的字符串支持多語(yǔ)言。
獲取字符碼:
單個(gè)字符:ord()
例:
ord("A") #65
ord("中") #20013
把編碼轉(zhuǎn)換成對(duì)應(yīng)的字符:chr()
例:
chr(20013) #中
str轉(zhuǎn)bytes
由于Python的字符串類型是str
,在內(nèi)存中以Unicode
表示升熊,一個(gè)字符串對(duì)應(yīng)若干個(gè)字節(jié)(bytes
)俄烁。
所以對(duì)于bytes類型的數(shù)據(jù)自帶b前綴的單引號(hào)或雙引號(hào)表示:
x = b'ABC'
"ABC"和b"ABC"是不一樣的。
以Unicode
表示的str
通過(guò)encode()
方法可以編碼為指定的bytes
级野,例如:
英文的str可以用
ASCII
編碼為bytes
页屠,內(nèi)容是一樣的。含中文的str可以用UTF-8編碼為bytes蓖柔。含有中文的str無(wú)法用ASCII編碼辰企,會(huì)報(bào)錯(cuò)。bytes轉(zhuǎn)str
要把
bytes
變?yōu)?code>str况鸣,就需要用decode()
方法牢贸。如果bytes
中包含無(wú)法解碼的字節(jié)济榨,decode()
方法會(huì)報(bào)錯(cuò)迫摔。如果
bytes
中只有一小部分無(wú)效的字節(jié)惧盹,可以傳入errors='ignore'
忽略錯(cuò)誤的字節(jié)扔字。
獲取str的字符長(zhǎng)度巨柒,可以用len()
函數(shù),也可以用來(lái)計(jì)算字節(jié)數(shù)畅哑。
Python的源代碼是一個(gè)文本文件蒙保,所以在源碼中包含中文的時(shí)候龄糊,在保存源碼的時(shí)玩焰,就要指定UTF-8編碼由驹。在文件開(kāi)頭寫這兩句:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
第一行注釋是為了告訴Linux/OS X系統(tǒng),這是一個(gè)Python可執(zhí)行程序,Windows會(huì)忽略這行注釋蔓榄。
第二行就是指定文件是UTF-8編碼并炮,否則在源碼中方寫的中文輸可能會(huì)亂碼。
格式化
-
%
運(yùn)算符
%
運(yùn)算符用來(lái)格式化字符串甥郑。在字符串內(nèi)部逃魄,%s表示用字符串替換,%d表示用整數(shù)替換澜搅,有幾個(gè)%?占位符伍俘,后面就跟幾個(gè)變量或者值,順序要對(duì)應(yīng)好勉躺。如果只有一個(gè)%?癌瘾,括號(hào)可以省略。
常見(jiàn)占位符:
其中饵溅,格式化整數(shù)和浮點(diǎn)數(shù)還可以指定是否補(bǔ)0和整數(shù)與小數(shù)的位數(shù):
不確定用什么妨退,%s
永遠(yuǎn)起作用,會(huì)把任何數(shù)據(jù)類型轉(zhuǎn)換成字符串:
>>> 'Age: %s. Gender: %s' % (25, True)
'Age: 25. Gender: True'
%
是普通字符串蜕企,需要轉(zhuǎn)義用%%
表示
- format()
另一種格式化字符串的方法是使用字符串的format()方法咬荷,它會(huì)用傳入的參數(shù)依次替換字符串內(nèi)的占位符{0}、{1}……轻掩,不過(guò)這種方式寫起來(lái)比%要麻煩得多:
>>> 'Hello, {0}, 成績(jī)提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成績(jī)提升了 17.1%'
- f-string
最后一種格式化字符串的方法是使用以f開(kāi)頭的字符串幸乒,稱之為f-string,它和普通字符串不同之處在于放典,字符串如果包含{xxx}逝变,就會(huì)以對(duì)應(yīng)的變量替換:
>>> r = 2.5
>>> s = 3.14 * r ** 2
>>> print(f'The area of a circle with radius {r} is {s:.2f}')
The area of a circle with radius 2.5 is 19.62
上述代碼中,{r}被變量r的值替換奋构,{s:.2f}被變量s的值替換壳影,并且:后面的.2f指定了格式化參數(shù)(即保留兩位小數(shù)),因此弥臼,{s:.2f}的替換結(jié)果是19.62宴咧。
練習(xí)
小明的成績(jī)從去年的72分提升到了今年的85分,請(qǐng)計(jì)算小明成績(jī)提升的百分點(diǎn)径缅,并用字符串格式化顯示出'xx.x%'掺栅,只保留小數(shù)點(diǎn)后1位:
s1 = 72
s2 = 85
r = ???
print("xxx" % r)
解題:
s1 = 72
s2 = 85
r = (s2 - s1)/s1*100
print(r)
#%運(yùn)算符
print("小明的成績(jī)提高了 %.1f %%" % r)
#format
print("小明的成績(jī)提高了 {0:.1f}%".format(r))
#f-string
print(f"小明的成績(jī)提高了 {r:.1f} %")
三、list和tuple
list數(shù)組 []
list是一種有序集合纳猪,可以隨時(shí)添加和刪除其中的元素氧卧。
>>> classmates = ["xiaoming","xiaofang","xiaoli"]
>>> classmates
['xiaoming', 'xiaofang', 'xiaoli']
- 獲取元素個(gè)數(shù)
len()
>>> len(classmates)
3
- 通過(guò)索引來(lái)獲取元素,可以是負(fù)數(shù)氏堤,-1就是最后一個(gè)沙绝,以此類推
>>> classmates[0]
'xiaoming'
索引超出范圍會(huì)報(bào)錯(cuò) IndexError
- 添加元素
append()
>>> classmates.append("xiaoxiao")
>>> classmates
['xiaoming', 'xiaofang', 'xiaoli', 'xiaoxiao']
- 把元素插入指定位置
insert(索引,插入元素)
>>> classmates.insert(0,"xiaoying")
>>> classmates
['xiaoying', 'xiaoming', 'xiaofang', 'xiaoli', 'xiaoxiao']
- 刪除末尾元素
pop()
>>> classmates.pop()
'xiaoxiao'
>>> classmates
['xiaoying', 'xiaoming', 'xiaofang', 'xiaoli']
- 刪除指定位置的元素
pop(i)
>>> classmates.pop(1)
'xiaoming'
>>> classmates
['xiaoying', 'xiaofang', 'xiaoli']
- 重新賦值
>>> classmates[2] = "xiaoxiao"
>>> classmates
['xiaoying', 'xiaofang', 'xiaoxiao']
- list的元素可以是不同數(shù)據(jù)類型,也可以是多維數(shù)組
>>> L = ["string",123,True]
tuple元組 ()
tuple和list非常相似,但是一旦初始化就不能修改闪檬,比如:
>>> classmates = ("xiaoying","xiaofang","xiaoxiao")
但是tuple的元素不能變了星著,沒(méi)有append(),insert()這些方法。
- tuple存在的意義粗悯?
因?yàn)閠uple不可變虚循,所以代碼更安全。所以能用tuple就不用list - 空的tuple
>>> t = ()
- 定義一個(gè)元素的tuple
>>> t = (1)
>>> t
1
定義的不是tuple样傍,是1這個(gè)數(shù)横缔,因?yàn)槔ㄌ?hào)既可以表示tuple,又可以表示數(shù)學(xué)公式的(),這就有歧義了铭乾。所以剪廉,Python規(guī)定,這種情況下炕檩,按小括號(hào)進(jìn)行計(jì)算,所以結(jié)果是1捌斧。
所以定義tuple定義時(shí)必須加上一個(gè)逗號(hào),
笛质,來(lái)消除歧義。
>>> t = (1,)
>>> t
(1,)
>>>
- tuple的每個(gè)元素的指向不變
即指向了'a'
,就不能改成指向'b'
,指向一個(gè)list捞蚂,就不能改成指向其他對(duì)象妇押,但指向的這個(gè)list本身時(shí)可變的!
>>> t = ("a","b",["A","B"])
>>> t[2][0] = "X"
>>> t[2][1] = "Y"
>>> t
('a', 'b', ['X', 'Y'])
練習(xí)
請(qǐng)用索引取出下面的list的指定元素:
# -*- coding: utf-8 -*-
L = [
['Apple', 'Google', 'Microsoft'],
['Java', 'Python', 'Ruby', 'PHP'],
['Adam', 'Bart', 'Lisa']
]
# 打印Apple:
print(?)
# 打印Python:
print(?)
# 打印Lisa:
print(?)
解答:
print(L[0][0])
print(L[1][1])
print(L[2][-1])
四姓迅、條件判斷
-
if
else
else if
(縮寫elif
)
注意有冒號(hào):
語(yǔ)法:
if <條件判斷1>:
<執(zhí)行1>
elif <條件判斷2>:
<執(zhí)行2>
elif <條件判斷3>:
<執(zhí)行3>
else:
<執(zhí)行4>
例:
age = 3
if age >= 18:
print("adult")
elif age >= 6:
print("teenager")
else:
print("kid")
- 結(jié)合輸入
input()
input()
返回的數(shù)據(jù)類型是str敲霍,str不能和整數(shù)比較,必須先轉(zhuǎn)化成整數(shù)丁存。
int()
函數(shù)肩杈,將其他類型轉(zhuǎn)換成整數(shù),轉(zhuǎn)換之后就只能輸入整數(shù)了解寝,不然會(huì)報(bào)錯(cuò)扩然。
age = 3
if age >= 18:
print("adult")
elif age >= 6:
print("teenager")
else:
print("kid")
s = input("生日:")
birth = int(s)
if birth < 2000:
print("00前")
else:
print("00后")
練習(xí)
小明身高1.75,體重80.5kg聋伦。請(qǐng)根據(jù)BMI公式(體重除以身高的平方)幫小明計(jì)算他的BMI指數(shù)夫偶,并根據(jù)BMI指數(shù):
低于18.5:過(guò)輕
18.5-25:正常
25-28:過(guò)重
28-32:肥胖
高于32:嚴(yán)重肥胖
用 if-elif判斷并打印結(jié)果:
height = 1.75
weight = 80.5
bmi = ???
if ???:
pass
解答:
height = 1.75
weight = 80.5
bmi = weight/height**2 #**n表示n次平方
if bmi < 18.5:
print("過(guò)輕")
elif bmi <= 25:
print("正常")
elif bmi <= 28:
print("過(guò)重")
elif bmi <= 32:
print("肥胖")
else:
print("嚴(yán)重肥胖")
五、循環(huán)
-
for ... in
循環(huán)
names = ["xiaoying","xiaofang","xiaoxiao"]
for name in names:
print(name)
①循環(huán)相加
sum = 0
for num in [1,2,3,4,5,6,7,8,9,10]:
sum = sum + num
print(sum)
②通過(guò)range()
函數(shù)生成整數(shù)序列,再用list()
轉(zhuǎn)換成list觉增。
>>> list(range(5))
[0, 1, 2, 3, 4]
計(jì)算 1-100的整數(shù)相加:
sum = 0
for x in list(range(101)):
sum = sum + x
print(sum)
-
while
循環(huán)
只要條件滿足兵拢,就不斷循環(huán),條件不滿足時(shí)就退出循環(huán)逾礁。
計(jì)算100以內(nèi)的奇數(shù)之和:
sum = 0
x = 99
while x > 0:
sum = sum + x
x = x - 2
print(sum)
- 練習(xí)
請(qǐng)利用循環(huán)依次對(duì)list中的每個(gè)名字打印Hello,xxx!
L = ['Bart', 'Lisa', 'Adam']
解答:
L = ['Bart', 'Lisa', 'Adam']
for name in L:
print("Hello,"+name+"!")
-
break
提前退出循環(huán)
打印1-100之間的1-10
n = 1
while n <= 100:
if n > 10: #當(dāng)n>10的時(shí)候说铃,就會(huì)退出循環(huán)
break
print(n)
n = n + 1
-
continue
跳出當(dāng)前循環(huán),進(jìn)入下一次循環(huán)
打印 1-10之間的奇數(shù)
n = 0
while n < 10:
n = n + 1
if n % 2 == 0: #當(dāng)n為偶數(shù)時(shí)
continue
print(n)
六、dict和set
dict字典
Python內(nèi)置了字典:dict的支持截汪,dict全稱dictionary疾牲,在其他語(yǔ)言中也稱為map,使用鍵-值(key-value)存儲(chǔ)衙解,具有極快的查找速度阳柔。
例:
>>> d = {"xiaoming":98,"xiaofang":78,"xiaoxiao":99}
>>> d["xiaoming"]
98
- 寫入值,通過(guò)key
>>> d["xiaoqian"] = 87
>>> d
{'xiaoming': 98, 'xiaofang': 78, 'xiaoxiao': 99, 'xiaoqian': 87}
- 獲取值
如果key不存在的話會(huì)報(bào)錯(cuò)
>>> d["xiaoqian"]
87
- 避免key不存在的錯(cuò)誤
①通過(guò)in
判斷key是否存在
>>> "xiao" in d
False
②通過(guò)dict提供的get()
方法蚓峦,如果key不存在舌剂,就返回None
(不會(huì)顯示),或者自己指定的值
>>> d.get("xiao",-1)
-1
- 刪除key,
pop(key)
>>> d.pop("xiaoxiao")
99
>>> d
{'xiaoming': 98, 'xiaofang': 78, 'xiaoqian': 87}
注:dict存放的順序可key放入的順序沒(méi)有關(guān)系暑椰。
和list比較霍转,dict有以下幾個(gè)特點(diǎn):
1.查找的插入的速度快,不會(huì)隨著key的增加而變慢一汽;
2.占用空間小避消。浪費(fèi)內(nèi)存少。
所以dict是用空間來(lái)?yè)Q取時(shí)間的一種方法召夹。
注:dict的key必須是不可變對(duì)象岩喷。
因?yàn)閐ict根據(jù)key計(jì)算value的存儲(chǔ)位置,如果每次計(jì)算相同的key得出的結(jié)果不同监憎,那dict內(nèi)部就完全混亂了纱意。這個(gè)通過(guò)key計(jì)算位置的算法稱為哈希算法(Hash)。
要保證hash的正確性鲸阔,作為key的對(duì)象就不能變偷霉。在Python中,字符串褐筛、整數(shù)等都是不可變的类少,因此,可以放心地作為key死讹。而list是可變的瞒滴,就不能作為key:
set
set和dict相似,也是一組key的集合赞警,但不存儲(chǔ)value妓忍。由于key不能重復(fù),所以在set中愧旦,沒(méi)有重復(fù)的key世剖。
要?jiǎng)?chuàng)建一個(gè)set,需要提供一個(gè)list作為輸入集合:
>>> s = set([1,2,3])
>>> s
{1, 2, 3}
注:傳入的是[],顯示的{}只是告訴你這個(gè)set內(nèi)部有這幾個(gè)元素笤虫,顯示的順序也不代表set是有序的旁瘫。
重復(fù)的元素在set中自動(dòng)過(guò)濾:
>>> s = set([1,2,4,5,7,8,2,5,7])
>>> s
{1, 2, 4, 5, 7, 8}
- 添加元素
add(set)
>>> s.add(9)
>>> s
{1, 2, 4, 5, 7, 8, 9}
- 刪除元素 remove(key)
>>> s.remove(9)
>>> s
{1, 2, 4, 5, 7, 8}
set可以看作是數(shù)學(xué)意義上的無(wú)序和無(wú)重復(fù)的集合祖凫,所以可以做交集、并集操作:
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}
set和dict的原理是一樣的酬凳,不可以放入可變對(duì)象惠况,因?yàn)闊o(wú)法判斷兩個(gè)可變對(duì)象是否相等。也就無(wú)法保證set內(nèi)部不會(huì)有重復(fù)元素宁仔,會(huì)報(bào)錯(cuò)稠屠。區(qū)別在于set沒(méi)有存儲(chǔ)對(duì)應(yīng)的value。
- 不可變對(duì)象
str不可變對(duì)象翎苫,list可變對(duì)象权埠。
對(duì)可變對(duì)象進(jìn)行操作,內(nèi)容有可能會(huì)發(fā)生變化煎谍,而不可變對(duì)象是不會(huì)有改變的攘蔽。
>>> a = ["c","b","a"]
>>> a.sort()
>>> a
['a', 'b', 'c']
>>> a = "abc"
>>> a.replace("a","A")
'Abc'
>>> a
'abc'
>>>
為什么a的值仍然是"abc"呢?
因?yàn)?a是變量呐粘,指向的是"abc"這個(gè)字符串對(duì)象满俗。
而replace()方法作用在"abc"這個(gè)對(duì)象上會(huì)創(chuàng)建一個(gè)新的字符串"Abc"并返回,"abc"這個(gè)對(duì)象是不可變的作岖,所以用另一個(gè)變量b賦值就讓b指向"Abc"了漫雷。
>>> a = "abc"
>>> b = a.replace("a","A")
>>> a
'abc'
>>>b
'Abc'
結(jié):
在dict中的key-value存儲(chǔ)結(jié)構(gòu),選擇不可變對(duì)象作為key很重要鳍咱,最常用的key是字符串。
試一試把(1,2,3)和(1,[2,3])放入dict或set中与柑,并解釋結(jié)果谤辜。
>>> key = (1,2,3)
>>> d[key] = "a dict"
>>> d
{'xiaoming': 98, 'xiaofang': 78, 'xiaoqian': 87, (1, 2, 3): 'a dict'}
>>> key = (1,[2,3])
>>> d[key] = "a dict"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> s.add((1,2,3))
>>> s
{1, 2, 4, 5, 7, 8, (1, 2, 3)}
>>> s.add((1,[2,3]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
解釋:
tuple是不可變對(duì)象,list是可變對(duì)象价捧,在set和dict中都不可以放入可變對(duì)象丑念,因?yàn)闊o(wú)法判斷兩個(gè)可變對(duì)象是否相等,無(wú)法判斷key是否是唯一的了结蟋。