1.本章學習心得、體會
學習方法論:輸入--輸出---糾正
堅持 堅持 再堅持
2.學習到的知識點總結。
學習內容:
Python 3最重要的新特性大概是對文字和二進位制資料做了更為清晰地區分。文字總是Unicode,由str型別表示,二進位制資料由bytes型別表示。Python 3不會以任意隱式的方式混用str和butes,正因為此,python 3不能拼接字串和字元包,也無法在位元組包裡搜尋字串,不能講字串傳入引數為位元組包的函式。
str 轉為 bytes – encode
>>> "fgf".encode('utf-8')
b'fgf'
>>> "活著".encode('utf-8') # utf-8編碼轉為二進位制
b'\xe6\xb4\xbb\xe7\x9d\x80'
# python 2.x 不指定編碼,則使用系統編碼
# python 3.x 不指定編碼,則使用utf-8
bytes 轉為 str – decode
>>> b'\xe6\xb4\xbb\xe7\x9d\x80'.decode('utf-8')
'活著' # 二進位制轉為utf-8編碼
python 資料傳輸,都是以二進位制資料傳。
二進位制和十六進位制的轉化
十六進位制:二進位制每4位表示16進位制的一位。對應關係如圖
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
0000 |
0001 |
0010 |
0011 |
0100 |
0101 |
0110 |
0111 |
1000 |
1001 |
1010 |
1011 |
1100 |
1101 |
1110 |
1111 |
二進位制轉換成十六進位制的方法是,取四合一法,即從二進位制的小數點為分界點,向左(或向右)每四位取成一位
1011 1001 1011 1001 # 二進位制 v v v v V B 9 B 9 # 十六進位制
注意16進位制的表示法,用字母H字尾表示,比如BH就表示16進位制數11;也可以用0X字首表示
在向左(或向右)取四位時,取到最高位(最低位)如果無法湊足四位,就可以在小數點的最左邊(或最右邊)補0,進行換算
將十六進位制轉為二進位制,一分四,即一個十六進位制數分成四個二進位制數,用四位二進位制按權相加,最後得到二進位制,小數點依舊就可以
B F 4 . B 5 # 十六進位制 v v v v v V 1011 1111 0100.1011 0101 # 二進位制
列表
命名規則“[]”
name = ["A","B","C","D","E"]
取值
print(name[0], name[1])
print(name[1:3]) # 切片,顧頭不顧尾
name[-1] # 取最後一個
# name[-1:-3] # 從左往右,這樣取不到值
name[-3:-1] # 取倒數第三到最後一個
name[-2:] # 取最後兩個
新增:
names.append("") # 追加
names.insert(1,"") # 插入哪寫哪
修改:
names[2] = "" # 修改
刪除:
names.remove("fgf") # 刪第一個從左往右
del names[1]
names.pop(1) # 座標為空則刪最後一個
取下標:
names.index("fgf") # 取下標
統計:
names.count("fgf") # 統計
排序: # 按ascii碼排序,符號、數字、大寫小寫
names.sort() # 排序
反轉:
names.reverse() # 反轉
清除列表:
names.clear() # 清空
擴充:
names2 = [1,2,3,4]
names.extend(name2) # 擴充
del names2 # 刪掉變數
遍歷:
for i in names: #遍歷列表
print i
步長:
range(1,10,2)
names[0:-1:2] <--> names(::2)
元組:
元組其實跟列表差不多,也是存一組數,只不是它一旦建立,便不能再修改,所以又叫只讀列表
語法
names = ("alex","jack","eric")
它只有2個方法,一個是count,一個是index,完畢。
字典:
字典一種key - value 的資料型別
語法:
info = {
'stu1101': "臺灣",
'stu1102': "釣魚島",
'stu1103': "南海", 字典的特性:
dict是無序的
key必須是唯一的,so 天生去重
增加或修改
info["stu"] = "fgf" # 存在為修改,不存在為新增
刪除
del info["stu"] # 刪除
info.pop("stu")
查詢
"fgf" in info # 標準用法
info.get("stu") # 獲取
info["stu"] # 如果不存在,就報錯,get不會,不存在返回None
-----------------------------------------------------------------------------
取Values
info.values()
取keys
info.keys()
setdefault
info.setdefault("stu1102", "小日本") # key有則不變,沒有就建立
update
b = {1:2,3:4, "stu1102":"釣魚島是中國的"}
info.update(b) # 類似列表的extend
info.items()
迴圈字典
# 方法1
for index,item in enumerate(info):
print(index,item)
# 方法2
for key in info: # 效果一樣,比下面高效
print(key,info[key])
# 方法3
for k,v in info.items(): #會先把dict轉成list,資料裡大時莫用
print(k,v)
}
深copy和淺copy
1、數字和字串
上篇提了:對於數字數字和字串一旦建立便不能被修改,假如對於字串進行替代操作,只會在記憶體中重新生產一個字串,而對於原字串,並沒有改變。
2、字典、列表等資料結構
alphabet = ["A","B","C",["L","M","N"]]
alphabet2 = alphabet.copy()
alphabet3 = alphabet
import copy
alphabet4 = copy.copy(alphabet)
alphabet5 = copy.deepcopy(alphabet)
請想一下:如果對alphabet的值做更改,其他四個變數的值會不會變化呢?
alphabet[2] = 2
alphabet[3][1] = 7
>>> alphabet
['A', 'B', 2, ['L', 7, 'N']]
下面分別看一下其他四個變數的值:
>>> alphabet # 更改後的值
['A', 'B', 2, ['L', 7, 'N']]
>>> alphabet2 # list.copy()
['A', 'B', 'C', ['L', 7, 'N']]
>>> alphabet3 # "="賦值
['A', 'B', 2, ['L', 7, 'N']]
>>> alphabet4 # copy.copy()
['A', 'B', 'C'['L', 7, 'N']]
>>> alphabet5 # copy.deepcopy()
['A', 'B', 'C'['L', 'M', 'N']]
總結一下
1、直接“=”賦值,都指向同一個記憶體地址,alphabet變,alphabet3也變。和簡單的數字、字串不一樣
2、list.copy()和copy模組的copy.copy()一樣,都是淺copy,只copy了第一層,下面的層只是copy記憶體地址,源變數深層被更改,則更改。
3、完全克隆,不只拷貝記憶體地址,則要深copy,使用copy模組的copy.deepcopy()
字典的fromkeys用法也是一樣。如下:
>>> deposit = dict.fromkeys(['husband','wife'],{"總存款:":"100w"})
>>> deposit
{'husband': '100w存款', 'wife': '100w存款'}
>>> deposit['husband']["總存款:"] = "80w"
>>> deposit
{'husband': {'總存款:': '80w'}, 'wife': {'總存款:': '80w'}}
# 改其中一個的值,其他的值就都改了。第一層不變,深層就都變了,
集合:
集合是一個無序的,不重複的資料組合,它的主要作用如下:
- 去重,把一個列表變成集合,就自動去重了
- 關係測試,測試兩組資料之前的交集、差集、並集等關係
1、常用操作
去重
list_1 = [1,1,2,3,4,5,6,6,7,7,8,8,9,9,3]
set_1 = set(list_1)
>>> set_1
{1, 2, 3, 4, 5, 6, 7, 8, 9}
# 集合用{}表示
交集
set_2 ={0,2,3,4}
set_1.intersection(set_2)
並集:
set_1.union(set_2)
差集:
set_1.difference(set_2)
# in set_1 but not in set_2
子集:
set_1.issubset(set_2)
父集:
set_1.issuperset(set_2)
對稱差集:(並集去除交集,即並集和交集的差集)
set_1.symmetric_difference(set_2)
(set_1 | set_2) - (set_1 & set_2)
判斷有沒有交集,無交集,返回True
set_1.isdisjoint(set_2)
2、符號操作
& : 交集 intersection | :並集 union - :差集 difference s <= t :子集 issubset s >= t :父集 issuperset ^ :對稱差集 symmetric_difference
3、集合增刪改查
新增: set_1.add(99) 批量新增 set_1.update([1,2,3,4]) 刪除: set_1.remove('h') # 沒有則報錯 set_1.discard(99) # 在則刪除,不在就不操作。無返回資訊 隨機刪: set_1.pop() 長度: len(set_1) 是否屬於判斷 s in set_1 # (判斷成員在不在都是這麼寫,字典中判斷key) 返回 set “s”的一個淺複製 s.copy()
字元編碼與轉碼
1、Python編碼詳解
為什麼我們要加“#-*- coding:utf-8 -*-”這一行?意思是置頂編碼型別為utf-8編碼!
為什麼我們能看到這些文字、數字、圖片、字元、等等資訊呢?大家都知道計算機本身只能識別 0 1 的組合,他們是怎麼展示這些內容的呢?我們怎麼和計算機去溝通呢?
那怎麼辦?如何讓計算機理解我們的語言,並且我們能理解計算機的語言呢?
ASCII(American Standard Code for Information Interchange,美國資訊交換標準程式碼)是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,並等同於國際標準ISO/IEC 646。
在儲存英文的時候我們至少需要1個位元組(一個字母),就是8位(bit),看下ASCII表中1個位元組就可以表示所有的英文所需要的字元,是不非常高效!
為什麼呢?早期的計算機的空間是非常寶貴的!
那你會發現1個位元組8位,他能儲存的最大資料是2的8次方-1 = 255,一個位元組最多能表示255個字元 那西方國家他們使用了127個字元,那麼剩下字元是做什麼的呢?就是用來做擴充套件的,西方人考慮到還有其他國家。所以留下了擴充套件位。
ASCII到了其他國家,完全不夠用,於是就在原有的擴充套件位中,擴充套件出自己的gbk、gb2312、gb2318等字元編碼。
他是怎麼擴充套件的呢?比如說在ASCII碼中的128這個位置,這個位置又指定一張單獨表
於是每個國家都有自己的字元編碼,也產生了1、沒有字符集: 2、字符集衝突
為了統一起來,Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字元編碼Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字元編碼
它為每種語言中的每個字元設定了統一併且唯一的二進位制編碼,
規定雖有的字元和符號最少由 16 位來表示(2個位元組),即:2 **16 = 65536, 注:此處說的的是最少2個位元組,可能更多。
這裡還有個問題:使用的位元組增加了,那麼造成的直接影響就是使用的空間就直接翻倍了!
為了解決個問題就出現了:UTF-8編碼
UTF-8編碼:是對Unicode編碼的壓縮和優化,他不再使用最少使用2個位元組,而是將所有的字元和符號進行分類:ascii碼中的內容用1個位元組儲存、歐洲的字元用2個位元組儲存,東亞的字元用3個位元組儲存…
OK 上面瞭解了:
1、什麼ASCII編碼
2、什麼Unicode編碼
3、什麼UTF-8編碼
回顧下亂碼的出現原因:1、沒有字符集 2、字符集衝突
2、Python編碼轉換
python3中,預設就是unicode編碼
name = '中國' # 轉為UTF-8編碼 print(name.encode('UTF-8')) # 轉為GBK編碼 print(name.encode('GBK')) # 轉為ASCII編碼(報錯為什麼?因為ASCII碼錶中沒有中文字符集~~) print(name.encode('ASCII'))
Python2.X中的編碼轉換
python2.X中預設是ASCII編碼,你在檔案中指定編碼為UTF-8,但是UTF-8如果你想轉GBK的話是不能直接轉的,的需要Unicode做一個轉接站點
#-*- coding:utf-8 -*- import chardet tim = '你好' print chardet.detect(tim) # 先解碼為Unicode編碼,然後在從Unicode編碼為GBK new_tim = tim.decode('UTF-8').encode('GBK') print chardet.detect(new_tim) # 結果 ''' {'confidence': 0.7525, 'encoding': 'utf-8'} {'confidence': 0.99, 'encoding': 'GB2312'} '''宣告只是檔案的編碼,python 3 的變數都是Unicode編碼
作業:
作業題目: 三級選單
作業需求:
資料結構:
menu = {
'北京':{
'海淀':{
'五道口':{
'soho':{},
'網易':{},
'google':{}
},
'中關村':{
'愛奇藝':{},
'汽車之家':{},
'youku':{},
},
'上地':{
'百度':{},
},
},
'昌平':{
'沙河':{
'老男孩':{},
'北航':{},
},
'天通苑':{},
'回龍觀':{},
},
'朝陽':{},
'東城':{},
},
'上海':{
'閔行':{
"人民廣場":{
'炸雞店':{}
}
},
'閘北':{
'火車戰':{
'攜程':{}
}
},
'浦東':{},
},
'山東':{},
}
需求:
可依次選擇進入各子選單
可從任意一層往回退到上一層
可從任意一層退出程式
所需新知識點:列表、字典
#三級選單
menu = {
'北京':{
'海淀':{
'五道口':{
'soho':{},
'網易':{},
'google':{}
},
'中關村':{
'愛奇藝':{},
'汽車之家':{},
'youku':{},
},
'上地':{
'百度':{},
},
},
'昌平':{
'沙河':{
'老男孩':{},
'北航':{},
},
'天通苑':{},
'回龍觀':{},
},
'朝陽':{},
'東城':{},
},
'上海':{
'閔行':{
"人民廣場":{
'炸雞店':{}
}
},
'閘北':{
'火車戰':{
'攜程':{}
}
},
'浦東':{},
},
'山東':{},
}
current_layer = menu
last_layer = []
while True:
for m in current_layer:
print(m)
choice = input('>:').strip()
if not choice:continue
if choice in current_layer:
last_layer.append(current_layer)
current_layer = current_layer[choice]
elif choice == 'b':
if len(last_layer) !=0:
current_layer = last_layer.pop()
else:
print("已經是頂層。")
elif choice == 'q':
exit ("bye.")
else:
print ("您輸入的城市不正確,請重新輸入,返回上級請輸1,退出請輸q")
作業題目: 購物車程式
作業需求:
資料結構: goods = [ {"name": "電腦", "price": 1999}, {"name": "滑鼠", "price": 10}, {"name": "遊艇", "price": 20}, {"name": "美女", "price": 998}, ...... ] 功能要求: 基礎要求: 1、啟動程式後,輸入使用者名稱密碼後,讓使用者輸入工資,然後列印商品列表 2、允許使用者根據商品編號購買商品 3、使用者選擇商品後,檢測餘額是否夠,夠就直接扣款,不夠就提醒 4、可隨時退出,退出時,列印已購買商品和餘額 5、在使用者使用過程中, 關鍵輸出,如餘額,商品已加入購物車等訊息,需高亮顯示
#購物車程式
goods = [
{"name": "電腦", "price": 1999},
{"name": "滑鼠", "price": 10},
{"name": "遊艇", "price": 20},
{"name": "美女", "price": 998},
]
shopping_car =[]
exit_flag=False
total_cost=0
username="1234"
user_password="1234"
while not exit_flag:
user = input ("請輸入使用者名稱:").strip()#使用者名稱
password = input ("請輸入密碼:").strip()#密碼
if username == user and password == user_password:
print("歡迎",username,"來Python開發入門14天集訓營")
break
else:
print("輸入的username or password 錯誤。")
continue
while not exit_flag:
salary = input ("請輸入您的工資:").strip () # 輸入金額
if salary.isdigit (): # 判斷輸入的salary是不是數字
salary = int (salary)
else:
print ("由於您的輸入的工資不合法,請再次輸入金額") # 輸入金額不合法
continue
while not exit_flag:
print ("商品列表".center (30, "-"))
for index, g in enumerate (goods):
print ("%s. %s %s" % (index, g.get ("name"), g.get ("price")))
choice=input("\033[31;1m請輸入要選擇的商品列表前的數字或退出(q/Q):\033[0m")
if choice.isdigit():# 判斷輸入的choice是不是一個數字
choice=int(choice)
if choice >= 0 and choice < len(goods):# 選擇商品編號必須小於商品列表的數量
goods_item = goods [choice] # 獲取商品
if goods[choice].get("price") <= salary :# 拿現有金額跟商品對比,是否買得起
shopping_car.append (goods[choice]) # 把選著的商品加入購物車
salary -= goods_item.get("price")# 扣完商品的價格
print ("已購買的商品:\033[31;1m{shop},當前的使用者餘額:\033[31;1m{balance}元\033[0m".format(shop = shopping_car,balance = salary))
else:
print ("餘額不足,不能購買此商品,只有:\033[31;1m{balance}元\033[0m".format(balance=salary))
else:
print ("\033[31;1m輸入的編號超出商品列表內容,請重新輸入\033[0m")
#break
elif choice == "q" or choice == "Q":#退出
if len(shopping_car) > 0:
print ("\033[31;1m購買以下商品\033[0m".center(30, "*"))
for index, g in enumerate (shopping_car):
print ("\033[31;1m%s. %s %s\033[0m" % (index,g.get("name"),g.get("price")))
total_cost += g.get("price")
print ("您的商品總價是:\033[31;1m{balance}\033[0m 元".format(balance=total_cost))
print ("您當前餘額是:\033[31;1m{balance}\033[0m 元".format(balance=salary))
exit_flag = True
else:
print ("您沒有購買任何商品")
user_choice=input("\033[31;1m是否重新購買商品(Y/y):\033[0m")
if user_choice == 'Y' or user_choice == 'y':
exit_flag = False
else:
exit_flag = True
else:
print ("商品編號有誤,請輸入整數型別編號")
# exit_flag = True