1. 程式人生 > >Python入門 - 2(真0基礎)

Python入門 - 2(真0基礎)

上鎖 ... 新功能 針對 解決方案 target 知識點 但是 param

一 前言

上一章說了那麽多,不知道大家是否有躍躍欲試的沖動。說實話,編程就像英語一樣,只是一門語言,如果不用出來,能力會衰退。就像荒島沒人對話,時間長了很可能就不會說話了。如果不能自己寫出來,永遠就是別人的東西。這就是為什麽很多人看了網絡上那麽多視頻都學不會的原因。是的,可能你也正在看,甚至跟著視頻將代碼敲了下來,但是這些都是別人的。試著問自己一下,關了視頻再寫一遍,能做到嗎?大概率是做不到的。。。怎麽辦?多寫?寫到吐?NO!!! base on project的學習計劃才是有意義的。盲目多寫,或者盲目寫重復的內容只能讓你記住了一部分的寫法,思路不是你的。找一個目標,你喜歡的方向,往那個方向去研究,找那個方向的project去做。舉個例子,我喜歡炒股炒外匯,那就去看一些關於量化交易系統的書或者文章,試著寫一個自動買賣的小系統。為什麽要這樣做?因為持久的學習需要滿足感,需要自信心。當自己寫的程序能跑起來時,那種快感是難以言喻的。當然,無論選擇哪個方向,基礎還是必須打好的,沒有這些基礎,根本無法支撐你走得更遠,更無法達到你的目標,所以,加油!堅持!

二 三元運算(裝13用!!!~~~)

上一章的流程控制,是不是一個if...else...就得分好幾行來寫,難道就不能有一行寫完的表達方式?必須有啊,寫出來還特別有逼格。別人幾百行實現的功能,幾十行就實現了,是不是短小精悍?

# 正常寫法
if 1 < 2:
    val = 1
else:
    val = 2

# 三元運算
val = 1 if 1 < 2 else 2

三 字符編碼

大家在使用電腦的過程肯定都見過一個現象,就是“亂碼”。好好地解壓一個文件,名字變成了亂碼。或者打開一個word文檔,裏面是各種不知名的字符。這些問題大概率都是和字符編碼相關的。最形象的說法就是,你有一把鎖配套一把鑰匙,鎖只能用你的鑰匙來開。要是別人用其他鑰匙硬塞進去,只會弄壞鎖本身。所以,什麽鎖配什麽鑰匙,“上鎖”“解鎖”都用同一把鑰匙就不會出問題了。

1、為什麽需要有字符編碼?

無論你是否科班出身,是否有過編程的經驗,只要你懂點電腦的基本常識,你大概率都會知道計算機只認識二進制,也就是一堆“010101010101”。那西方的英語、西班牙語,東方的國語、韓語、日語等語言,計算機又是怎麽明白的呢?就拿Python作為例子,為什麽我們寫英語,電腦能夠執行?如果說計算機只懂得0和1,是不是會像摩斯密碼一樣,存在一個對照表將我們輸入的內容轉換成0和1?從而破譯出答案來?是的,這就是字符編碼存在的價值。下面是各種字符編碼的簡介,是按照【時間順序】逐一介紹。

2、ASCII碼(American Standard Code for Information Interchange)

最初的版本大概長這個樣子↓↓↓

技術分享圖片

ASCII碼最早在美國被提出,當時發明者根本就沒想過以後中國人也能用上電腦,所以除了英文字母和一些特殊字符能夠對應上,中文和其他語言均沒有對應。後來又拓展了一些,但依然沒有支持其他語言的對應↓↓↓

技術分享圖片

3、GBK(Guo Biao Kuozhan國標擴展的首字母,不要Z可能是因為不好讀吧~~~>.<)

從0開始到255,一共256位就是ASCII碼的極限了,但就連一個邊旁部首都沒有,中國人不樂意啊,中國人也會強大啊,憑什麽我們不能有自己的一席之地?一怒之下,自己搞了個GBK,把中文收編進去,而且不能和ASCII碼有沖突。緊接著其他國家的各種碼也出來了。韓國的EUC-KR,日本的Shift_JIS等等。

4、Unicode

碼是越來越多了,難道以後每個電腦都要預裝這麽多不同的碼麽?更重要的是,預裝一個別的國家的東西,那種不安全感,就像要強迫出廠的蘋果手機預裝小米軟件一樣。所以,針對這種需求,萬國碼出現了。終於有一個看上去啥都有的百科全書了。但是有一部分人開始不高興了。你可能不知道,ASCII碼對於英語字符是非常節省的,一個字符只需要1個Bytes,也就是1個B。而在Unicode裏,為了配合其他語言,一個英語字符變成了2個B。無端端多了一倍。。。一兩個字符不是問題,但問題是,多起來怎麽辦?!在那個年代,內存是極其珍貴的,網絡是很慢的,內容多了,肯定慢。我本來可以存的內容,因為Unicode這麽一搞,能存的東西就減半了。有解決方案嗎?繼續看下去。。。

Bit,計算機中最小的表示單位
8Bit = 1Bytes 字節,最小的存儲單位,1Bytes縮寫為1B
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB
1EB = 1024PB
1ZB = 1024EB
1YB = 1024ZB
1BB = 1024YB

5、UTF-8(Unicode Transformation Format)

為了節約內存,UTF-8誕生了,對Unicode進行了一些加工,將英文字母編寫成1個字節,將漢字編寫成3個字節,對非常生僻的字符才用4-6個字節。這樣解決了英文字母占用內存倍增的問題,也讓各國的編碼整合了。算是現時最完善的編碼了。但是這一切都是按時間順序發生進而完善的,那原本那些已經用GBK、ASCII編碼存好的程序怎麽辦?如果硬生生換編碼,從硬盤讀取到內存時程序肯定會出現各種異常,可能冒這個險嗎?根本不可能!!!幾百萬行代碼重新寫嗎?想太多!!!那怎麽辦?(咋問題這麽多(-_ -!!!))其實上面的內容已經有答案了。Unicode就是答案。反正Unicode整合了這麽多個國家的編碼,只要用Unicode這把萬能鑰匙去解鎖,就一定能不損壞鎖又能開鎖。現在的計算機基本上是這麽幹的,在內存中用的是Unicode,在硬盤中和傳輸中用的是UTF-8。舉個例子,我們打開一個文件,文件會進入內存,這個時候會轉換為Unicode。然後在保存時,文件會進入硬盤,這個時候就會轉換成UTF-8。

技術分享圖片

6、字符編碼的轉換

總結:什麽鑰匙開什麽鎖。用什麽編碼存到硬盤的,就得用什麽編碼取出來。

最後拋出一個問題。假設現在有兩臺電腦,一臺是日本產的,預裝有Unicode和Shift-JIS日本編碼,一臺是中國產的,預裝有Unicode和GBK中文編碼。如果在中國產的電腦上編寫好文件,在日本產的電腦上打開,能顯示中文嗎?

答案是可以的。文件會先從GBK轉換成Unicode存到內存裏,可以讀取到中文,自然可以顯示中文。

技術分享圖片

四 文件處理

讀寫文件在Python中是常見的事情。因為暫時不知道數據庫如何使用,所以很多臨時的數據只能夠格式化存到文檔中(也就是存到硬盤裏,不用怕存到內存一斷電就沒了)。以下是一般的文件操作思路:

#1 打開文件,得到文件內容並賦值給一個變量
#2 修改文件內容,增刪改查等方式
#3 將修改的文件內容存回文件
#4 關閉文件

1、讀文件,“r”模式

#1 打開文件nick.txt,並賦值給變量f,方便後續操作用
f = open(nick.txt, r, encoding=utf-8)  # 默認打開模式就為r

#2 通過read命令獲得變量f的內容,並賦值給變量data,方便對內容進行增刪改查
data = f.read()  # 讀取所有內容
data = f.readline()  # 讀取一行內容
data = f.readlines()  # 讀取每一行內容,並存放在列表

#3 關閉文件
f.close()

2、寫文件,“w”模式

#1 以“w”模式打開文件nick.txt,並賦值給變量f,方便後續操作用
f = open(nick.txt, w, encoding=utf-8)

#2 通過write命令覆蓋變量f的內容
f.write("01010101")  # 註意!原內容會被覆蓋!
f.writelines("0101010101")  # 當需要將多行內容寫入txt文件時用這個

#3 關閉文件
f.close()

3、加內容,“a”模式

#1 以“a”模式打開文件nick.txt,並賦值給變量f,方便後續操作用
f = open(nick.txt, a, encoding=utf-8)

#2 通過write命令覆蓋變量f的內容
f.write("\n01010101")  # 註意!新內容會追加在原內容的後面!

#3 關閉文件
f.close()

五 函數(終於要邁入一個稍微有點難度的部分喇~~~散花~~~)

能學到這裏,證明你對最最最基礎的語法已經有了一定的了解。現在寫幾十行甚至上百行代碼實現一些基本功能已經不是問題了。或許你已經感受到,寫代碼時經常會重復用到一些語句,而且頻次還較高,這樣看起來很low,如果能有辦法將這些常用的語句整合到一個地方,然後每次調用這個地方的內容,就不用重復寫同一些代碼了,對不?所以函數就出現了!!!這裏的函數不是數學中常說的函數,而是這類重復功能歸集到一起的統稱。

這部分之所以說是上升了一個難度,並不是說內容難,而是因為你如果不用函數,依然可以實現功能。而用函數能讓代碼優雅,更容易被維護。這是一種思維層次的改變,並不是你學懂了就能用出來的。換句話說,如果你沒有編程經驗,你怎麽知道某些方法會重復?你怎麽知道某些代碼會被經常使用?所以沒有經驗的時候,是無法順利用出函數的。對於入門者,這是一道坎!只有告訴自己,即使代碼low,先寫,重復就重復,通過第二版去將重復的內容寫成函數,不斷修改和優化代碼。切忌一步登天。也不要因為寫不出函數而氣餒。說到底,就是積累得還不夠而已。解釋完函數存在意義,我們一起來看看函數的分類。

1、函數分類

# 使用函數前必須要先定義函數,再使用。就像先有了一只籃球,才能開始一場籃球比賽一樣。定義函數,可以是內置的,也可以是自定義的:

#1 內置函數
還記得之前我們在人與機器交互那小節中提及的input功能嗎?其實這裏的input就是一種函數,而且是被內置好的,也就是啟動Python時就會附帶定義好的。這是為了方便開發時,不用再針對一些簡單的功能重復定義。對於內置函數,我們可以拿來就用而無需事先定義,見下表。

#2 自定義函數
由於內置函數的功能都相對簡單,並無法應對復雜的需求。這就需要我們自己根據需求,事先定制好我們自己的函數來實現某種功能,在遇到應用場景時,調用自定義的函數即可。例如在一次計算中,我們可以定義一個函數來處理加法,只需要將內容傳進去,就會返回加法的結果。

以下是常用的內置函數↓↓↓

技術分享圖片

2、如何自定義函數

# 邏輯大概是這樣的:

def 函數名(參數1,參數2,參數3,...):  # 定義了函數,函數名最好能夠精煉概括要做的事情
    ‘‘‘註釋‘‘‘
    函數體  # 具體函數要做的事情,函數的主體內容
    return 返回的值  # 讓函數結束時返回一個東西,可以返回值,甚至函數,遇到return語句,函數就會停止執行並返回結果

# 舉個栗子

def id_verification(account, password):
    ”””
    定義了一個id驗證函數用於驗證輸入賬號是否正確。
    :param account: 賬號
    :param password: 密碼
    :return: 認證結果
    ”””
    if account == nick and password == 1234:  
        return Welcome back!
    else:
        return invalid account or password

3、調用函數

# 定義了函數就是為了用,不然定義來幹嘛對不對?那如何調用呢?就像上面的栗子,如果要調用id_verification函數,可以這樣寫

account = input(account:).strip()
password = input(password:).strip()

id_verification(account, password)  # 調用函數,並傳入account和password兩個參數,如果僅僅只有id_verification,沒有括號,函數是不會被調用的

# 調用函數後,參數會被送進函數進行運算。最終得出結果取決於自定義函數的返回值。有時候定義函數不一定要傳入參數。像下面的例子,括號裏是空的。

4、函數參數

# 談到函數的參數,就要知道什麽叫實參和形參,簡單理解即可

def calc(x, y):  # 這裏的x和y就是形參,等著別人賦值給自己
    res = x ** y
    return res

c = calc(1, 2)  # 這裏的1和2就是實參,等著傳值給別人
print(c)

# 了解完什麽是形參和實參後,我們來看看一些更實用的例子。

def register(name, age, country):  # 定義一個函數,讓用戶傳入基礎資料並打印
    print("name:", name)
    print("age:", age)
    print("country:", country)

register("nick", 18, "China")
...

# 關鍵參數
# 如果100個用戶都是來自於中國,那其實可以設置一個默認值,這個時候就出現了關鍵參數

def register(name, age, country="China"):
    print("name:", name)
    print("age:", age)
    print("country:", country)

register("nick", 18)  # 這樣就不用輸入了~100個用戶都省了事
register("alex", 18, country="USA")  # 當出現一個特殊的,這樣寫就好了
...


# 非固定參數
# 對於在定義函數時不知道將來會傳什麽進來的,可以這樣寫

def register(name, age, *args, **kwargs):
    print(name, age, args, kwargs)

# 調用函數
register("nick", 18, "China", "Guangdong", course="Python", gender="male")
# 輸出
# nick 18 (China, Guangdong) {‘course‘= ‘Python‘, ‘gender‘= ‘male‘}
...

# *args會生成一個元組
# **kwargs會生成一個字典

5、嵌套函數

# 其實在函數裏面,也是可以調用已定義好的函數,也可以定義函數。

def f1():  # 定義函數f1
    print(f1)

def f2():  # 定義函數f2
    def f3():  # 在函數f2內定義函數f3
        print(f3)
    f3()  # 執行函數f3,如果沒有這一行,則不會執行函數f3
    print(f2)

def f4():
    f1()
    f2()  # 調用已定義好的函數f2

# 這種函數套函數,就是嵌套函數,在以後的編程會較為常用,很鍛煉邏輯的哦~

6、高階函數

# 函數裏面的參數不僅可以接收變量,也可以接收其他函數,一起看這個高階函數例子

def add(x, y, func):
    print(func(x) + func(y))  # 兩數絕對值相加

add(1, 2, abs)  # abs是內置函數,代表絕對值

7、遞歸

# 如果一個函數在內部調取自己,就叫遞歸

def calc(n)
    print(n)
    if int(n / 2) == 0:
        return n
    return calc(int(n / 2))


calc(10)
#輸出
10
5
2
1

8、名稱空間

# 上面的例子裏存在一個問題,我們可以直接輸入f1(), f2()或f4()來調用函數,但我們無法直接輸入f3()調用函數f3,這樣會報錯,那是為什麽呢?

# 簡單來說,就是因為函數f3在函數f2內,函數f3在局部,並不是全局。在全局的位置查看不了局部,但是在局部可以查看全局。就像上面的函數f4裏,可以在局部調用全局的函數f1和f2。

# 復雜來說,就需要引入名稱空間這個新名詞。名稱空間儲存的是變量名和變量值的關系。例如n = 1,名稱空間就儲存著n和1的關系。

# 計算機在查找名稱空間的過程是有順序的,先查看局部的名稱空間,然後才是全局的名稱空間,這就是為什麽當計算機在找到局部名稱空間時,可以找到全局名稱空間。反之則不可以。屬於先後順序問題!

# 完整來說,整個名稱空間查找順序可以簡寫為4個字母:LEGB 也稱為作用域。

Locals 是函數內的名稱空間
Enclosing 上一級嵌套函數的名稱空間(閉包中常見,後面會講閉包)
Globals 全局變量,函數定義所在模塊的名稱空間
Builtins 內置模塊的名稱空間 

9、匿名函數

# 記住一個詞,叫lambda;lambda函數常與其他函數搭配使用,從而節省代碼量,看一下下面的例子。

# 一般來說,如果要計算一堆數各自的平方,我們需要先定義一個計算平方的函數,然後再通過map內置函數,將數導進去進行平方,看代碼↓↓↓

def square(x):
    return x ** 2

list(map(square, [1, 2, 3, 4, 5]))  # 由於是內置函數,不用定義直接使用,得到一個列表

# 如果用lambda,就可以節省一些代碼,不用定義square函數,直接套進map函數使用

list(map(lambda x: x ** 2, [1, 2, 3, 4, 5]))

# 對於那種不常用的功能,可以通過lambda來節省代碼,用完即棄。

10、閉包(開始有點深度了哦~)

# 函數裏套了函數,外層函數被調用時,返回了內層函數的內存地址,執行內層函數時,內層函數調用外層函數局部變量的值,這種關系就是閉包。一起看下面這個例子

def outer(x):
    def inner(y):
        return x + y
    return inner  # 只返回了inner的內存地址,沒有括號,沒有執行inner函數

a = outer(2)  # 執行了外層outer函數
print(a)
返回了inner的內存地址

print(a(3))  # 執行inner函數,inner函數調用了外層函數的局部變量x = 2
返回了5

11、裝飾器(又叫做語法糖,是函數章節較難的部分,很難啃~~做好心理準備,啃下去你就贏了~~>3<)

很多程序已經寫完,且經過大量用戶使用後,已無其他bug反饋,就可以認為該程序已經能穩定運行了。如果要增加新功能,有一個約定俗成的原則就是不能修改已經穩定運行的程序,只能加,不能改,畢竟誰都不是神,誰都無法保證改了之後是否會產生新的bug,特別是上百萬行代碼的程序,一旦發現新的bug,debug起來不是開玩笑的。因此,必須要用特定的方法去加入新功能,這個時候就有了裝飾器存在的價值。一起看下面這個例子。

# 假設我一開始寫了這些代碼(假設有幾十萬行),並且經過了長久驗證,已穩定運行。

def bar():  # 定義了函數bar,用來打印某段話。
    print("I am bar")  # 假設這裏是幾十萬行代碼,有各種復雜的邏輯
    ...

bar() # 執行該函數

# 如果我突然想加一個功能,希望用戶輸入自己的名字後,才執行這幾十萬行代碼,我不能動這些穩定運行的代碼。所以我只能用裝飾器,加功能。我們先感性認識一下裝飾器長什麽樣子。接下去會一步一步解釋。

def login(func):  # 在原本的幾十萬行代碼上,加入了這麽一個【裝飾器】(函數)
    def collect_name(*args, **kwargs):  # 函數裏套了函數
        input("name:")  # 讓用戶輸入名字
        return func(*args, **kwargs)  # 返回了外層函數參數名的函數(與閉包概念類似)
    return collect_name  # 返回內層函數的內存地址,註意這裏沒有括號,所以是返回內存地址,而不是執行函數


@login  # 語法糖,讓下面的函數不止運行自己,還運行與語法糖同名的函數
def bar():  # 定義了函數bar,用來打印某段話。
    print("I am bar")  # 假設這裏是幾十萬行代碼,有各種復雜的邏輯
    ...


bar()  # 執行該函數,調用bar函數的同時,調用login函數,這樣就做到了沒有動原本的代碼,又增加了新功能的目的

# 下面我們來一步一步分析這個運行過程,請按照【數字順序】閱讀,建議多看幾遍,一遍是看不懂的

def login(func):  # 2、因為語法糖的原因,這裏的函數綁定成login(bar)
    def collect_name(*args, **kwargs):  # 5、執行了login函數內部的collect_name函數
        input("name:")  # 6、讓用戶輸入名字
        return func(*args, **kwargs)  # 7、執行bar函數
    return collect_name  # 3、不執行內部函數,直接將collect_name內存地址(不帶括號時)返回


@login  # 1、程序經過了上面的函數login,再來到這個語法糖。這個語法糖的目的是綁定下面這個函數bar,當執行下面這個函數bar時,也同時調用與語法糖同名的函數login。
def bar():  
    print("I am bar")  # 8、執行並打印
    ...


bar()  # 4、執行該函數,實際上會執行了函數bar本身,也執行了函數login(bar)(),也就是collect_name函數

四 生成器和叠代器

# 生成器
g = (x * x for x in range(10))

>>>next(g)
1

>>>next(g)
4

>>>next(g)
9

>>>next(g)
16

>>>next(g)
25

# 如果所有值都需要next去調出,會瘋掉的吧。不如用for,值用完了還不會報錯
g = (x * x for x in range(10))
for n in g:
    print(n)

# 叠代器

# 判斷一個對象是否為可叠代對象

from collections import Iterable
a = isinstance([], Iterable)
print(a)

# 返回True

# 判斷一個對象是否為叠代器
from collections import Iterable
b = isinstance([], Iterator)
print(b)

# 返回False

# 將其轉成叠代器,用itor函數
from collections import Iterable
b = isinstance(iter([]), Iterator)
print(b)

# 返回True

五 模塊

終於送走了函數,說明在中級的路上已越走越穩了。別忘記多做project,將上面的內容用在實戰中。有一件事是可以肯定的,如果你曾經用過某個知識點,並且解決了問題,這個知識點會記得比其他都要牢固。不斷用,不斷試錯。加油!!!

模塊這一部分,簡直就是Python的精華所在。為什麽近年來Python越來越多人用?那是因為不同的功能模塊越來越完善。(不禁感嘆這個世界牛人真多啊~~~)大神們通過自己的努力,將寫好的Python文件打包,放到網上,讓大家隨意下載使用。這些模塊覆蓋的細分領域越來越廣,從金融、醫療、數學到高新科技,幾乎一切你能想象的領域都有現成的模塊可以下載。大家如果想多了解更多模塊可以到這個網址https://pypi.python.org/pypi,根據自己喜歡的方向去尋找吧~~或許在不久的將來,你也能上傳你的作品。

模塊的存在大大節省了我們的開發時間,畢竟大神已經為我們準備好的工具,不用白不用,對吧?那我們先來看看模塊分了幾種:

1、模塊分類

# 內置標準模塊。有一些模塊在安裝Python時就會一並裝入。可以理解為官方版本的模塊。

# 第三方開源模塊。由世界各地的大神撰寫並上傳,我們可以通過Pycharm等下載安裝使用。

# 自定義模塊。就是自己寫出來的程序,自己打包,自己用。

2、模塊調用

# 有不少表達式可以用來導入模塊,根據不同情況而定,常用的有以下幾種:

import module

from module import settings

from . import module

# 是時候動起來了。快!動手打開Pycharm,建個文件夾printer,文件夾裏新建兩個py文件,分別寫入以下內容。如下

# printer文件夾

  # test.py文件

  from hello import say_hi

  say_hi()


  # hello.py文件

  def say_hi():
      print("hello world")


# 概括點來說,這兩個文件其實可以看作是一個程序,目的是打印某句話。test文件作為程序入口,調用其他模塊來輔助實現這個功能。

# 包(Package)

# 上面的例子,我們用了一個文件夾,兩個py文件,實現了打印某句話的功能程序。這類打印功能我們就統一放在printer這個文件夾裏。像這樣一個文件夾裏存放多個模塊文件,就稱這個文件夾為【包】

# 上面的printer文件夾,為了能成為包,還需要在文件夾中加入__init__.py文件,從而告訴程序這是個包

# 像一些比較大型的項目,如微信等,也是將不同功能用不同包分開,例如朋友圈功能和聊天功能分開等。。然後包和包之間互相調用來實現功能。這是為了更加方便運維團隊維護代碼

# 為了調取不同包裏的模塊,有時候需要鋪設好一條路。就像鐵路一樣,通了才有火車的身影

# 下面的例子,為了能夠讀取到另外一個文件夾account下的json文件,我們需要鋪出一條路給程序,為此需要用到兩個內置模塊,os和sys,下面就導入一下

import sys
import os

# 當前文件路徑向上返回兩級,將路徑賦值於DIR(大寫表示常量,代表不變)
DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 將這條路加入到環境變量裏面,這樣Python才會去找這條路找文件
sys.path.append(DIR)
# 往DIR路徑後加入account和json.json,拼接出json文件的完整路徑,可以直接用於open
os.path.join(DIR, account, json.json)

3、time模塊

# time模塊是常常用來顯示、計算各種格式的時間,下面是幾個常用的,我們暫時不求多,只求用得著

time.time()  # 返回當前時間的時間戳(就是一串數字)

time.sleep()  # 延遲執行,括號裏寫上時間即可,單位為秒。

time.strftime()
# 舉例:time.strftime("%Y-%m-%d %X", time.localtime()) 
# 輸出‘2018-07-06 00:00:00‘

4、random模塊

# 直接來看兩個例子

# 生成隨機6位數密碼,是不是和一些網站登錄時要你輸入的驗證碼很像
import random
import string

numbers = " ".join(random.sample(string.ascii_lowercase + string.digits, 6))
print(numbers)  # 這樣每次打印都會是不同的6位數字或字母,而且沒有空格

# 洗牌功能
import random

a = [0, 1, 2, 3, 4, 5]
random.shuffle(a)
print(a)  # 列表a的順序會被打亂

5、json模塊

# json模塊可以存儲字典,而之前我們常用的txt文件存不了字典
import json

data = {"name": "nick", "age": 18}

# 將data寫入json文件
with open("nick.json", "w", encoding="utf-8") as db:
    json.dump(data, db)
    db.close()

# 讀取nick.json文件中的字典,並賦值給nick_data
with open("nick.json", "r", encoding="utf-8") as db:
    nick_data = json.load()
    db.close()

6、logging模塊

# logging模塊是非常常用的生成日誌的模塊。程序執行時,如果沒有日誌記錄,有很多信息會有缺失,甚至不清楚誰登陸過,誰做過什麽,這樣是非常不安全的。因此,這個模塊十分十分重要。看下面的步驟,可以配置好不同的日誌內容

# 下面這個例子,是配置日誌內容的過程,目的是在文件和Pycharm消息框中同時輸出內容,不妨復制到Pycharm試一試
import logging

# 1. 生成logger對象
logger = logging.getLogger("web")  # 相當於給日誌起了個名字web
logger.setLevel(logging.DEBUG)  # 如果不設置默認級別是WARNING,此為全局

# 2. 生成handler對象
ch = logging.StreamHandler()  # 輸出到屏幕
ch.setLevel(logging.INFO)  # 給不同輸出途徑設置不同的輸出日誌級別,設置級別不能比全局的低

fh = logging.FileHandler("web.log")  # 輸出到文件
fh.setLevel(logging.WARNING)  # 給不同輸出途徑設置不同的輸出日誌級別,設置級別不能比全局的低

# 2.1 把handler對象綁定到logger
logger.addHandler(ch)
logger.addHandler(fh)

# 3. 生成formatter對象,用於自定義格式化輸出內容
# 3.1 把formatter對象綁定handler對象
file_formatter = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(message)s)
console_formatter = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s  -  %(lineno)d - %(message)s)

ch.setFormatter(console_formatter)
fh.setFormatter(file_formatter)


logger.error(test log)
logger.error(test log 2)

7、re模塊

# 正則表達式也是一個常用的模塊,甚至有的Python開發書一上來第一章第一節就講正則表達式。爬蟲等工序到最後需要用正則表達式格式化輸出內容。不妨通過下面的例子看看,復制到Pycharm上玩一玩吧。不過,看完後盡量自己寫一遍哦!
import re

# re.match 從頭開始匹配
s = abc1d3e
b = re.match([0-9], s)  # 要求第一個值必須是數字,否則返回None
print(b:, b)

f = 12bdfd
c = re.match([0-9], f)  # 默認只能匹配到一個值
print(c:, c)

# re.search 匹配包含,全局匹配
e = re.search([0-9], s)
print(e:, e)

# re.findall 匹配上值,然後以列表形式保存
g = re.findall([0-9], s)
print(g:, g)

# re.split 以匹配到的字符當做列表分隔符
s = alex22jack23rain31jinxin50|mack-Oldboy
print(re.split(\d+|\||\W| , s))  # ‘|‘本身作為或標識符,需要前面加‘\‘才能用於分隔

s = alex22jack23rain\jinxin50|mack-Oldboy
print(re.split(\d+|\\\\|\||\W| , s))  # ‘\‘本身作為標識符需要用4個才能表示一個

# re.sub 匹配字符並替換
s = alex22jack23rain31jinxin50|mack-Oldboy
print(re.sub(\d+|\||\W, _, s))  # 替換掉數字

h = 9-2*5/3+7/3*99/4*2998+10*568/14
print(re.split([-\*/+], h))
print(re.split(\W, h))

i = "[email protected]"
j = re.fullmatch("\w+@\w+\.(com|cn|edu|org)", i)
print(j)

Python入門 - 2(真0基礎)