Python-基礎學習-第二輪
數據類型
Python 默認擁有以下內置數據類型:
| 文本類型: | str |
|---|---|
| 數值類型: | int, float, complex |
| 序列類型: | list, tuple, range |
| 映射類型: | dict |
| 集合類型: | set, frozenset |
| 布爾類型: | bool |
| 二進位類型: | bytes, bytearray, memoryview |
在 Python 中,當您為變數賦值時,會設置數據類型:
| 示例 | 數據類型 |
|---|---|
| x = "Hello World" | str |
| x = 29 | int |
| x = 29.5 | float |
| x = 1j | complex |
| x = ["apple", "banana", "cherry"] | list |
| x = ("apple", "banana", "cherry") | tuple |
| x = range(6) | range |
| x = {"name" : "Bill", "age" : 63} | dict |
| x = {"apple", "banana", "cherry"} | set |
| x = frozenset({"apple", "banana", "cherry"}) | frozenset |
| x = True | bool |
| x = b"Hello" | bytes |
| x = bytearray(5) | bytearray |
| x = memoryview(bytes(5)) | memoryview |
如果希望指定數據類型,則您可以使用以下構造函數:
| 示例 | 數據類型 |
|---|---|
| x = str("Hello World") | str |
| x = int(29) | int |
| x = float(29.5) | float |
| x = complex(1j) | complex |
| x = list(("apple", "banana", "cherry")) | list |
| x = tuple(("apple", "banana", "cherry")) | tuple |
| x = range(6) | range |
| x = dict(name="Bill", age=36) | dict |
| x = set(("apple", "banana", "cherry")) | set |
| x = frozenset(("apple", "banana", "cherry")) | frozenset |
| x = bool(5) | bool |
| x = bytes(5) | bytes |
| x = bytearray(5) | bytearray |
| x = memoryview(bytes(5)) | memoryview |
文件
open函數的參數
要讀寫文件,首先要通過內置函數open 打開文件,獲得文件對象。
函數open的參數如下
open(
file,
mode='r',
buffering=-1,
encoding=None,
errors=None,
newline=None,
closefd=True,
opener=None
)
其中下面這3個參數是我們常用的。
-
參數 file
file參數指定了要打開文件的路徑。
可以是相對路徑,比如 『log.txt』, 就是指當前工作目錄下面的log.txt 文件, 也可以是絕對路徑,比如 』d:\project\log\log.txt', -
參數 mode
mode參數指定了文件打開的
模式,打開文件的模式,決定了可以怎樣操作文件。常用的打開模式有
- r 只讀文本模式打開,這是最常用的一種模式
- w 只寫文本模式打開
- a 追加文本模式打開
如果我們要 讀取文本文件內容到字元串對象中 , 就應該使用 r 模式。
我們可以發現mode參數的預設值 就是 『r』 。
就是說,調用open函數時,如果沒有指定參數mode的值,那麼該參數就使用預設值 『r』,表示只讀打開。
如果我們要 創建一個新文件寫入內容,或者清空某個文本文件重新寫入內容, 就應該使用 『w』 模式。
如果我們要 從某個文件末尾添加內容, 就應該使用 『a』 模式。
-
參數 encoding
encoding 參數指定了讀寫文本文件時,使用的 字元編解碼 方式。
調用open函數時,如果傳入了encoding參數值:
後面調用write寫入字元串到文件中,open函數會使用指定encoding編碼為位元組串; 後面調用read從文件中讀取內容,open函數會使用指定encoding解碼為字元串對象如果調用的時候沒有傳入encoding參數值,open函數會使用系統預設字元編碼方式。 比如在中文的Windows系統上,就是使用cp936(就是gbk編碼)。
建議大家編寫程式碼 讀寫文本文件時,都指定該參數的值。
if __name__ == '__main__':
# 指定編碼方式為 utf8
f = open('D:/Code2022/Python/pythonProjectStudy/table_contents/tmp.txt', 'w', encoding='utf8')
# write方法會將字元串編碼為utf8位元組串寫入文件
f.write('李嘉圖:祝大家學有所成!')
# 文件操作完畢後, 使用close 方法關閉該文件對象
f.close()
# 指定編碼方式為utf8
f = open('D:/Code2022/Python/pythonProjectStudy/table_contents/tmp.txt', 'r', encoding='utf8')
# read 方法會在讀取文件中的原始位元組串後, 根據上面指定的gbk解碼為字元串對象返回
content = f.read()
# 文件操作完畢後, 使用close 方法關閉該文件對象
f.close()
# 通過字元串的split方法獲取其中用戶名部分
name = content.split(':')[0]
print(name)
with
if __name__ == '__main__':
f = open('D:/Code2022/Python/pythonProjectStudy/table_contents/tmp.txt', 'w', encoding='utf8')
f.write('李嘉圖:祝大家學有所成!')
f.close()
with open('D:/Code2022/Python/pythonProjectStudy/table_contents/tmp.txt', 'r', encoding='utf8') as f:
linelist = f.readlines()
for line in linelist:
print(line)
附加:文件和目錄
自調用其他程式
Python中調用外部程式主要是通過兩個方法實現的, 一個是os庫的
system函數,另外一個是subprocess庫。
os.system函數
使用os庫的 system 函數 調用其它程式 是非常方便的。就把命令行內容 作為 system 函數的參數 即可
import os
if __name__ == '__main__':
os.system('cd D:/test && mkdir test.txt')
os.system 函數調用外部程式的時候, 必須要等被調用程式執行結束, 才會接著往下執行程式碼。 否則就會一直等待。
os.system 函數沒法獲取 被調用程式輸出到終端窗口的內容。 如果需要對被調用程式的輸出資訊進行處理的話, 可以使用 subprocess 模組。
os.startfile 函數
如果我們想達到類似文件瀏覽器雙擊打開一個文件的效果可以使用 os.startfile 函數。
這個函數的參數可以是任何 非可執行程式 文件
os.startfile('d:\\統計數據.xlsx')
可以調用該xlsx對應的關聯程式(Excel)來打開該文件。
subprocess 模組
Popen 是 subprocess的核心,子進程的創建和管理都靠它處理。
- //cloud.tencent.com/developer/article/1445388
- //docs.python.org/zh-cn/3.9/library/subprocess.html?highlight=subprocess#module-subprocess
執行緒和進程
創建新執行緒
# 從 threading 庫中導入Thread類
from threading import Thread
from time import sleep
# 定義一個函數,作為新執行緒執行的入口函數
def threadFunc(arg1, arg2):
print('子執行緒 開始')
print(f'執行緒函數參數是:{arg1}, {arg2}')
sleep(5)
print('子執行緒 結束')
if __name__ == '__main__':
print('主執行緒執行程式碼')
# 創建 Thread 類的實例對象
thread = Thread(
# target 參數 指定 新執行緒要執行的函數
# 注意,這裡指定的函數對象只能寫一個名字,不能後面加括弧,
# 如果加括弧就是直接在當前執行緒調用執行,而不是在新執行緒中執行了
target=threadFunc,
# 如果 新執行緒函數需要參數,在 args裡面填入參數
# 注意參數是元組, 如果只有一個參數,後面要有逗號,像這樣 args=('參數1',)
args=('參數1', '參數2')
)
# 執行start 方法,就會創建新執行緒,
# 並且新執行緒會去執行入口函數裡面的程式碼。
# 這時候 這個進程 有兩個執行緒了。
thread.start()
# 主執行緒的程式碼執行 子執行緒對象的join方法,
# 就會等待子執行緒結束,才繼續執行下面的程式碼
thread.join()
print('主執行緒結束')
共享數據的訪問控制
from threading import Thread, Lock
from time import sleep
bank = {
'count': 0
}
bankLock = Lock()
# 定義一個函數,作為新執行緒執行的入口函數
def deposit(theadidx, amount):
# 操作共享數據前,申請獲取鎖
bankLock.acquire()
balance = bank['count']
# 執行一些任務,耗費了0.1秒
sleep(0.1)
bank['count'] = balance + amount
print(f'子執行緒 {theadidx} 結束')
# 操作完共享數據後,申請釋放鎖
bankLock.release()
if __name__ == '__main__':
theadlist = []
for idx in range(10):
thread = Thread(target=deposit,
args=(idx, 1)
)
thread.start()
# 把執行緒對象都存儲到 threadlist中
theadlist.append(thread)
for thread in theadlist:
thread.join()
print('主執行緒結束')
print(f'最後我們的帳號餘額為 {bank["count"]}')
deamon執行緒
from threading import Thread
from time import sleep
def threadFunc():
sleep(1)
print('子執行緒 結束')
if __name__ == '__main__':
# thread = Thread(target=threadFunc)
# thread.start()
# print('主執行緒結束')
thread = Thread(target=threadFunc,
daemon=True # 設置新執行緒為daemon執行緒
)
thread.start()
print('daemon主執行緒結束')
多執行緒
Python 官方解釋器 的每個執行緒要獲得執行許可權,必須獲取一個叫 GIL (全局解釋器鎖) 的東西。
這就導致了 Python 的多個執行緒 其實 並不能同時使用 多個CPU核心。
所以如果是計算密集型的任務,不能採用多執行緒的方式。
from threading import Thread
def f():
while True:
b = 53*53
if __name__ == '__main__':
plist = []
# 啟動10個執行緒
for i in range(10):
p = Thread(target=f)
p.start()
plist.append(p)
for p in plist:
p.join()
多個CPU核心的運算能力,可以使用Python的多進程庫。
from multiprocessing import Process
def f():
while True:
b = 53*53
if __name__ == '__main__':
plist = []
for i in range(2):
p = Process(target=f)
p.start()
plist.append(p)
for p in plist:
p.join()
from multiprocessing import Process, Manager
from time import sleep
def f(taskno, return_dict):
sleep(1)
# 存放計算結果到共享對象中
return_dict[taskno] = taskno
if __name__ == '__main__':
manager = Manager()
# 創建 類似字典的 跨進程 共享對象
return_dict = manager.dict()
plist = []
for i in range(10):
p = Process(target=f, args=(i, return_dict))
p.start()
plist.append(p)
for p in plist:
p.join()
print('get result...')
# 從共享對象中取出其他進程的計算結果
for k, v in return_dict.items():
print(k, v)
JSON
序列化和反序列化
Python中內置了json這個庫,可以 方便的把內置的數據對象 序列化為json格式文本的字元串。
import json
historyTransactions = [
{
'time': '20300101070311', # 交易時間
'amount': '3088', # 交易金額
'productid': '45454455555', # 貨號
'productname': 'iphone30' # 貨名
},
{
'time': '20300101050311', # 交易時間
'amount': '18', # 交易金額
'productid': '453455772955', # 貨號
'productname': '餅乾' # 貨名
}
]
if __name__ == '__main__':
# dumps 方法將數據對象序列化為 json格式的字元串
jsonstr = json.dumps(historyTransactions)
print(jsonstr)
import json
historyTransactions = [
{
'time': '20300101070311', # 交易時間
'amount': '3088', # 交易金額
'productid': '45454455555', # 貨號
'productname': 'iphone30' # 貨名
},
{
'time': '20300101050311', # 交易時間
'amount': '18', # 交易金額
'productid': '453455772955', # 貨號
'productname': '餅乾' # 貨名
}
]
if __name__ == '__main__':
# dumps 方法將數據對象序列化為 json格式的字元串
jsonstr = json.dumps(historyTransactions)
print(jsonstr)
print('================')
print(json.dumps(historyTransactions, ensure_ascii=False, indent=4))
print('================')
jsonstr = '[{"time": "20300101070311", "amount": "3088", "productid": "45454455555", "productname": "iphone7"}, {"time": "20300101070311", "amount": "18", "productid": "453455772955", "productname": "\u5999\u5999\u5999"}]'
translist = json.loads(jsonstr)
print(translist)
print(type(translist))
裝飾器
Python中裝飾器通常用來裝飾函數、或者類的方法。
通常被裝飾後的函數, 會在原有的函數基礎上,增加一點功能。
裝飾器經常被用在庫和框架中, 給別的開發者使用。
這些庫的開發者預料到 使用者 開發的函數可能需要 一些增強的功能。
但是 這些庫的開發者 沒法去改使用者的程式碼, 就可以把這些增強的部分做在 裝飾器函數中。
這樣使用者,只需要在他們的函數前面上@xxx 就使用了這些增強的功能了。
基礎示例:
import time
# 定義一個裝飾器函數
def sayLocal(func):
def wrapper():
curTime = func()
return f'當地時間: {curTime}'
return wrapper
@sayLocal
def getXXXTime():
print()
return time.strftime('%Y_%m_%d %H:%M:%S', time.localtime())
if __name__ == '__main__':
# 裝飾 getXXXTime
# getXXXTime = sayLocal(getXXXTime)
print(getXXXTime())
進階示例-被裝飾的函數有參數:
import time
def sayLocal(func):
def wrapper(*args, **kargs):
curTime = func(*args, **kargs)
return f'當地時間: {curTime}'
return wrapper
@sayLocal
def getXXXTimeFormat1(name):
curTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
return f'{curTime} ,數據採集者:{name} '
@sayLocal
def getXXXTimeFormat2(name, place):
curTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
return f'{curTime} ,數據採集者:{name} , 採集地:{place}'
if __name__ == '__main__':
print(getXXXTimeFormat1('張三'))
print(getXXXTimeFormat2('張三', place='北京'))
進階示例-裝飾器函數自身有參數:
# 添加輸出日誌的功能
def logging(flag):
def decorator(fn):
def inner(num1, num2):
if flag == "+":
print("--正在努力加法計算--")
elif flag == "-":
print("--正在努力減法計算--")
result = fn(num1, num2)
return result
return inner
# 返回裝飾器
return decorator
# 使用裝飾器裝飾函數
@logging("+")
def add(a, b):
result = a + b
return result
@logging("-")
def sub(a, b):
result = a - b
return result
if __name__ == '__main__':
result = add(1, 2)
print(result)
result = sub(1, 2)
print(result)
加密
| 演算法 | 計算結果長度 |
|---|---|
| MD5 | 16位元組 |
| SHA1 | 20位元組 |
| SHA224 | 28位元組 |
| SHA256 | 32位元組 |
| SHA384 | 48位元組 |
| SHA512 | 64位元組 |
典型應用場景:
校驗拷貝下載文件
校驗資訊有效性
使用 Python 內置庫 hashlib 創建hash值。
示例:
import hashlib
if __name__ == '__main__':
# 使用 md5 演算法
# m = hashlib.md5()
# 如果你想使用別的哈希演算法,比如, sha256 演算法,只需要修改為對應的函數 sha256()即可
m = hashlib.sha256()
# 要計算的源數據必須是位元組串格式
# 字元串對象需要encode轉化為位元組串對象
m.update("ML李嘉圖|mllijaitu".encode())
# 產生哈希值對應的bytes對象
resultBytes = m.digest()
# 產生哈希值的十六進位表示
resultHex = m.hexdigest()
print(resultHex)
SSH遠程操作
Python第三方庫 Paramiko 就是作為ssh客戶端遠程控制Linux主機 的。
exec_command 是每次執行都是 新打開一個channel的東西執行,
每個channel都是命令執行的環境,每執行命令都是一個新的執行環境,不在上次執行的環境裡面,
相當於 每次都在各自的執行環境裡面,和前面的執行環境沒有關係。
多個命令一起執行,用分號隔開,像這樣:
stdin, stdout, stderr = ssh.exec_command("cd testdir;pwd")
操作單台主機:
# 單台主機操作
import paramiko
#############################配置資訊#####################################
# 登陸參數設置
hostname = ""
host_port = 22
username = "root"
password = ""
########################################################################
def ssh_client_con():
"""創建ssh連接,並執行shell指令"""
# 1 創建ssh_client實例
ssh_client = paramiko.SSHClient()
# 自動處理第一次連接的yes或者no的問題
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
# 2 連接伺服器
ssh_client.connect(
port=host_port,
hostname=hostname,
username=username,
password=password
)
# 3 執行shell命令
# 構造shell指令
shell_command = "ls"
stdin, stdout, stderr = ssh_client.exec_command(shell_command)
# 輸出返回資訊
stdout_info = stdout.read().decode('utf8')
print(stdout_info)
# 輸出返回的錯誤資訊
stderr_info = stderr.read().decode('utf8')
print(stderr_info)
def sftp_client_con():
# 1 創建transport通道
tran = paramiko.Transport((hostname, host_port))
tran.connect(username=username, password=password)
# 2 創建sftp實例
sftp = paramiko.SFTPClient.from_transport(tran)
# 3 執行上傳功能
local_path = "" # 本地路徑
remote_path = "" # 遠程路徑
put_info = sftp.put(local_path, remote_path, confirm=True)
print(put_info)
print(f"上傳{local_path}完成")
# 4 執行下載功能
save_path = "" # 本地保存文件路徑
sftp.get(remotepath=remote_path, localpath=save_path)
print(f'下載{save_path}完成')
# 5 關閉通道
tran.close()
if __name__ == '__main__':
# 調用函數執行功能
ssh_client_con()
# sftp_client_con()
Python面向對象編程
類變數與實例變數
# 創建一個學生類
class Student:
# number屬於類變數,不屬於某個具體的學生實例
number = 0
# 定義學生屬性,初始化方法
# name和score屬於實例變數
def __init__(self, name, score):
self.name = name
self.score = score
Student.number = Student.number + 1
# 定義列印學生資訊的方法
def show(self):
print("Name: {}. Score: {}".format(self.name, self.score))
# 實例化,創建對象
student1 = Student("John", 100)
student2 = Student("Lucy", 99)
print(Student.number) # 列印2
print(student1.__class__.number) # 列印2
類方法
有些變數只屬於類,有些方法也只屬於類,不屬於具體的對象。
你有沒有注意到屬於對象的方法裡面都有一個self參數, 比如__init__(self), show(self)?
self是指對象本身。
屬於類的方法不使用self參數, 而使用參數cls,代表類本身。
另外習慣上對類方法我們會加上@classmethod的修飾符做說明。
class Student:
# number屬於類變數,不屬於某個具體的學生實例
number = 0
# 定義學生屬性,初始化方法
# name和score屬於實例變數
def __init__(self, name, score):
self.name = name
self.score = score
Student.number = Student.number + 1
# 定義列印學生資訊的方法
def show(self):
print("Name: {}. Score: {}".format(self.name, self.score))
# 定義類方法,列印學生的數量
@classmethod
def total(cls):
print("Total: {0}".format(cls.number))
if __name__ == '__main__':
# 實例化,創建對象
student1 = Student("John", 100)
student2 = Student("Lucy", 99)
Student.total() # 列印 Total: 2
類的私有屬性和私有方法
類裡面的私有屬性和私有方法以雙下劃線__開頭。私有屬性或方法不能在類的外部被使用或直接訪問。
# 創建一個學生類
class Student:
# 定義學生屬性,初始化方法
# name和score屬於實例變數, 其中__score屬於私有變數
def __init__(self, name, score):
self.name = name
self.__score = score
# 定義列印學生資訊的方法
def show(self):
print("Name: {}. Score: {}".format(self.name, self.__score))
# 實例化,創建對象
student1 = Student("John", 100)
student1.show() # 列印 Name: John, Score: 100
student1.__score # 列印出錯,該屬性不能從外部訪問。
@property
# 創建一個學生類
class Student:
# 定義學生屬性,初始化方法
# name和score屬於實例變數, 其中score屬於私有變數
def __init__(self, name, score):
self.name = name
self.__score = score
# 利用property裝飾器把函數偽裝成屬性
@property
def score(self):
print("Name: {}. Score: {}".format(self.name, self.__score))
if __name__ == '__main__':
# 實例化,創建對象
student1 = Student("John", 100)
student1.score # 列印 Name: John. Score: 100
類的繼承
# 創建父類學校成員SchoolMember
class SchoolMember:
def __init__(self, name, age):
self.name = name
self.age = age
def tell(self):
# 列印個人資訊
print('Name:"{}" Age:"{}"'.format(self.name, self.age), end=" ")
# 創建子類老師 Teacher
class Teacher(SchoolMember):
def __init__(self, name, age, salary):
SchoolMember.__init__(self, name, age) # 利用父類進行初始化
self.salary = salary
# 方法重寫
def tell(self):
SchoolMember.tell(self)
print('Salary: {}'.format(self.salary))
# 創建子類學生Student
class Student(SchoolMember):
def __init__(self, name, age, score):
SchoolMember.__init__(self, name, age)
self.score = score
def tell(self):
SchoolMember.tell(self)
print('score: {}'.format(self.score))
if __name__ == '__main__':
teacher1 = Teacher("John", 44, "$60000")
student1 = Student("Mary", 12, 99)
teacher1.tell()
student1.tell()
靜態變數和靜態方法
# 創建一個學生類
class Student:
# number屬於類變數,定義在方法外,不屬於具體實例
number = 0
# 定義學生屬性,初始化方法
# name和score屬於實例變數,定義在方法里
def __init__(self, name, score):
self.name = name
self.score = score
Student.number = self.number + 1
# 定義列印學生資訊的方法
def show(self):
print("Name: {}. Score: {}".format(self.name, self.score))
# 靜態方法無法使用cls和self參數訪問類或實例的變數
@staticmethod
def func1():
print("this is static function!")
