最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

2nd Python基礎(chǔ)語(yǔ)法的拓展補(bǔ)充

2021-01-09 22:42 作者:MoNanGo  | 我要投稿

第二章 基礎(chǔ)語(yǔ)法的補(bǔ)充拓展

2.1 關(guān)于變量的機(jī)制

2.1.1 變量的創(chuàng)建和修改

當(dāng)Python創(chuàng)建一個(gè)變量時(shí),我們假設(shè)是name,賦值為zm,變量的值(zm)就會(huì)存儲(chǔ)在計(jì)算機(jī)的內(nèi)存中,而該變量的變量名(name就會(huì)指向變量數(shù)據(jù)(zm)存放的內(nèi)存地址,我們?cè)诖a中可以通過(guò)id(name)來(lái)查看變量name的內(nèi)存地址。

現(xiàn)在我們修改name的值,修改成zhuming。此時(shí),zhuming放到內(nèi)存的一個(gè)新的地方,然后name指向的內(nèi)存地址改變成zhuming的內(nèi)存地址。那么就意味著一開(kāi)始的zm就已經(jīng)斷了聯(lián)系了,Python解釋器有自動(dòng)垃圾回收機(jī)制,在一定時(shí)間內(nèi)就會(huì)刷新內(nèi)存,將沒(méi)有引用關(guān)系的變量值(zm)清除掉,恢復(fù)成可用的存儲(chǔ)位置。

2.1.2 變量的指向關(guān)系

現(xiàn)在,創(chuàng)建變量name并賦值為zm,再創(chuàng)建一個(gè)新的變量name1,賦值為變量name,此時(shí)的對(duì)應(yīng)關(guān)系改怎么解釋。

name1賦值為name時(shí),name1name就同時(shí)指向name的內(nèi)存地址(name1name都指向zm的內(nèi)存地址,此時(shí)name1name無(wú)任何關(guān)系);

我們這時(shí)候再修改name的值為zhuming,現(xiàn)在輸出namename1,我們可以看到name輸出為zhumingname1輸出為zm。

2.2 身份運(yùn)算和None

python中有很多數(shù)據(jù)類型,查看一個(gè)數(shù)據(jù)類型的方法有type()。

?name = 'zm'
?age = 1
?
?print(type(age)) # <class 'int'>
?print(type(name)) # <class 'str'>

2.2.1 身份運(yùn)算

需要用到isis not運(yùn)算符,可以理解為是和不是。

?name = 'zm'
?print(type(name) is str) # True
?print(type(name) is int) # False
?print(type(name) is not int) # True
?print(type(name) is not str) # False

2.2.2 None

None表示什么都沒(méi)有,為空。

在程序中的用處:很多時(shí)候創(chuàng)建出來(lái)的變量是給用戶輸入的數(shù)據(jù)來(lái)賦值的,但是我們?nèi)绻麅H僅創(chuàng)建變量,不賦值就會(huì)報(bào)錯(cuò)。我們就會(huì)用None來(lái)賦值,表示現(xiàn)在值為空,后面會(huì)賦值的意思。

2.3 三元運(yùn)算

?a = 10
?b = 5
?
?# 一般代碼
?if a > 15:
? ? ?c = a
?else:
? ? ?c = b
?
?# 三元運(yùn)算 表示如果a > 15,d=a;否則d=b
?d = a if a > 15 else b

三元運(yùn)算的公式可以看為變量名 = 值1 if 條件A else 值2

2.4 細(xì)說(shuō)數(shù)據(jù)類型-列表

前面說(shuō)了列表的基本知識(shí)(1.3.4 列表),可以回顧一下。下面就做出一些補(bǔ)充。

2.4.1 列表的

  1. append(value):追加,需要一個(gè)參數(shù),將value插入在末尾

  2. insert(index, value):插入,需要兩個(gè)參數(shù),將value插入到index的位置,原來(lái)此位置以及后面的元素都往后挪1。

  3. extend(new_list):合并,需要一個(gè)列表參數(shù),將new_list與調(diào)用此方法的

2.4.2 列表的

  1. del:Python自帶的刪除方法,不需調(diào)用。del后面跟刪除的元素就好。eg:del names[1]

  2. pop([index]):刪除,不加參數(shù)就默認(rèn)刪除列表的最后一個(gè)元素;加參數(shù)就會(huì)刪除索引為index的元素。如果傳進(jìn)的index值越界就會(huì)報(bào)錯(cuò)。eg:names.pop() names.pop(3)。

  3. clear():清空,不用參數(shù),直接將列表清空,變成空列表(可以print()空列表看看,clear()返回的不是None)。eg:names.clear() ?# names為[] 即為空列表。

  4. remove(value):從左到右刪除第一個(gè)匹配到的value。刪掉不存在的值也會(huì)報(bào)錯(cuò)。

學(xué)過(guò)下面列表的查方法之一的index()之后,我們可以搭配起來(lái)實(shí)現(xiàn),通過(guò)元素值來(lái)匹配刪除指定元素。

?names = ['zm', 'wzw', 'yz', 'zk']
?names.pop(names.index('wzw')) ?# 刪除列表中的wzw

2.4.3 列表的

和前面一樣,還是以索引的方式來(lái)修改值。eg:names[0] = 'zm'

2.4.4 列表的

  1. index(value):從左到右查看第一個(gè)value的下標(biāo),若列表中無(wú)value的值,會(huì)報(bào)錯(cuò)的。eg:names.index('zm')

  2. count(value):統(tǒng)計(jì)value數(shù)量,返回的是int型數(shù)據(jù)。

2.4.5 切片

切片的正反

?names = ['zm', 'wzw', 'yz', 'zk']
?print(names[1:2]) # 輸出['wzw'],顧頭不顧尾(包括1不包括2)
?print(names[2:]) # 輸出['yz', 'zk']
?print(names[:2]) # 輸出['zm', 'wzw']
?print(names[-2:]) # 輸出['yz', 'zk']
?print(names[:-3]) # 輸出['zm']

關(guān)于上面的負(fù)數(shù),是切片的逆序切法,但是切片還是從左到右(沒(méi)變),只是索引變成從右往左,所以還是顧頭不顧尾。這個(gè)東西......多試試就會(huì)懂了,上升至理論層次可能會(huì)比較抽象,難以理解。eg:第五行代碼切片包括-2的元素,第六行代碼切片不包括-3的元素。

步長(zhǎng)

切片完整的格式是[begin: end: step],這里的step就是步長(zhǎng)。

關(guān)于步長(zhǎng),默認(rèn)是1(eg:[begin: end]),可以來(lái)試試修改步長(zhǎng)。eg:names[::2] # 列表全部元素隔一個(gè)輸出一個(gè)

切片也可以啥都不寫(xiě),比如names[::],name[:],他們都等價(jià)于names,就是啥都沒(méi)切,原樣輸出了。

有趣的是,步長(zhǎng)可以為負(fù)值,這時(shí)候整個(gè)列表就會(huì)反轉(zhuǎn)輸出。

?names = ['zm', 'wzw', 'yz', 'zk']
?print(names[::]) # ['zm', 'wzw', 'yz', 'zk']
?print(names[::-1]) # ['zk', 'yz', 'wzw', 'zm']

那步長(zhǎng)為負(fù)時(shí),beginend參數(shù)也是負(fù)值的話,那是不是也符合顧頭不顧尾呢?有興趣可以自己試試,這個(gè)點(diǎn)不是很重要。

2.4.6 列表的循環(huán)與排序

  • 排序:sort(),根據(jù)字符的十進(jìn)制碼進(jìn)行排序。大體的優(yōu)先級(jí)可以模糊理解為:字符<英文<漢字,可能會(huì)有一些特殊的個(gè)例。

  • 循環(huán):通常我們使用循環(huán)來(lái)遍歷打印列表的元素(大多使用for循環(huán),while循環(huán)看個(gè)人,習(xí)慣while的話就可以使用while)。

?names = [1, 2, 3, 4, 5]
?for i in names:
? ? ?print(i)

2.4.7 嵌套

嵌套適用于列表,也包括后面的元組、字典,除了字符串,其他的基本數(shù)據(jù)類型都支持嵌套語(yǔ)句。所謂嵌套,就是在一個(gè)數(shù)據(jù)類型里面放入一個(gè)數(shù)據(jù)類型,不限于單一的數(shù)據(jù)類型。

?names = ['zm', ['zm', 'wzw', 'yz'], {'411': 'zm', '409': 'yz'}]
?print(names)

2.4.8 enumerate()的使用

有時(shí)我們既需要取出列表的值,又需要列表的索引,我們就可以使用enumerate()

?# -*- encoding: utf-8 -*-
?lis = ['b', 'a']
?for i, k in enumerate(lis):
? ? ?print(i, k)

不過(guò),enumerate()可以使用index()來(lái)代替,但比較麻煩一點(diǎn)而已,盡量記住enumerate()。

2.5 細(xì)說(shuō)數(shù)據(jù)類型-元組

取值和創(chuàng)建都與列表類似,只是把[]改成了()。與列表不同的是,元組創(chuàng)建后,只能查,不能增刪改,可以看做只讀列表。元組只有count()index()兩種方法,方法的功能也與前面列表的一樣。

?names = ('zm', 'wzw')
?print(type(names)) # <class 'tuple'>

元組的循環(huán)遍歷、包含(if ... in tuple:)等運(yùn)算都和列表一樣。

不過(guò),元組中的元素設(shè)置為可變的數(shù)據(jù)類型,就可以改變?cè)M中的元素。

?names = ('yz', ['zm', 'wzw'])
?print(names) # ('yz', ['zm', 'wzw'])
?names[1][0] = 'zhuming'
?print(names) # ('yz', ['zhuming', 'wzw'])

比如我們?cè)M中嵌套列表,我們可以修改列表里面的元素。元組只是存每個(gè)元素的內(nèi)存地址,而作為元組的元素的列表里面的元素存在內(nèi)存里另外的空間,所以是可變的。

2.6 細(xì)說(shuō)數(shù)據(jù)類型-字符串

2.6.1 切片

我們也可以對(duì)字符串使用切片的所有功能,或者說(shuō)我們可以把字符串當(dāng)做一個(gè)列表,每一個(gè)字符是列表的每個(gè)元素。

?name = 'zhuming'
?print(name[::-1])
?print(name[::2])
?print(name[::2])

但是,值得注意的是,字符串不可被修改,修改的話都會(huì)創(chuàng)建一個(gè)新值,我們可以通過(guò)查看修改前和修改后的內(nèi)存地址來(lái)觀察。

?name = 'zm'
?print(id(name))
?name = 'wzw'
?print(id(name)) ?# 與第一次輸出的地址不一樣

2.6.3 轉(zhuǎn)義字符

Python中有許多有代表特殊含義的字符,被稱為轉(zhuǎn)義字符。比如常見(jiàn)的有\n、\t等,分別代表了回車、縮進(jìn)等特殊含義。

如果不想讓轉(zhuǎn)義字符生效,就可以在前面加一個(gè)\,或者在字符串前加一個(gè)r,表示原生,不觸發(fā)轉(zhuǎn)義字符。

?print('zm\nwzw\tyz')
?# 輸出:
?# zm
?# wzw ? ?yz
?
?print('zm\\nwzw\\tyz') # 輸出:zm\nwzw\tyz
?print(r'zm\nwzw\tyz') # 輸出:zm\nwzw\tyz

2.6.4 字符串的常用操作

  • capitalize():大寫(xiě)字符串的首字母。eg:name = 'jack chen' name.capitalize()就是'Jack chen',注意而不是'Jack Chen'

  • casefold():大寫(xiě)全部變小寫(xiě),與lower()函數(shù)的區(qū)別在于,casefold()適用于大多數(shù)字符。eg:name = 'Jack Chen' name.casefold()就是'jack chen'

  • center(width, fillchar):定義寬度,然后字符中間顯示,兩側(cè)填充fillchar的字符。

    ?name = 'System Of Information'
    ?print(name.center(50, '#'))
    ?# 輸出:
    ?# ##############System Of Information###############

  • count(char, start, end):計(jì)數(shù)字符串內(nèi)出現(xiàn)char字符的次數(shù),后面兩個(gè)參數(shù)可填可不填,表示切片的開(kāi)始和結(jié)束,在切出來(lái)的一段字符串內(nèi)對(duì)char進(jìn)行計(jì)數(shù)。

    ?the_string = 'ssaadd sad'
    ?print(the_string.count('s')) # 3
    ?print(the_string.count('a', 0, 3)) # 1(顧頭不顧尾)

  • endswith(str):判斷字符串是以什么結(jié)尾。

    ?email = '2511343050@qq.com'
    ?if email.endswith('@qq.com'):
    ? ? ?print('郵箱格式正確')
    ?elif email.endswith('@163.com'):
    ? ? ?print('郵箱格式正確')
    ?else:
    ? ? ?print('郵箱格式錯(cuò)誤')
    ?# 輸出:
    ?# 郵箱格式正確

  • find(char, start, end):這里的三個(gè)參數(shù)和count的參數(shù)一樣的含義,找到了就返回char的下標(biāo)。注意的是find只能找從左到右第一個(gè)的char。

    ?name = 'qwq owo xwx'
    ?

  • format():格式化輸出。

    ?title = ' the system '
    ?choice_1 = ' [1] select '
    ?choice_0 = ' ?[0] exit ?'
    ?# %
    ?welcome = """
    ?----%s----
    ?----%s----
    ?----%s----
    ?----%s----
    ?""" % (title, choice_1, choice_0, title)
    ?print(welcome)
    ?
    ?# format 1
    ?welcome = """
    ?----{0}----
    ?----{1}----
    ?----{2}----
    ?----{0}----
    ?""".format(title, choice_1, choice_0)
    ?print(welcome)
    ?
    ?# format 2
    ?welcome = f"""
    ?----{title}----
    ?----{choice_1}----
    ?----{choice_0}----
    ?----{title}----
    ?"""
    ?print(welcome)

  • index(char, start, end):和count以及find類似的功能,只是返回的是下標(biāo)

  • isdigit():判斷字符串是否是一個(gè)整數(shù)(可以理解為int()強(qiáng)制轉(zhuǎn)換為整型),返回TrueFalse

  • islower():判斷字符串是否全部是小寫(xiě)。

  • isspace():判斷字符串是否有空格,多個(gè)空格也可以。

  • isupper():判斷字符串是否全部是大寫(xiě)。

  • join(iterable):字符串的拼接,必須全是字符串,不能有其他任何類型。

    ?names = ['zm', 'wzw', 'yz']
    ?print(''.join(names)) # zmwzwyz
    ?print('|'.join(names)) # zm|wzw|yz
    ?print(', '.join(names)) # zm, wzw, yz

  • ljust(width, fillchar):與center()類似,從左開(kāi)始數(shù)

  • lower():大寫(xiě)變小寫(xiě),只支持ASCI Ⅱ編碼。

  • strip(chars):將字符串兩邊的其他字符清除,不寫(xiě)具體chars的值就默認(rèn)包括空格和轉(zhuǎn)義字符這些。該函數(shù)還衍生出另外兩個(gè)函數(shù),分別是lstrip()rstrip()lstrip()功能是將左邊的其他字符清除,rstrip()功能是將左邊的其他字符清除。

  • replace(old, new, count=None):將原字符串中的old片段換成new,count表示換多少個(gè)(順序?yàn)閺淖蟮接遥?,默認(rèn)是全部old都換。

    ?score = 'My score is 580!580!580!'
    ?print(score.replace("580", "630")) # 修改成My score is 630!630!630!
    ?print(score.replace("580", "630", 1)) # 修改成My score is 630!580!580!
    ?print(score.replace("580", "630", 2)) # 修改成My score is 630!630!580!

  • split(sep, maxsplit=-1):字符串通過(guò)sep分割成列表的元素,以列表的形式返回。如果什么參數(shù)都不寫(xiě),字符串直接變成只有一個(gè)元素的列表。maxsplit設(shè)置的是從左到右分割幾次,默認(rèn)無(wú)數(shù)次。該函數(shù)還衍生出一個(gè)函數(shù),是rsplit(),其功能就是把從左往右變成從右往左。

    ?n = ['zm', 'yz', 'wzw']
    ?name = ",".join(n) # 'zm,yz,wzw'
    ?names = name.split(',') # ['zm', 'yz', 'wzw']

  • startswith(prefix, start=None, end=None):和endswith()一樣,一個(gè)判斷字符串以什么開(kāi)頭,一個(gè)以什么結(jié)尾。startendendswith()的參數(shù)功能一模一樣。

  • swapcase():大小寫(xiě)交換,小寫(xiě)變大寫(xiě),大寫(xiě)變小寫(xiě),不過(guò)特殊字符不會(huì)變。

  • upper():字符串統(tǒng)一變成大寫(xiě)。

  • zfill(width):規(guī)定長(zhǎng)度,不夠長(zhǎng)度用0來(lái)補(bǔ),一般不常用,網(wǎng)絡(luò)編程時(shí)可能會(huì)用到。

總結(jié):

  • find()、index()、count()

  • replace()、upper()、lower()、swapcase()、casefold()、strip()、split()

  • 格式化format()、ljust()rjust()、join()

  • 判斷isdigit()、startswith()、endswith()

2.7 細(xì)說(shuō)數(shù)據(jù)類型-字典

2.7.1 字典的優(yōu)點(diǎn)及創(chuàng)建

方便嵌套操作海量數(shù)據(jù),而且字典是以鍵值對(duì)形式存儲(chǔ),可以通過(guò)查找鍵來(lái)獲得值,而字典的鍵可以是整型、字符串、元組等不可變數(shù)據(jù)類型(且每個(gè)鍵要唯一存在),而不是像列表那樣只有單一的下標(biāo)查詢。

字典的創(chuàng)建:

?# {key1: value1, key2: value2, ...}
?new_dict = {
? "name": 'zm',
? ? ?"password": '123',
?}
?print(new_dict)
?print(new_dict['name']) # 取鍵name對(duì)應(yīng)的值

字典沒(méi)有順序(無(wú)序),查詢速度不受字典大小的影響(HASH,索引結(jié)構(gòu)),非???。字典的鍵不可變、必須唯一,鍵對(duì)應(yīng)的值可以有多個(gè),可以被修改、可以不唯一。

幾種創(chuàng)建方法

?# 1
?person = {"name": "zm", "age": 20} # {'name': 'zm', 'age': 20}
?# 2
?person = dict(name='zm', age=20) # {'name': 'zm', 'age': 20}
?# 3
?{}.fromkeys([1, 2, 3, 4, 5, 6, 7, 8], 100) # {1: 100, 2: 100, 3: 100, 4: 100, 5: 100, 6: 100, 7: 100, 8: 100}

2.7.2 字典的增刪改查

字典的增

?new_dict = {
? "name": 'zm',
? ? ?"password": '123',
?}
?# 增 1 (如果job已經(jīng)存在就變成了修改job的值)
?new_dict['job'] = 'teacher'
?# 增 2 (如果address已經(jīng)存在,setdefault就只會(huì)返回原address的值,不進(jìn)行任何修改或添加操作)
?new_dict.setdefault('address', '地球')
?print(new_dict) ?# 多了job和address兩個(gè)鍵值對(duì)

字典的刪

?new_dict = {
??? "name": 'zm',
? ? "password": '123',
?}
?new_dict.pop('name') # 刪除鍵為name的鍵值對(duì)
?new_dict.popitem() # 隨機(jī)刪除一個(gè)鍵值對(duì)
?del new_dict['name'] # 刪除鍵為name的鍵值對(duì)
?new_dict.clear() # 清空字典

del在刪除數(shù)據(jù)類型的所有方法里,盡量不要用......

字典的改

?dic = {1: 1, 2: 2, 3: 3}
?dic2 = {1: 2, 2: 4, 4: 8}
?# 修改3的鍵值對(duì)
?dic[3] = 5 # {1: 1, 2: 2, 3: 5}
?# 將dic2的鍵值對(duì)加到dic里面,如果鍵有重復(fù)的情況,dic2中的鍵值對(duì)會(huì)覆蓋dic的原鍵值對(duì)
?dic.update(dic2) # {1: 1, 2: 4, 4: 8, 3: 5}

字典的查

  1. dic['key']:返回字典key對(duì)應(yīng)的值,不存在則會(huì)報(bào)錯(cuò);

  2. dic.get(key, default=None):如果有就返回key對(duì)應(yīng)的value,找不到就返回default的值;

  3. 'key' in dic:存在返回True,不存在返回False;

  4. dic.keys():返回包括dic的所有鍵的列表;

  5. dic.values():返回包括dic的所有值的列表;

  6. dic.items():返回包括dic所有鍵值對(duì)(元組的形式:(key, value))的列表。

循環(huán)

?for i in dic:
? ? ?print(i) # 打印的只是key
?# 推薦方法
?for i in dic:
? ? ?print(i, dic[i])
?# 以下效率比較低(用到keys(),items(),values()的都比較慢)
?for i in dic.items():
? ? ?print(i)
?for k, v in dic.items():
? ? ?print(k, v)

2.8 細(xì)說(shuō)數(shù)據(jù)類型-集合

2.8.1 集合的作用

和列表一樣,存一堆數(shù)據(jù),里面的元素不可變,不能存列表、字典等可變數(shù)據(jù)類型放在集合內(nèi),只能存儲(chǔ)元組、數(shù)字、字符串等不可變數(shù)據(jù);集合天生去重,在集合不存在重復(fù)元素;集合無(wú)序,不能通過(guò)索引來(lái)查找值。

集合最重要的兩個(gè)功能:去重關(guān)系運(yùn)算(與、并、異或等)

2.8.2 集合的增刪改查

?# 去重
?names = ['zm', 'wzw', 'yz', 'zk', 'zm', 'zk']
?print(set(names)) # {'wzw', 'zm', 'zk', 'yz'}
?print(type(set(names))) # <class 'set'>
?
?# 增
?set_name = set(names)
?set_name.add('py') # {'zm', 'zk', 'yz', 'wzw', 'py'}
?
?# 刪
?set_name.discard('py') # 刪除py,{'zm', 'zk', 'yz', 'wzw'}
?set_name.discard('p2y') # 刪除不存在的值時(shí),就不進(jìn)行任何操作
?
?set_name.pop() # 隨機(jī)刪除并返回刪除后的集合
?
?set_name.remove('zm') # 刪除zm
?set_name.remove('zm2') # 刪除不存在的值時(shí),就會(huì)報(bào)錯(cuò)
?
?# 查
?# 只能in運(yùn)算
?if 'wzw' in set_name:
? ? ?print(True)
?
?# 改
?# 不能修改!
?# 切片也是不能用的

2.8.3 集合的關(guān)系運(yùn)算

?names_181 = ['zm', 'wzw', 'yz', 'zk', 'kyj']
?names_182 = ['zm', 'yz', 'py', 'zzw', 'ghd']
?
?print(names_181 & names_182) # 交集
?print(names_181 | names_182) # 并集
?print(names_181 - names_182) # 差集,only in names_181
?print(names_182 - names_181) # 差集,only in names_182
?print(names_181 ^ names_182) # 對(duì)稱差集,等于 兩個(gè)集合的并集 - 兩個(gè)集合的交集

集合的關(guān)系一般只有三個(gè):包含、相交、不相交。Python中分別用下面的方法判斷:

  • names_181.isdisjoint(names_182):判斷兩個(gè)集合是否相交,返回True or False

  • names_181.issubset(names_182):判斷name_181是否被包含于name_182中,返回True or False

  • names_181.issuperset(names_182):判斷name_181是否包含name_182,返回True or False

集合還有其他的方法,這些就不一一贅述了,用到就百度一下就好了。

2.9 關(guān)于二進(jìn)制和十六進(jìn)制

2.9.1 二進(jìn)制

理解數(shù)學(xué)的十進(jìn)制到二進(jìn)制的轉(zhuǎn)換就好了,二進(jìn)制逢2進(jìn)一。

計(jì)算機(jī)為什么用二進(jìn)制?是因?yàn)橛?jì)算機(jī)的晶體管只能有高電平和低電平兩個(gè)狀態(tài),先人把低電平和高電平用0和1表示,通過(guò)這種方法,用二進(jìn)制來(lái)抽象表示人類生活中的種種信息數(shù)據(jù)。

Python中將十進(jìn)制轉(zhuǎn)化成二進(jìn)制的方法是bin(),十進(jìn)制的值只能從0-255,更高的表示方法需要更深學(xué)習(xí)bin()方法的具體表示,我們就可以不用看了,了解二進(jìn)制的轉(zhuǎn)化即可。

2.9.2 十六進(jìn)制

10進(jìn)制用0-9表示所有數(shù)字,2進(jìn)制用0, 1表示所有數(shù)字,而16進(jìn)制用0-9以及A-F,15個(gè)符號(hào)表示所有數(shù)字,逢16進(jìn)一。A-F分別代表10-15。

16進(jìn)制只是一種表示方法,計(jì)算機(jī)的底層還是使用2進(jìn)制的。計(jì)算機(jī)中16進(jìn)制多用來(lái)表示HTML/CSS的顏色表的色號(hào)(有RGB等,16進(jìn)制也是一種常用表示方法)、mac地址、字符編碼等都用16進(jìn)制來(lái)表示。

為了16進(jìn)制不與其他進(jìn)制不混淆,16進(jìn)制一般開(kāi)頭為0x,后面的字符才是可以轉(zhuǎn)化的東西,比如hex(16)輸出是0x10,數(shù)學(xué)上的計(jì)算方法就是:0* 16*0+1* 16*1=16,數(shù)學(xué)方法就不再多介紹了,可以自行百度了解,自己演算的時(shí)候很常用。

Python中將十進(jìn)制轉(zhuǎn)換成十六進(jìn)制的方法是hex(),可以自己多試試。

2.10 字符編碼

2.10.1 文字的顯示原理

為了表示字符,我們必須實(shí)現(xiàn)zhuming -> 十進(jìn)制,使他們關(guān)聯(lián)起來(lái)。

將一個(gè)一個(gè)字符與十進(jìn)制數(shù)字對(duì)應(yīng)起來(lái),最常見(jiàn)的有ASCII碼(基于拉丁字母和特殊字符的一套字符編碼表)。然而ASCII碼一開(kāi)始只有127個(gè),后來(lái)又補(bǔ)充了一些(128后面的字符對(duì)應(yīng)關(guān)系稱作擴(kuò)展ASCII碼),但是沒(méi)有中文。Python中可以通過(guò)ord()來(lái)查看字符對(duì)應(yīng)的十進(jìn)制數(shù)。

但是每個(gè)字符轉(zhuǎn)化的二進(jìn)制長(zhǎng)度都不一樣,二進(jìn)制怎么斷句呢?因?yàn)锳SCI Ⅱ碼小于255,所以就規(guī)定每8位(bit)代表一個(gè)字節(jié)(B,又稱bytes)。1024B=1KB,1024KB=1MB,1024MB=1GB,1024GB=1TB -> PB EB ZB等等。

因?yàn)?code>ASCII表沒(méi)有中文,我們就自己研發(fā)了一張表,又因?yàn)闈h字一個(gè)bit存不下,我們就用了兩個(gè)bit來(lái)存儲(chǔ)。后來(lái)研發(fā)成功,名為GB2312,總共可有存儲(chǔ)6w個(gè)漢字,當(dāng)時(shí)只有6763個(gè)漢字(日常生活中常用的)

隨著電腦在中國(guó)的普及,越來(lái)越多的字需要被計(jì)算機(jī)表示,后面升級(jí)成了GBK編碼,表示了2w多個(gè)字符(包括漢字、少數(shù)民族語(yǔ)言、日語(yǔ)、韓語(yǔ)等),21世紀(jì)又進(jìn)行了升級(jí),表示了2w8k多個(gè)字符。

隨著發(fā)展,問(wèn)題又來(lái)了,人們生活中不光單純使用中文,英文使用的頻率和中文的頻率差不多,如果用GBK來(lái)表示純英文的文檔比用ASCII一倍的內(nèi)存。那么如何兼容呢?

因?yàn)?code>ASCII高位的字符(大于127的特殊字符)比較少用,那么兩個(gè)連續(xù)的高位字符就更少出現(xiàn)了。我們就增加一個(gè)判斷,如果有兩個(gè)連續(xù)的高位字符,我們就使用GBK編碼,其他情況就用ASCII編碼,較好的解決了兼容性問(wèn)題。

2.10.2 編碼種類

每個(gè)國(guó)家可能都會(huì)有自己的編碼,比如美國(guó)是ASCII,中國(guó)是GBK,日本是shift_JIS等等等等,每個(gè)的字符對(duì)應(yīng)關(guān)系都不一樣,那不同國(guó)家的軟件自己拿來(lái)就會(huì)產(chǎn)生亂碼。

最后,出現(xiàn)了Unicode編碼,2-4字節(jié),俗稱萬(wàn)國(guó)碼,支持所有的語(yǔ)言(13w6k多個(gè)),可以與各種語(yǔ)言進(jìn)行轉(zhuǎn)換(將已經(jīng)出來(lái)的軟件不用推倒重做)

但是Unicode用了2-4個(gè)字節(jié),比ASCII的一個(gè)字節(jié)多了很多,在當(dāng)時(shí)的傳輸和硬件存儲(chǔ)水平下,很不適應(yīng)。

最后針對(duì)傳輸和存儲(chǔ),基于Unicode做出了一個(gè)新編碼,叫UTF-8(使用1、2、3、4字節(jié)表示所有字符,優(yōu)先使用少的字節(jié))。

下面兩個(gè)編碼因?yàn)闆](méi)有解決傳輸和存儲(chǔ)的問(wèn)題,所以不常使用,只做解。

UTF-16:使用2、4字節(jié)表示所有字符

UTF-32:使用4個(gè)字節(jié)表示所有字符

這里也簡(jiǎn)單提一下python2和python3的區(qū)別。

python2用的是ASCII碼,python3用的是utf-8,所以python2不能顯示中文,所以python2在程序的開(kāi)頭一般都要手動(dòng)聲明# -*- encoding: utf-8 -*-(官網(wǎng)推薦寫(xiě)法),必須在代碼的頂頭(第一行)寫(xiě)。

我們python3呢建議也寫(xiě)上,防止python3偶爾因?yàn)榫幋a文件導(dǎo)致自己的項(xiàng)目代碼運(yùn)行報(bào)錯(cuò),最后花個(gè)好幾天解決就很傷了。

# -*- encoding: utf-8 -*-

2.11 字典密碼——HASH

2.11.1 HASH

HASH(又稱哈希)是把任意長(zhǎng)度的輸入(又叫做預(yù)映射)通過(guò)散列算法變換成固定長(zhǎng)度的輸出,該輸出值就是散列值。這種轉(zhuǎn)換是一種壓縮映射,這樣我們可以通過(guò)更小的值來(lái)表示很大的值所表示的東西。

HASH是一種算法,很復(fù)雜的運(yùn)算,它的輸入可以是字符創(chuàng)或者數(shù)字或者任何文件,經(jīng)過(guò)哈希算法處理后,變成一個(gè)固定長(zhǎng)度的輸出,該輸出就是哈希值。哈希算法有一個(gè)很大的特點(diǎn),就是不能從結(jié)果推算出輸出是什么,所以成為不可逆的算法。

哈希多應(yīng)用于密碼學(xué)以及區(qū)塊鏈等方面。

Python中有hash()的方法來(lái)將字符串或數(shù)字變成哈希值,每次重啟Python之后,同樣的字符或數(shù)字hash()的哈希值都不是一致的。注意,hash()的參數(shù)只能hash不可變的值。

HASH的特性

  1. 剛才也說(shuō)了,不可逆是HASH的一個(gè)重要特性。生活中也有許多不可逆的情況,比如煮熟的雞蛋變不回生雞蛋。

  2. 計(jì)算極快。20G高清電影和5K的文件

HASH的用途

  1. 密碼。常用的加密算法是md5。md5就是基于HASH做的,使你的密碼經(jīng)過(guò)基于HASH的算法處理,使你的密碼與一個(gè)哈希值一一對(duì)應(yīng),然后存放進(jìn)數(shù)據(jù)庫(kù)中。如果想登陸,就只能知道原來(lái)的密碼是什么,然后輸入,進(jìn)行算法的處理,將生成的值與數(shù)據(jù)庫(kù)內(nèi)存儲(chǔ)的哈希值比較,如果一致才可以登陸成功。

  2. 文件完整性校驗(yàn)。常用的也是md5算法。一個(gè)文件對(duì)應(yīng)一個(gè)哈希值,在傳輸過(guò)程中可能會(huì)遇到攔截等惡意攻擊,當(dāng)接收文件之后,再進(jìn)行md5處理,如果兩次得出的哈希值一致,那就說(shuō)明文件完整,沒(méi)有殘缺或植入了木馬等惡意程序。

  3. 數(shù)字簽名。數(shù)字簽名是為了防止假情報(bào),效果類似于對(duì)暗號(hào),A說(shuō)天王蓋地虎,B回應(yīng)寶塔鎮(zhèn)河妖,那A和B就確定了是自己人,才可以進(jìn)行通信。數(shù)字簽名就是在互聯(lián)網(wǎng)上的暗號(hào)應(yīng)用。A說(shuō)的天王蓋地虎在互聯(lián)網(wǎng)上稱為私鑰,將發(fā)送的原文進(jìn)行hash,生成一段hash值(就是摘要信息),然后把原文和摘要信息一同發(fā)給B。他回應(yīng)的寶塔鎮(zhèn)河妖被稱為公鑰,將你的摘要信息解密,得到hash值。B再對(duì)原文件進(jìn)行hash,也得到一個(gè)hash值,將這個(gè)hash與a發(fā)來(lái)的hash值進(jìn)行比較,如果一致就說(shuō)明這個(gè)原文是A本人發(fā)送的,而不是別人發(fā)送的。

  4. 區(qū)塊鏈。電子錢包,加密錢包等應(yīng)用。

  5. 還有很多其他的應(yīng)用就不一一介紹了。

2.11.2 應(yīng)用HASH的數(shù)據(jù)結(jié)構(gòu)

Python中有兩個(gè)數(shù)據(jù)類型是基于hash來(lái)做的,一個(gè)是dict,一個(gè)是set。

字典快的原因

dict有三個(gè)顯著特點(diǎn):

  • key唯一

  • key不可變

  • 查詢速度極快,且不受dict大小的影響的特點(diǎn)。

第三個(gè)特性就是hash帶來(lái)的。下面就進(jìn)行簡(jiǎn)單的原理解釋(真實(shí)的原理不是這樣,只是做類似的解說(shuō))。

dict的每個(gè)key都會(huì)經(jīng)過(guò)hash生成一段固定長(zhǎng)度的hash值,然后這些hash值經(jīng)過(guò)大小排序放入一個(gè)列表A中(hash值都是一串?dāng)?shù)字),需要查詢哪個(gè)字典的值就通過(guò)二分法查找列表A,所以只需要31次查詢就可以找20億的數(shù)據(jù),計(jì)算機(jī)查詢一次也僅僅只需要幾毫秒。

不過(guò),字典的原理還不單單只有這些,這些只是簡(jiǎn)單地類似原理,真實(shí)的字典原理比這還要復(fù)雜。

集合為何去重

集合每add進(jìn)一個(gè)值,他都會(huì)經(jīng)過(guò)hash運(yùn)算出一個(gè)hash值,然后存放在一個(gè)列表A中,如果后面add的數(shù)據(jù)的hash值在列表A中,那么這個(gè)數(shù)據(jù)就不會(huì)再存進(jìn)集合里了。

2.11.3 判斷數(shù)據(jù)結(jié)構(gòu)是否可變

將這個(gè)數(shù)據(jù)進(jìn)行hash,如果可以哈希就是不可變的數(shù)據(jù),反之則是可變的數(shù)據(jù)類型。

2.12 文件操作

2.12.1 基礎(chǔ)操作

日常文件操作的步驟:

  1. 找到文件,打開(kāi)

  2. 讀、修改

  3. 保存、關(guān)閉

Python中的文件操作:

  1. open(filename):根據(jù)路徑和文件名打開(kāi)文件

  2. f.read()/f.write():讀寫(xiě)操作

  3. f.close():文件關(guān)閉(默認(rèn)保存)

需要注意的是文件操作的模式只能以一種方式(后面再介紹復(fù)雜的多種方式混合的文件操作模式)。python有rw,a三種基本方法,分別代表只讀模式、寫(xiě)入模式、追加模式三種基本方式。(注意,如果w的寫(xiě)入模式下會(huì)覆蓋原文件的舊數(shù)據(jù),想在原文件的舊數(shù)據(jù)后面寫(xiě)新數(shù)據(jù)的話就要用到a的追加模式才可以)

因?yàn)槭俏募牟僮?,所以存在路徑、文件名等差異,每個(gè)人都不一樣。我們這里就統(tǒng)一規(guī)定一下。

以下文件操作的代碼都是對(duì)名為test.txt,路徑是所在目錄是當(dāng)前python文件下的路徑的文件進(jìn)行的操作。

?# -*- encoding: utf-8 -*-
?# 文件的讀
?f = open(file='test.txt', mode='r')
?# 讀一行
?print(f.readline())
?# 讀剩下的數(shù)據(jù)
?print(f.read())
?f.close()

?# 不需要寫(xiě)close()的with語(yǔ)句
?with open(file='test.txt', mode='r') as f:
? # 讀一行
? ? ?print(f.readline())
? ? ?# 讀剩下的數(shù)據(jù)
? ? ?print(f.read())
?print('with代碼塊執(zhí)行完之后,with會(huì)關(guān)閉所有代碼塊中用到的功能進(jìn)程,其中就包括f.close()')
?
?# 文件的追加寫(xiě)入
?f = open(file='test.txt', mode='a')
?# 讀一行
?f.write('\nzk\t24\t18845516854')
?f.close()
?
?# 文件的覆蓋寫(xiě)入
?f = open(file='test.txt', mode='w')
?# 讀一行
?f.write('zk\t24\t18845516854')
?f.close()

循環(huán)輸出

?# -*- encoding: utf-8 -*-
?f = open(file='test.txt', mode='r')
?
?print('循環(huán)輸出:')
?for line in f:
? ? ?print(line.strip()) ? ? # strip是去掉每一行末尾的\n?# -*- encoding: utf-8 -*-
?f = open(file='test.txt', mode='r')
?print('輸出age大于20的信息')
?for line in f:
? ? ?line_info = line.strip().split(', ')
? ? ?if int(line_info[1]) >= 20:
? ? ? ? ?print(line.strip())
?
?f.close()?# -*- encoding: utf-8 -*-
?f = open(file='test.txt', mode='r')
?print("全部輸出:")
?f.readlines()
?
?f.close()

2.12.2 file類的常用功能

  • seek(num):光標(biāo)的定位,移動(dòng)到num的位置,num是以字節(jié)來(lái)算而不是字符!中文占三個(gè)字節(jié),所以seek()定位的時(shí)候可能會(huì)定位到一個(gè)字符的幾個(gè)字節(jié)之間,導(dǎo)致可能會(huì)拋出編碼錯(cuò)誤(UnicodeDecodeError

    ?# -*- encoding: utf-8 -*-
    ?with open('test.txt', 'r') as f:
    ? ? ?f.seek(2) # 從zm后面開(kāi)始輸出
    ? ? ?print(f.readlines())

  • flush():強(qiáng)制刷入硬盤。因?yàn)閷?duì)硬盤的數(shù)據(jù)進(jìn)行頻繁操作很慢,所以文件操作有個(gè)緩存機(jī)制,write的數(shù)據(jù)先寫(xiě)到緩存的內(nèi)存里,緩存滿了才會(huì)刷到硬盤里。比如我們一直write方法寫(xiě)入,但是如果你不close()它就不會(huì)立即刷到硬盤。如果寫(xiě)入的數(shù)據(jù)很重要,怕運(yùn)行過(guò)程中斷電等因素(計(jì)算機(jī)關(guān)閉時(shí)只有硬盤的數(shù)據(jù)不會(huì)被清空)影響到關(guān)鍵數(shù)據(jù)的寫(xiě)入,就可以用flush()強(qiáng)制刷入硬盤中。

  • readable():判斷文件是否可讀。

  • seekable():判斷文件是否可以進(jìn)行seek(),比如Linux所有的東西都是文件,所以需要判斷這個(gè)函數(shù)判斷,不常用。

  • tell():返回當(dāng)前光標(biāo)的位置。

  • truncate():按指定長(zhǎng)度截?cái)辔募?。指定長(zhǎng)度就從文件頭開(kāi)始到指定長(zhǎng)度為止;不指定就從當(dāng)前位置截到文件末尾。長(zhǎng)度也是用字節(jié)來(lái)算,不是按字符來(lái)算!針對(duì)網(wǎng)站訪問(wèn)量大的日志的分析可能會(huì)用到。

  • writable():判斷文件是否可寫(xiě)。

  • writelines():傳入一個(gè)列表數(shù)據(jù),然后一個(gè)元素一行的寫(xiě)入文件。

2.12.3 混合模式下處理文件

文件模式肯定不止前面的基本三種,打開(kāi)文件還有w+、r+、a+三種混合模式,分別是三種基本文件模式的組合,比如

  • w+就是創(chuàng)建一個(gè)新文件,寫(xiě)一段內(nèi)容可以再把內(nèi)容讀出,可以理解為wr的組合,不常用;

  • r+就是能讀能寫(xiě),可以理解為ra的組合,文件寫(xiě)入是從末尾開(kāi)始寫(xiě);讀的話,是從開(kāi)頭開(kāi)始讀,不用重新seek(),不用為較為常用;

  • a+就是文件一打開(kāi),文件寫(xiě)入是從末尾開(kāi)始寫(xiě),讀也是從文件末尾開(kāi)始讀。

這三種模式很少使用,r+a+偶爾會(huì)用到。

混合模式修改文件

我們要修改文件的話就需要用到r+的混合模式。比如我們要在test.txt的第一行中插入一個(gè)'dd'。

?# -*- encoding: utf-8 -*-
?with open('test.txt', 'r+', encoding='utf-8') as f:
? ? ?f.seek(2)
? ? ?f.write('dd')

插入過(guò)后打開(kāi)test.txt文件,我們就可以看到,插入的'dd'插入是插入成功了,但是dd的第二個(gè)d會(huì)把seek(2)后面的一個(gè)字節(jié)(別忘了seek()是以字節(jié)為單位的)覆蓋掉...... 這是我們不想看到的,下面我們就來(lái)闡述這個(gè)問(wèn)題的原因以及解決方法。

在文件中間修改數(shù)據(jù)的話,就會(huì)覆蓋后面的數(shù)據(jù),這個(gè)和數(shù)據(jù)在硬盤上的數(shù)據(jù)存儲(chǔ)方法有關(guān)系。但是像wordvim這些工具都可以修改文件,那他們到底是怎么實(shí)現(xiàn)的呢?

我們就可以先把硬盤的文件數(shù)據(jù)加載到內(nèi)存,再對(duì)內(nèi)存的文件數(shù)據(jù)進(jìn)行修改,然后再重新刷到硬盤里。如果你打開(kāi)很大的word,你的電腦可能會(huì)花費(fèi)較多的時(shí)間加載,就是因?yàn)樵趯⑽募?shù)據(jù)讀入內(nèi)存。

2.12.4 其他模式

二進(jìn)制打開(kāi)文件的三種模式:rb、wb、ab

2.12.5 不占內(nèi)存的修改文件

如果像上面講的那樣,我們將數(shù)據(jù)從硬盤全部讀入到內(nèi)存,然后再對(duì)內(nèi)存的文件數(shù)據(jù)進(jìn)行修改的話,如果文件很大的話,那就會(huì)對(duì)內(nèi)存造成很大影響。

那么我們可以讀取一行數(shù)據(jù)到內(nèi)存然后對(duì)這行數(shù)據(jù)進(jìn)行修改的操作,然后刷入硬盤,周而復(fù)始,就完成了對(duì)整個(gè)文件數(shù)據(jù)的修改。這種方法被稱作邊讀邊寫(xiě)的方法。

將文件中的zm都改為qq

?# -*- encoding: utf-8 -*-
?import os
?
?old_file = 'test.txt'
?new_file = 'test_new.txt'
?f = open(old_file, "r")
?f_new = open(new_file, "w")
?old_str = 'zm'
?new_str = "qq"
?
?for line in f:
? ? ?if "zm" in line:
? ? ? ? ?line = line.replace(old_str, new_str)
? ? ? ? ?f_new.write(line)
?
?f.close()
?f_new.close()
?
?os.replace(new_file, old_file)

2.13 關(guān)于腳本的說(shuō)明

Python原來(lái)就是一種腳本語(yǔ)言,腳本的數(shù)據(jù)獲取是通過(guò)sys模塊的argv()實(shí)現(xiàn)的。

前面沒(méi)講的是,在Python中導(dǎo)入庫(kù)或者模塊,需要用到import語(yǔ)句,并在開(kāi)頭幾行寫(xiě),上面的import os就是一個(gè)例子。

下面我們給出不占內(nèi)存修改文件的腳本寫(xiě)法,主要看5到7行的腳本獲取輸入數(shù)據(jù)。

?import os
?import sys
?
?# 腳本獲取傳入的數(shù)據(jù) 需要在前面寫(xiě),中間不能用其它語(yǔ)句
?old_str = sys.argv[1]
?new_str = sys.argv[2]
?file = sys.argv[3]
?
?new_file = f'new_{file}'
?
?f = open(file, 'r', encoding='utf-8')
?new_f = open(new_file, 'w', encoding='utf-8')
?
?for line in f.readlines():
? ? ?if old_str in line:
? ? ? ? ?new_line = line.replace(old_str, new_str)
? ? ?else:
? ? ? ? ?new_line = line
? ? ?new_f.write(new_line)
?
?f.close()
?new_f.close()
?os.replace(new_file, file)



有什么Python代碼或者其他問(wèn)題可以私信問(wèn)我或者在下面留言,Python課程設(shè)計(jì)我也偶爾可以有償幫做,祝大家變得更強(qiáng)[狗頭]

剩下的就是和上一篇文章末尾一樣要說(shuō)的,我就當(dāng)成套話了。

套話:因?yàn)樾∑普旧系奈谋靖袷綄?duì)演示代碼極其不友好,而且自己平時(shí)的筆記是通過(guò)Markdown語(yǔ)法來(lái)記錄的,在格式上和美觀程度上不是很好看,如果你看的不習(xí)慣,就去下載一個(gè)Typora(或者支持markdown語(yǔ)法的應(yīng)用),我這里給出md文件的迅雷網(wǎng)盤鏈接(百度網(wǎng)盤上傳不了),然后用Typora打開(kāi)文件看就好了。

鏈接:https://pan.xunlei.com/s/VMQbWK_-yU0afk7Eh4eRHm_hA1
提取碼:js9z


2nd Python基礎(chǔ)語(yǔ)法的拓展補(bǔ)充的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
山阴县| 丰宁| 兴和县| 南宫市| 博兴县| 安阳县| 洞口县| 乳山市| 栾城县| 宝应县| 泰顺县| 图木舒克市| 新泰市| 宜兰市| 开阳县| 东山县| 香港 | 龙南县| 丹阳市| 阜南县| 三江| 尼勒克县| 久治县| 河源市| 错那县| 阜平县| 东城区| 汨罗市| 东兰县| 城固县| 玉树县| 永顺县| 郸城县| 社旗县| 北票市| 桂东县| 嘉善县| 塘沽区| 扎兰屯市| 信宜市| 无锡市|