三赵抢、Python速覽
- 原始字符串
print(r'C:\some\name')
原始字符串還有一個(gè)微妙的限制:一個(gè)原始字符串不能以奇數(shù)個(gè) \ 字符結(jié)束
- 以下切片操作會(huì)返回列表的淺拷貝
squares[:]
- append() 方法
可以在列表末尾添加新元素
四、其他流程控制工具
- 循環(huán)
for i in range(5):
print(i)
a = ['Mary', 'had', 'a', 'little', 'lamb']
for i in range(len(a)):
print(i, a[i])
pass 語句
match 語句
match status:
case 400:
return "Bad request"
case _:
return "Something's wrong with the internet"
“變量名” _ 被作為 通配符 并必定會(huì)匹配成功
定義函數(shù)
def fib(n):
"""Print a Fibonacci series up to n."""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
函數(shù)內(nèi)的第一條語句是字符串時(shí),該字符串就是文檔字符串其爵,也稱為 docstring
默認(rèn)值只計(jì)算一次摩渺。默認(rèn)值為列表、字典或類實(shí)例等可變對(duì)象時(shí)横侦,會(huì)產(chǎn)生與該規(guī)則不同的結(jié)果绰姻。
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
輸出結(jié)果如下:
[1]
[1, 2]
[1, 2, 3]
不想在后續(xù)調(diào)用之間共享默認(rèn)值時(shí)狂芋,應(yīng)以如下方式編寫函數(shù):
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
最后一個(gè)形參為 **name 形式時(shí),接收一個(gè)字典
*name 形參接收一個(gè)元組
- 特殊參數(shù)
函數(shù)定義中未使用 / 和 * 時(shí)辆影,參數(shù)可以按位置或關(guān)鍵字傳遞給函數(shù)。
standard_arg(2) //按位置傳遞參數(shù)
standard_arg(arg=2) //按關(guān)鍵字傳遞參數(shù)
def pos_only_arg(arg, /):
def kwd_only_arg(*, arg):
def combined_example(pos_only, /, standard, *, kwd_only):
- lambda表達(dá)式
def make_incrementor(n):
return lambda x: x + n
- 文檔字符串
第一行應(yīng)為對(duì)象用途的簡(jiǎn)短摘要锯蛀。
文檔字符串為多行時(shí)旁涤,第二行應(yīng)為空白行迫像,在視覺上將摘要與其余描述分開闻妓。
def my_function():
"""Do nothing, but document it.
No, really, it doesn't do anything.
"""
pass
print(my_function.__doc__)
五由缆、數(shù)據(jù)結(jié)構(gòu)
- 列表
list.insert(len(a),x) = append(x)
list.remove(x)
list.pop()
list.sort()
list.reverse()
- 用列表實(shí)現(xiàn)堆棧
pop() append()
- 用列表實(shí)現(xiàn)隊(duì)列
popleft() append()
- 列表推導(dǎo)式
squares = []
for x in range(10):
squares.append(x**2)
squares = [x**2 for x in range(10)]
l = [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
- 嵌套的列表推導(dǎo)式
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
#外層循環(huán)是 for i in range(len(matrix[0])),它遍歷了原始矩陣的每一列的索引是晨。內(nèi)層循環(huán)是 for row in matrix罩缴,它遍歷了原始矩陣的每一行层扶。
- 集合
創(chuàng)建空集合只能用 set()怒医,不能用 {}奢讨,{} 創(chuàng)建的是空字典
a = set('abracadabra')
b = set('alacazam')
a-b a+b a&b a^b
- 字典
tel = {'jack': 4098, 'sape': 4139}
tel['guido'] = 4127
對(duì)字典執(zhí)行 list(d) 操作拿诸,返回該字典中所有鍵的列表
在字典中循環(huán)時(shí),用items()
方法可同時(shí)取出鍵和對(duì)應(yīng)的值:
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
print(k, v)
在序列中循環(huán)時(shí)季率,用 enumerate()
函數(shù)可以同時(shí)取出位置索引和對(duì)應(yīng)的值:
for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)
逆向循環(huán)序列時(shí)飒泻,先正向定位序列,然后調(diào)用 reversed()
函數(shù):
for i in reversed(range(1, 10, 2)):
print(i)
使用 set()
去除序列中的重復(fù)元素
- 比較運(yùn)算符
in not in 用于執(zhí)行確定一個(gè)值是否存在(或不存在)于某個(gè)容器中的成員檢測(cè)
is is not 用于比較兩個(gè)對(duì)象是否是同一個(gè)對(duì)象
and or
六惰许、模塊
Python 把各種定義存入一個(gè)文件汹买,在腳本或解釋器的交互式實(shí)例中使用聊倔。這個(gè)文件就是 模塊 耙蔑;模塊中的定義可以導(dǎo)入到其他模塊或主模塊。
其文件名是模塊名加后綴名.py
徐鹤。在模塊內(nèi)部邀层,通過全局變量 __name__
可以獲取模塊名(即字符串)
- 導(dǎo)入模塊
import fibo
fibo.fib(1000)
from fibo import fib, fib2
fib(500)
from fibo import *
fib(500)
import fibo as fib
fib.fib(500)
from fibo import fib as fibonacci
fibonacci(500)
- 以腳本方式執(zhí)行模塊
python fibo.py <arguments>
這項(xiàng)操作將執(zhí)行模塊里的代碼寥院,和導(dǎo)入模塊一樣秸谢,但會(huì)把 __name__ 賦值為 "__main__"
。 也就是把下列代碼添加到模塊末尾:
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
這個(gè)文件既能被用作腳本塑煎,又能被用作一個(gè)可供導(dǎo)入的模塊最铁,因?yàn)榻馕雒钚袇?shù)的那兩行代碼只有在模塊作為“main”文件執(zhí)行時(shí)才會(huì)運(yùn)行
- dir()函數(shù)
內(nèi)置函數(shù) dir()
用于查找模塊定義的名稱垮兑。返回結(jié)果是經(jīng)過排序的字符串列表
- 包
包是一種用“點(diǎn)式模塊名”構(gòu)造 Python 模塊命名空間的方法
例如系枪,模塊名 A.B 表示包 A 中名為 B 的子模塊
例如一個(gè)包的架構(gòu):
導(dǎo)入包時(shí),Python 搜索 sys.path 里的目錄雾棺,查找包的子目錄垢村。
必須要有
__init__.py
文件才能讓 Python 將包含該文件的目錄當(dāng)作包來處理。這可以防止具有通用名稱的目錄如 string 在無意中屏蔽后續(xù)出現(xiàn)在模塊搜索路徑中的有效模塊宏榕。
在最簡(jiǎn)單的情況下麻昼,init.py 可以只是一個(gè)空文件馋辈,但它也可以執(zhí)行包的初始化代碼或設(shè)置 all 變量迈螟。
import sound.effects.echo
from sound.effects import echo
from sound.effects.echo import echofilter
- 從包中導(dǎo)入 *
如果包的 init.py 代碼定義了列表 all答毫,運(yùn)行 from package import * 時(shí),它就是被導(dǎo)入的模塊名列表消返。
__all__ = ["echo", "surround", "reverse"]
如果沒有定義 all撵颊,from sound.effects import * 語句 不會(huì) 把包 sound.effects 中所有子模塊都導(dǎo)入到當(dāng)前命名空間惫叛;該語句只確保導(dǎo)入包 sound.effects
- 相對(duì)導(dǎo)入
可以用 import 語句的 from module import name 形式執(zhí)行相對(duì)導(dǎo)入
下面的導(dǎo)入語句使用前導(dǎo)句點(diǎn)表示相對(duì)導(dǎo)入中的當(dāng)前包和父包
from . import echo
from .. import formats
from ..filters import equalizer
注意嘉涌,相對(duì)導(dǎo)入基于當(dāng)前模塊名。因?yàn)橹髂K名永遠(yuǎn)是 "main",所以如果計(jì)劃將一個(gè)模塊用作 Python 應(yīng)用程序的主模塊固耘,那么該模塊內(nèi)的導(dǎo)入語句必須始終使用絕對(duì)導(dǎo)入。
包還支持一個(gè)特殊屬性 __path__
番枚。在包的 __init__.py
中的代碼被執(zhí)行前,該屬性被初始化為一個(gè)只含一項(xiàng)的列表拗馒,該項(xiàng)是一個(gè)字符串溯街,是 init.py 所在目錄的名稱
七呈昔、輸入與輸出
輸出格式
- 格式化字符串字面值
f'Results of the {year} {event}'
# 將 pi 舍入到小數(shù)點(diǎn)后三位
print(f'The value of pi is approximately {math.pi:.3f}.')
print('We are the {} who say "{}!"'.format('knights', 'Ni'))
print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam
#使用關(guān)鍵字參數(shù)名引用值
print('This {food} is {adjective}.'.format(
food='spam', adjective='absolutely horrible'))
This spam is absolutely horrible.
'{:-9} aaabbbb votes {:2.2%}'.format(var1, var2)
- 舊式字符串格式化方法
print('The value of pi is approximately %5.3f.' % math.pi)
The value of pi is approximately 3.142.
讀寫文件
open(filename, mode, encode)
f = open('workfile', 'w', encoding="utf-8")
mode
的值包括 'r' 堤尾,表示文件只能讀取辞槐;'w' 表示只能寫入(現(xiàn)有同名文件會(huì)被覆蓋)榄檬;'a' 表示打開文件并追加內(nèi)容育特,任何寫入的數(shù)據(jù)會(huì)自動(dòng)添加到文件末尾缰冤。'r+' 表示打開文件進(jìn)行讀寫。mode 實(shí)參是可選的怀薛,省略時(shí)的默認(rèn)值為 'r'
在mode
后面加上一個(gè) 'b' 枝恋,可以用 binary mode 打開文件with open
在處理文件對(duì)象時(shí)焚碌,最好使用 with
關(guān)鍵字霸妹。優(yōu)點(diǎn)是,子句體結(jié)束后鹃骂,文件會(huì)正確關(guān)閉畏线,即便觸發(fā)異常也可以寝殴。而且,使用 with
相比等效的 try
-finally
代碼塊要簡(jiǎn)短得多:
with open('workfile', encoding="utf-8") as f:
read_data = f.read()
# We can check that the file has been automatically closed.
f.closed
True
- 文件對(duì)象的方法
f.read(size)
可用于讀取文件內(nèi)容并返回字符串(文本模式)栈虚,或字節(jié)串對(duì)象(在二進(jìn)制模式下)魂务。
size 是可選的數(shù)值參數(shù)泌射。省略 size 或 size 為負(fù)數(shù)時(shí)熔酷,讀取并返回整個(gè)文件的內(nèi)容
f.readline()
從文件中讀取單行數(shù)據(jù)
for line in f:
print(line, end='')
f.write(string)
把 string 的內(nèi)容寫入文件拒秘,并返回寫入的字符數(shù)。
f.tell()
返回整數(shù)押蚤,給出文件對(duì)象在文件中的當(dāng)前位置
f.seek(offset, whence)
可以改變文件對(duì)象的位置
- 使用JSON
只需一行簡(jiǎn)單的代碼即可查看某個(gè)對(duì)象的 JSON 字符串表現(xiàn)形式:
import json
x = [1, 'simple', 'list']
json.dumps(x)
'[1, "simple", "list"]'
dumps()函數(shù)還有一個(gè)變體dump()
,將對(duì)象序列化為text file揽碘。因此园匹,如果 f
是text file 對(duì)象裸违,可以這樣做:
json.dump(x, f)
# 解碼對(duì)象
x = json.load(f)
八供汛、異常
- 異常的處理
try 語句的工作原理如下:
首先凛俱,執(zhí)行 try 子句 (try 和 except 關(guān)鍵字之間的語句)。
如果沒有觸發(fā)異常岸啡,則跳過 except 子句赫编,try 語句執(zhí)行完畢擂送。
如果在執(zhí)行 try 子句時(shí)發(fā)生了異常,則跳過該子句中剩下的部分搬味。 如果異常的類型與 except 關(guān)鍵字后指定的異常相匹配碰纬,則會(huì)執(zhí)行 except 子句问芬,然后跳到 try/except 代碼塊之后繼續(xù)執(zhí)行此衅。
如果發(fā)生的異常與 except 子句 中指定的異常不匹配挡鞍,則它會(huì)被傳遞到外部的 try 語句中;如果沒有找到處理程序陵刹,則它是一個(gè) 未處理異常 且執(zhí)行將終止并輸出如上所示的消息衰琐。
try:
this_fails()
except ZeroDivisionError as err:
print('Handling run-time error:', err)
- 觸發(fā)異常
raise 語句支持強(qiáng)制觸發(fā)指定的異常
唯一的參數(shù)就是要觸發(fā)的異常羡宙。這個(gè)參數(shù)必須是異常實(shí)例或異常類
raise ValueError # shorthand for 'raise ValueError()'
如果只想判斷是否觸發(fā)了異常掐隐,但并不打算處理該異常,則可以使用更簡(jiǎn)單的 raise 語句重新觸發(fā)異常:
try:
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
raise
- 異常鏈
如果一個(gè)未處理的異常發(fā)生在 except 部分內(nèi)僧凰,它將會(huì)有被處理的異常附加到它上面训措,并包括在錯(cuò)誤信息中
try:
open("database.sqlite")
except OSError:
raise RuntimeError("unable to handle error")
如果存在 finally 子句光羞,則 finally 子句是 try 語句結(jié)束前執(zhí)行的最后一項(xiàng)任務(wù)纱兑。不論 try 語句是否觸發(fā)異常潜慎,都會(huì)執(zhí)行 finally 子句
九、類
Python 的類有點(diǎn)類似于 C++ 和 Modula-3 中類的結(jié)合體
- 作用域
global
語句用于表明特定變量在全局作用域里局服,并應(yīng)在全局作用域中重新綁定淫奔;
nonlocal
語句表明特定變量在外層作用域中唆迁,并應(yīng)在外層作用域中重新綁定竞穷。
- 類定義:
在實(shí)踐中瘾带,類定義內(nèi)的語句通常都是函數(shù)定義
當(dāng)(從結(jié)尾處)正常離開類定義時(shí)看政,將創(chuàng)建一個(gè) 類對(duì)象
三種對(duì)象類型
- Class 對(duì)象
類對(duì)象支持兩種操作:屬性引用和實(shí)例化。
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
#屬性引用
obj.name
# 類的 實(shí)例化
#實(shí)例化操作會(huì)創(chuàng)建一個(gè)空對(duì)象
x = MyClass()
# __init__() 創(chuàng)建帶有特定初始狀態(tài)的自定義實(shí)例 eg:
def __init__(self):
self.data = []
# __init__() 方法還可以有額外參數(shù),提供給類實(shí)例化運(yùn)算符的參數(shù)將被傳遞給 __init__()
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
x.r, x.i
(3.0, -4.5)
實(shí)例對(duì)象
實(shí)例對(duì)象所能理解的唯一操作是屬性引用。 有兩種有效的屬性名稱:數(shù)據(jù)屬性和方法森渐。方法對(duì)象
調(diào)用 x.f() 其實(shí)就相當(dāng)于 MyClass.f(x)
f定義為:
def f(self): return 'hello world'
- 類和實(shí)例變量
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self, name):
self.name = name # instance variable unique to each instance
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
self.后面的變量相當(dāng)于private
而直接定義在類里面的數(shù)據(jù)是共享的同衣。
方法的第一個(gè)參數(shù)常常被命名為 self。 這也不過就是一個(gè)約定: self 這一名稱在 Python 中絕對(duì)沒有特殊含義浪秘。但是要注意,不遵循此約定會(huì)使得你的代碼對(duì)其他 Python 程序員來說缺乏可讀性询枚,而且也可以想像一個(gè) 類瀏覽器 程序的編寫可能會(huì)依賴于這樣的約定金蜀。
方法可以通過使用 self 參數(shù)的方法屬性調(diào)用其他方法:
class Bag:
def __init__(self):
self.data = []
def add(self, x):
self.data.append(x)
def addtwice(self, x):
self.add(x)
self.add(x)
- 繼承
當(dāng)基類定義在另一個(gè)模塊中的時(shí)候
class DerivedClassName(modname.BaseClassName):
(對(duì) C++ 程序員的提示:Python 中所有的方法實(shí)際上都是 virtual 方法渊抄。)
有一種方式可以簡(jiǎn)單地直接調(diào)用基類方法:
即調(diào)用 BaseClassName.methodname(self, arguments)
Python 也支持一種多重繼承丧裁。
- 私有變量
大多數(shù) Python 代碼都遵循這樣一個(gè)約定:帶有一個(gè)下劃線的名稱 (例如 _spam) 應(yīng)該被當(dāng)作是 API 的非公有部分 (無論它是函數(shù)煎娇、方法或是數(shù)據(jù)成員)缓呛。
由于存在對(duì)于類私有成員的有效使用場(chǎng)景(例如避免名稱與子類所定義的名稱相沖突)哟绊,因此存在對(duì)此種機(jī)制的有限支持,稱為 名稱改寫攀涵。 任何形式為 __spam 的標(biāo)識(shí)符(至少帶有兩個(gè)前綴下劃線汁果,至多一個(gè)后綴下劃線)的文本將被替換為 _classname__spam玲躯,其中 classname 為去除了前綴下劃線的當(dāng)前類名稱。 這種改寫不考慮標(biāo)識(shí)符的句法位置橱野,只要它出現(xiàn)在類定義內(nèi)部就會(huì)進(jìn)行水援。
class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable) #在構(gòu)造函數(shù)中調(diào)用了私有方法 __update
def update(self, iterable):
for item in iterable:
self.items_list.append(item)
# 將 update 方法賦值給私有方法 __update
__update = update
- 偽結(jié)構(gòu)體
from dataclasses import dataclass
@dataclass
class Employee:
name: str
dept: str
salary: int
john = Employee('john', 'computer lab', 1000)
john.dept
'computer lab'
john.salary
1000
- 迭代器
iter()
s = 'abc'
it = iter(s)
it
<str_iterator object at 0x10c90e650>
next(it)
'a'
next(it)
'b'
next(it)
'c'
next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
next(it)
StopIteration
- 生成器
生成器 是一個(gè)用于創(chuàng)建迭代器的
十蜗元、標(biāo)準(zhǔn)庫簡(jiǎn)介
- 操作系統(tǒng)接口
一定要使用 import os 而不是 from os import * 奕扣。這將避免內(nèi)建的 open() 函數(shù)被 os.open() 隱式替換掉
import os
os.getcwd() # Return the current working directory
'C:\\Python311'
os.chdir('/server/accesslogs') # Change current working directory
os.system('mkdir today') # Run the command mkdir in the system shell
import shutil
shutil.copyfile('data.db', 'archive.db')
'archive.db'
shutil.move('/build/executables', 'installdir')
'installdir'
- 字符串模式匹配
import re
re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
- 互聯(lián)網(wǎng)訪問
smtplib 用于發(fā)送郵件
import smtplib
server = smtplib.SMTP('localhost')
server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
"""To: jcaesar@example.org
From: soothsayer@example.org
Beware the Ides of March.
""")
server.quit()
- 性能測(cè)量
from timeit import Timer
Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.57535828626024577
Timer('a,b = b,a', 'a=1; b=2').timeit()
0.54962537085770791
- 多線程
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, infile, outfile):
threading.Thread.__init__(self)
self.infile = infile
self.outfile = outfile
def run(self):
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
f.write(self.infile)
f.close()
print('Finished background zip of:', self.infile)
background = AsyncZip('mydata.txt', 'myarchive.zip')
background.start()
print('The main program continues to run in foreground.')
background.join() # Wait for the background task to finish
print('Main program waited until background was done.')
- 日志記錄
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
十二、虛擬環(huán)境和包
相當(dāng)于一個(gè)容器楷兽,nbcs
應(yīng)用程序有時(shí)需要特定版本的庫芯杀,可以創(chuàng)建一個(gè) virtual environment瘪匿,一個(gè)目錄樹寻馏,其中安裝有特定Python版本诚欠,以及許多其他包。
用于創(chuàng)建和管理虛擬環(huán)境的模塊稱為 venv
#創(chuàng)建虛擬環(huán)境粉寞,確定放置的目錄
python -m venv tutorial-env #創(chuàng)建 tutorial-env 目錄
# 創(chuàng)建虛擬環(huán)境后唧垦,您可以激活它振亮。
tutorial-env\Scripts\activate.bat #Windows上
source tutorial-env/bin/activate #Unix上
- pip的使用
python -m pip uninstall
python -m pip show
python -m pip list
python -m pip freeze
requirements.txt
install -r
python -m pip install novas
python -m pip install requests==2.6.0
python -m pip install --upgrade requests
# 顯示包的版本信息坊秸、位置等
python -m pip show requests
#顯示已安裝的所有包
python -m pip list
#輸出已安裝的包到指定文件褒搔,可供install -r命令使用
python -m pip freeze > requirements.txt
python -m pip install -r requirements.txt