1. 程式人生 > 其它 >自學python-語句

自學python-語句

技術標籤:python指令碼語言

自學python-語句

文章目錄

程式設計第一步

斐波納契數列

#!/usr/bin/python3
# Fibonacci series: 斐波納契數列
# 兩個元素的總和確定了下一個數
a, b = 0, 1
while b < 10:
    print(b)
    a, b = b, a+b

a,b=b,a+b是先計算右邊,再賦值給左邊

end關鍵字

關鍵字end可以用於將結果輸出到同一行,或者在輸出的末尾新增不同的字元

條件控制

一般形式

#根據縮排劃分程式碼塊
if cond1:
    state1
elif condition_2:
state2 else: state3

python沒有switch-case語句

題外話:input("點選 enter 鍵退出")

age = int(input("請輸入你家狗狗的年齡: "))

判斷運算子與其他語言一樣

if語句可巢狀

迴圈語句

while語句一般形式

while 判斷條件(condition):
    statements

沒有do…while迴圈

無限迴圈,ctrl+c退出迴圈,在伺服器上客戶端的實時請求非常有用

while…else一般形式

while <expr>:
    <statement(s)>
else:
    <additional_statement(s)>

簡單語句可以將一句程式碼直接寫在:

for語句一般形式

for <variable> in <sequence>:
    <statements>
else:
    <statements>

break跳出當前迴圈體

range函式

內建函式,能生成數列

range(m,n,step):[m,n),step增量或步長,只有一個引數,預設為n,m=0,step=1

break,continue,迴圈中的else

break是跳出迴圈,對應的迴圈 else 塊將不執行

continue是跳到下一次判斷語句

pass語句

空語句,保持程式結構的完整性,做佔位語句

迭代器與生成器

迭代器

是python最強大的功能之一,訪問集合元素方式之一

是一個可以記住遍歷的位置物件

從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退

有兩個基本的方法:iter()next()

字串列表元組物件都可用於建立迭代器:

list=[1,2,3,4]
it=iter(list) #建立迭代器物件
next(it) #輸出迭代器的下一個元素

迭代器物件可以使用for進行遍歷

#!/usr/bin/python3
 
list=[1,2,3,4]
it = iter(list)    # 建立迭代器物件
for x in it:
    print (x, end=" ")

或者用next遍歷

#!/usr/bin/python3
 
import sys         # 引入 sys 模組
 
list=[1,2,3,4]
it = iter(list)    # 建立迭代器物件
 
while True:
    try:
        print (next(it))
    except StopIteration:#next出錯處理,即沒有下一個
        sys.exit()#退出直譯器,os._exit()(一般用於線上程中退出)直接退出,此處丟擲異常,供捕獲進行清理工作,用於在主執行緒中退出

建立一個迭代器

把一個類作為一個迭代器使用需要在類中實現兩個方法 __iter__()__next__()

類都有一個建構函式,Python 的建構函式為 __init__(), 它會在物件初始化的時候執行。

__iter__()方法返回一個特殊的迭代器物件, 這個迭代器物件實現了 __next__()方法並通過 StopIteration 異常標識迭代的完成。

__next__()方法(Python 2 裡是 next())會返回下一個迭代器物件。

建立一個返回數字的迭代器,初始值為 1,逐步遞增 1:

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self
 
  def __next__(self):
    x = self.a
    self.a += 1
    return x
 
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))

StopIteration 異常用於標識迭代的完成,防止出現無限迴圈的情況,在 __next__()方法中我們可以設定在完成指定迴圈次數後觸發 StopIteration 異常來結束迭代

def __next__(self):
    if self.a <= 20:
      x = self.a
      self.a += 1
      return x
    else:
      raise StopIteration
    
for x in myiter:
  print(x)

生成器

使用了 yield 的函式被稱為生成器(generator)

生成器是一個返回迭代器的函式,只能用於迭代操作,更簡單點理解生成器就是一個迭代器

在呼叫生成器執行的過程中,每次遇到 yield 時函式會暫停並儲存當前所有的執行資訊,返回 yield 的值, 並在下一次執行 next() 方法時從當前位置繼續執行。

使用 yield 實現斐波那契數列

#!/usr/bin/python3
 
import sys
 
def fibonacci(n): # 生成器函式 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一個迭代器,由生成器返回生成
 
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()

對比

迭代器是由建立物件,iter()返回,生成器是由函式返回。迭代器也是屬於建立的物件型別(type),所以可以呼叫內建next函式

生成器返回的type就是生成器了

兩種next的實現是明顯不同的

函式

定義一個函式

def funcname(params):
    #文件字串用於存放函式說明
    statement
    return [表示式]#不帶則表示返回None
    

在 python 中,型別屬於物件,變數是沒有型別的,=左邊變數是沒有型別的,只是一個引用,右邊物件是有型別的。

引數傳遞

可更改(mutable)和不可更改(immutable)物件

list,dict可更改,其他都不可更改

不可變型別:重新賦值,生成新物件,引用變換。

可變:list,dict內部部分值改變

引數傳遞:不可變型別是傳遞變數的值,函式改變值,原始值不會改變。可變就類似引用傳遞,函式改變值,原始值也改變。

python 中一切都是物件,嚴格意義我們不能說值傳遞還是引用傳遞,我們應該說傳不可變物件和傳可變物件。

引數型別

必需引數

以正確的順序傳入函式,呼叫時的數量必須和宣告時的一樣

關鍵字引數

允許函式呼叫時引數的順序與宣告時不一致:func( param = " ")

預設引數

def func( param1, param1 = value1 ):

不定長引數

def functionname([formal_args,] *var_args_tuple ):
   "函式_文件字串"
   function_suite
   return [expression]

加了星號 ***** 的引數會以元組(tuple)的形式匯入,存放所有未命名的變數引數:func(param1,param2,param3) print(var_args_tuple)>>>(param2,param3),元組也可以為空

引數帶兩個星號 ******基本語法如下:

def functionname([formal_args,] **var_args_dict ):
   "函式_文件字串"
   function_suite
   return [expression]

加了兩個星號 ** 的引數會以字典的形式匯入:func(1, a=2,b=3) print(var_args_dict)>>>{'a': 2, 'b': 3}

宣告函式時,引數中星號 ***** 可以單獨出現:def f(a,b,*,c):,但這種情況下 ***** 後的引數必須用關鍵字傳入:f(1,2,c=3)否則報錯TypeError: f() takes 2 positional arguments but 3 were given

匿名函式

使用 lambda 來建立匿名函式

lambda的主體是一個表示式,擁有自己的名稱空間,且不能訪問自己引數列表之外或全域性名稱空間裡的引數

題外話:C或C++的行內函數,只能寫一行的目的是呼叫小函式時不佔用棧記憶體從而增加執行效率。lambda不等同於此

lambda [arg1 [,arg2,.....argn]]:expression

強制位置引數

Python3.8 新增, / 用來指明函式形參必須使用指定位置引數,不能使用關鍵字引數的形式。

在以下的例子中,形參 a 和 b 必須使用指定位置引數,c 或 d 可以是位置形參或關鍵字形參,而 e 或 f 要求為關鍵字形參:

def f(a, b, /, c, d, *, e, f):
    print(a, b, c, d, e, f)

資料結構

列表

可變,區別於字串和元組

方法補充:remove(x)(刪除值為x的第一個元素,無則返回i錯誤),pop([i])(刪除指定位置元素,無則返回最後一個元素)

當作堆疊使用

後進先出,append()方法新增到堆疊頂。不指定索引的pop() 方法可以釋放堆疊頂

當做佇列使用

佇列裡第一加入的元素,第一個取出來popleft()。效率不高,因為所有其他的元素都得一個一個地移動。

from collections import deque #雙向佇列,操作很像list ,擁有更低的時間和空間複雜度
queue = deque(["Eric", "John", "Michael"])

推導式

列表推導式提供了從序列建立列表的簡單途徑。for 之後跟一個表示式,然後有零到多個 for 或 if 子句

例:[3*x for x in list],[str(round(355/113, i)) for i in range(1, 6)],[x*y for x in list1 for y in list2]

巢狀列表

例:將3X4的矩陣列表轉換為4X3列表

[[row[i] for row in matrix] for i in range(4)]

等價於

transposed = []
for i in range(4):
    transposed.append([row[i] for row in matrix])
    
#或者
transposed = []
for i in range(4):
     # the following 3 lines implement the nested listcomp
     transposed_row = []
     for row in matrix:
         transposed_row.append(row[i])
     transposed.append(transposed_row)

推導式的for從右往左巢狀

del刪除

del list[]或者del list

元組和序列

在輸入時可能有或沒有括號

集合

無序不重複元素的集,基本功能包括關係測試(-,|,&,^)和消除重複元素,也支援推導式

字典

以關鍵字為索引,dict() 直接從鍵值對元組列表[(,),(,),(,)]中構建字典

如果關鍵字只是簡單的字串,使用關鍵字引數指定鍵值對:dict(a=value1,b=value2)

遍歷

在字典中遍歷時:for k, v in dict.items():

在序列中遍歷時,索引位置和對應值可以使用 enumerate()函式同時得到:for i, v in enumerate(list):

同時遍歷兩個或更多的序列,可以使用 zip() 組合:for a, b in zip(list1, list2):

反向遍歷:reverse()

順序遍歷:sorted(),不改變原值

模組

模組是一個包含所有你定義的函式和變數的檔案,其後綴名是.py。模組可以被別的程式引入。使用 python 標準庫的方法相同。

import語句

import module1[, module2[,... moduleN]#把命令放在指令碼的頂端

當直譯器遇到 import 語句,如果模組在當前的搜尋路徑就會被匯入。

搜尋路徑是一個直譯器會先進行搜尋的所有目錄的列表。

可在下圖操作後檢視搜尋路徑

在這裡插入圖片描述

一個模組只會被匯入一次,不管執行了多少次import

自定義模組:要在搜尋路徑建立py檔案,這樣做並沒有把py檔案中直接定義的函式名稱寫入到當前符號表裡,可以使用模組名稱來訪問函式module.func,如果你打算經常使用一個函式,你可以把它賦給一個本地的名稱funcname=module.func

from…import語句

from modname import name1[, name2[, ... nameN]]

將模組裡的某些函式引入進來

from…import*:把一個模組的所有內容全都匯入到當前的名稱空間,然而這種宣告不該被過多地使用。這將把所有的名字都匯入進來,但是那些由單一下劃線(_)開頭的名字不在此例。大多數情況, 不使用這種方法,因為引入的其它來源的命名,很可能覆蓋了已有的定義。

深入模組

模組除了方法定義,還可以包括可執行的程式碼。這些程式碼一般用來初始化這個模組。這些程式碼只有在第一次被匯入時才會被執行。

每個模組有各自獨立的符號表,在模組內部為所有的函式當作全域性符號表來使用。

1、一個模組(或者指令碼,或者其他地方)的最前面使用 import 來匯入一個模組,被匯入的模組的名稱將被放入當前操作的模組的符號表中

2、可以使用 import 直接把模組內(函式,變數的)名稱匯入到當前操作模組。匯入的方法不會把被匯入的模組的名稱放在當前的字元表中

__name__屬性

一個模組被另一個程式第一次引入時,其主程式將執行。

每個模組都有一個__name__屬性,當其值是’__main__'時,表明該模組自身在執行,否則是被引入。

如果我們想在模組被引入時,模組中的某一程式塊不執行,我們可以用__name__屬性來使該程式塊僅在該模組自身執行時執行。

if __name__ == '__main__':
   print('程式自身在執行') #引入時執行
else:
   print('我來自另一模組') #引入時不執行

dir()函式

內建的函式 dir() 可以找到模組內定義的所有名稱。以一個字串列表的形式返回

在這裡插入圖片描述

如果沒有給定引數,那麼 dir() 函式會羅列出當前定義的所有名稱

在這裡插入圖片描述

標準模組

Python 本身帶著一些標準的模組庫

有些模組直接被構建在解析器裡,這些雖然不是一些語言內建的功能,但是他卻能很高效的使用,甚至是系統級呼叫也沒問題。

這些元件會根據不同的作業系統進行不同形式的配置

一個特別的模組 sys ,它內建在每一個 Python 解析器中。變數 sys.ps1 和 sys.ps2 定義了主提示符和副提示符所對應的字串:

在這裡插入圖片描述

是一種管理 Python 模組名稱空間的形式,採用"點模組名稱"。比如一個模組的名稱是 A.B, 那麼他表示一個包 A中的子模組 B 。不用擔心不同庫之間的模組重名的情況。

類似分層的檔案系統:包-》模組-》函式,變數

目錄只有包含一個叫做 __init__.py 的檔案才會被認作是一個包

匯入方式:1.匯入包裡特定模組import package.module,訪問package.module.func

​ 2.匯入特定模組from package import module,訪問module.func

​ 3.直接匯入一個函式或者變數from package.module import func,訪問func

記憶:訪問就是抄下import後面

從包中匯入*

Python 會進入檔案系統,找到這個包裡面所有的子模組,一個一個的把它們都匯入進來。

因為Windows是一個大小寫不區分的系統,在 Windows平臺上工作的就不好

為了解決這個問題,包作者需要提供一個精確的包的索引

如果包定義檔案 __init__.py存在一個叫做 __all__的列表變數,那麼在使用 from package import * 的時候就把這個列表中的所有名字作為包內容匯入:__all__ = ["echo", "surround", "reverse"]。在更新包之後保證 __all__也更新了

如果 __all__ 真的沒有定義,那麼使用from package import *這種語法的時候,就不會匯入包package裡的任何子模組。他只是把包package和它裡面定義的所有內容匯入進來(可能執行__init__.py裡定義的初始化程式碼)。

這會把 __init__.py裡面定義的所有名字匯入進來。並且他不會破壞掉我們在這句話之前匯入的所有明確指定的模組。

通常不主張使用 * 這種方法來匯入模組,因為這種方法經常會導致程式碼的可讀性降低。如果不同模組之間有相同的函式命名,最後匯入的會覆蓋前面的,也就是說只會呼叫到最後匯入進的函式

from Package import specific_submodule 這種方法永遠不會有錯。事實上,這也是推薦的方法。

無論是隱式的還是顯式的相對匯入都是從當前模組開始的。主模組的名字永遠是"__main__",一個Python應用程式的主模組,應當總是使用絕對路徑引用。

包還提供一個額外的屬性__path__。這是一個目錄列表,裡面每一個包含的目錄都有為這個包服務的__init__.py,得在其他__init__.py被執行前定義。可以修改這個變數,用來影響包含在包裡面的模組和子包。

這個功能並不常用,一般用來擴充套件包裡面的模組。

輸入與輸出

輸出格式美化

輸出方式:表示式和print,檔案物件的write

write:標準輸出檔案可以用 sys.stdout 引用

格式化輸出值: str.format()

轉化為string:str()(使用者易讀),repr(直譯器易讀)

repr:repr() 函式可以轉義字串中的特殊字元(和r相似),引數可以是 Python 的任何物件

題外話rjust(n[, fillchar]) 字串函式,右對齊,用空格(或者fillchar)填補達到n長度,ljust,center類似,zfill(n)在數字左邊填補0達到n

str.format()基本用法:1.使用了關鍵字引數,2.位置及關鍵字引數可以任意的結合

print('{0} 和 {1}'.format('Google', 'baidu'))
print('{name}網址: {site}'.format(name='百度', site='www.baidu.com'))

!a (使用 ascii()), !s (使用 str()) 和 !r (使用 repr()) 可以用於在格式化某個值之前對其進行轉化

 print('常量 PI 的值近似為: {!r}。'.format(math.pi))

可選項 : 和格式識別符號可以跟著欄位名。 這就允許對值進行更好的格式化。

 print('常量 PI 的值近似為 {0:.3f}。'.format(math.pi))

: 後傳入一個整數, 可以保證該域至少有這麼多的寬度。

print('{0:10} ==> {1:10d}'.format(name, number))

如果你有一個很長的格式化字串, 而你不想將它們分開, 在格式化時通過變數名而非位置。

最簡單的就是傳入一個字典, 然後使用方括號 [] 來訪問鍵值

table = {'Google': 1,'Taobao': 2}
print(' Google: {0[Google]:d}; Taobao: {0[Taobao]:d}'.format(table))

也可以通過在 table 變數前使用 ** 來實現相同的功能:

table = {'Google': 1,  'Taobao': 2}
print('Google: {Google:d}; Taobao: {Taobao:d}'.format(**table))

舊式字串格式化

% 操作符也可以實現字串格式化

print('常量 PI 的值近似為:%5.3f。' % math.pi)

這種舊式的格式化最終會從該語言中移除

讀取鍵盤輸入

Python提供了 input() 內建函式從標準輸入讀入一行文字。

input 可以接收一個Python表示式作為輸入,並將運算結果返回。

讀和寫檔案

open() 將會返回一個 file 物件,基本語法格式如下:

open(filename, mode)

mode:決定了開啟檔案的模式:只讀,寫入,追加等。。這個引數是非強制的,預設檔案訪問模式為只讀®。

模式描述
r以只讀方式開啟檔案。檔案的指標將會放在檔案的開頭。這是預設模式。
rb以二進位制格式開啟一個檔案用於只讀。檔案指標將會放在檔案的開頭。
r+開啟一個檔案用於讀寫。檔案指標將會放在檔案的開頭。
rb+以二進位制格式開啟一個檔案用於讀寫。檔案指標將會放在檔案的開頭。
w開啟一個檔案只用於寫入。如果該檔案已存在則開啟檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。
wb以二進位制格式開啟一個檔案只用於寫入。同上
w+開啟一個檔案用於讀寫。同上
wb+以二進位制格式開啟一個檔案用於讀寫。同上
a開啟一個檔案用於追加。如果該檔案已存在,檔案指標將會放在檔案的結尾。如果該檔案不存在,建立新檔案進行寫入。
ab以二進位制格式開啟一個檔案用於追加。同a
a+開啟一個檔案用於讀寫。如果該檔案已存在,檔案指標將會放在檔案的結尾。檔案開啟時會是追加模式。如果該檔案不存在,建立新檔案用於讀寫。
ab+以二進位制格式開啟一個檔案用於追加。同a+
模式rr+ww+aa+
++++
+++++
建立++++
覆蓋++
指標在開始++++
指標在結尾++

檔案物件的方法

f.read()

呼叫 f.read(size), 這將讀取一定數目的資料, 然後作為字串或位元組物件返回。size 是一個可選的數字型別的引數。 當 size 被忽略了或者為負, 那麼該檔案的所有內容都將被讀取並且返回。

f.readline()

會從檔案中讀取單獨的一行。換行符為 ‘\n’。f.readline() 如果返回一個空字串, 說明已經已經讀取到最後一行。

f.readlines()

返回該檔案中包含的所有行(以字串列表返回,每個字串後有\n)。如果設定可選引數 sizehint, 則讀取指定長度的位元組, 並且將這些位元組按行分割。

另一種方式是迭代一個檔案物件然後讀取每行:

for line in f:
    print(line, end='')

如果要寫入一些不是字串的東西, 那麼將需要先進行轉換。

f.tell()

返回檔案物件當前所處的位置, 它是從檔案開頭開始算起的位元組數。

f.seek()

如果要改變檔案當前的位置, 可以使用 f.seek(offset, from_what) 函式。

from_what 的值, 如果是 0 表示開頭, 如果是 1 表示當前位置, 2 表示檔案的結尾,from_what 值為預設為0。offset是移動字元數

  • seek(x,0) : 從起始位置即檔案首行首字元開始移動 x 個字元
  • seek(x,1) : 表示從當前位置往後移動x個字元
  • seek(-x,2):表示從檔案的結尾往前移動x個字元

f.close

當你處理完一個檔案後, 呼叫 f.close() 來關閉檔案並釋放系統的資源,如果嘗試再呼叫該檔案,則會丟擲異常。

當處理一個檔案物件時, 使用 with 關鍵字是非常好的方式。在結束後, 它會幫你正確的關閉檔案。 而且寫起來也比 try - finally 語句塊要簡短:

with open('/tmp/foo.txt', 'r') as f:
     read_data = f.read()

檢驗是否關閉:f.closed==True

pickle模組

實現了基本的資料序列和反序列化。

通過pickle模組的序列化操作我們能夠將程式中執行的物件資訊儲存到檔案中去,永久儲存。

通過pickle模組的反序列化操作,我們能夠從檔案中建立上一次程式儲存的物件。

基本介面:

pickle.dump(obj, file, [,protocol])

有了 pickle 這個物件, 就能對 file 以讀取的形式開啟:

x = pickle.load(file)

**註解:**從 file 中讀取一個字串,並將它重構為原來的python物件。

file: 類檔案物件,有read()和readline()介面。

import pickle
output = open('data.pkl', 'wb')
# Pickle dictionary using protocol 0.
pickle.dump(data1, output)
# Pickle the list using the highest protocol available.
pickle.dump(datalist, output, -1)

#使用pickle模組從檔案中重構python物件
pkl_file = open('data.pkl', 'rb')

data1 = pickle.load(pkl_file)
data2 = pickle.load(pkl_file)

格式化精度,對齊方式

%f 保留小數點後面六位有效數字 float

%e 保留小數點後面六位有效數字

%g 在保證六位有效數字的前提下,使用小數方式,否則使用科學計數法。

print('%.2g' % 1111.1111)  # 取2位有效數字,自動轉換為科學計數法1.1e+03

%s 字串輸出 string

%10s 右對齊,佔位符 10位

%-10s 左對齊,佔位符 10 位

%.2s 擷取 2 位字串

%10.2s,10 位佔位符,擷取兩位字串。

  • <:左對齊
  • >:右對齊
  • ^:居中
  • =:在正負號(如果有的話)和數字之間填充,該對齊選項僅對數字型別有效。它可以輸出類似 +0000120 這樣的字串。
>>> print("|",format("RUNOOB","*>30"),"|")    #左對齊
| ************************RUNOOB |
>>> print("|",format("RUNOOB","*^30"),"|")    #居中對齊
| ************RUNOOB************ |
>>> print("|",format("RUNOOB","*<30"),"|")    #右對齊
| RUNOOB************************ |

file方法

open()

Python open() 方法用於開啟一個檔案,並返回檔案物件,在對檔案進行處理過程都需要使用到這個函式,如果該檔案無法被開啟,會丟擲 OSError

完整的語法格式為:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

引數說明:

  • file: 必需,檔案路徑(相對或者絕對路徑)。

  • mode: 可選,檔案開啟模式

  • buffering: 設定緩衝

  • encoding: 一般使用utf8

  • errors: 報錯級別

  • newline: 區分換行符

  • closefd: 傳入的file引數型別

  • opener: 設定自定義開啟器,開啟器的返回值必須是一個開啟的檔案描述符。

    上面的mode表新增如下

模式描述
t文字模式 (預設)。
x寫模式,新建一個檔案,如果該檔案已存在則會報錯。
b二進位制模式。
+開啟一個檔案進行更新(可讀可寫)。
U通用換行模式(Python 3 不支援)。

預設為文字模式,如果要以二進位制模式開啟,加上 b

file物件

file.flush()(重新整理檔案內部緩衝,直接把內部緩衝區的資料寫入檔案),file.fileno()(返回一個整型的檔案描述符),file.isatty()(是否連線到一個終端裝置),file.next()(返回檔案下一行,python3不支援),file.read(size)(返回指定位元組數),file.readline([size])(讀取整行,包括“、\n”)

file.readlines([sizeint])讀取所有行並返回列表,若給定sizeint>0,返回總和大約為sizeint位元組的行, 實際讀取值可能比 sizeint 較大, 因為需要填充緩衝區。

file.truncate([size])從檔案的首行首字元開始截斷,截斷檔案為 size 個字元,無 size 表示從當前位置截斷;截斷之後後面的所有字元被刪除,其中 windows 系統下的換行代表2個字元大小。

file.write(str)將字串寫入檔案,返回的是寫入的字元長度。

file.writelines(sequence)向檔案寫入一個序列字串列表,如果需要換行則要自己加入每行的換行符。

os

os 模組提供了非常豐富的方法用來處理檔案和目錄。

詳細介紹

以下是比較能理解且平常能用到的函式

os.access(path,mode),path:檔案路徑,mode:F_OK,R_OK,W_OK,X_OK——是否存在,可讀,可寫,可執行

os.chdir(path)(改變當前工作目錄)

os.chomd(path,mode),修改許可權,Unix可用

os.chown(path, uid, gid),更改檔案所有者,Unix可用,uid: 所屬使用者ID,gid :所屬使用者組 ID

os.closerange(fd_low, fd_high) 關閉所有檔案描述符(open的返回值),從 fd_low (包含) 到 fd_high (不包含), 錯誤會忽略

os.dup(fd) 複製檔案描述符 fd

os.getcwd() 輸出當前目錄

錯誤和異常

Python 有兩種錯誤:語法錯誤和異常。

assert(斷言)用於判斷一個表示式,在表示式條件為 false 的時候觸發異常。

執行期檢測到的錯誤被稱為異常。

異常處理

try/except語句

一個 try 語句可能包含多個except子句,一個except子句可以同時處理多個異常,這些異常將被放在一個括號裡成為一個元組。

最後一個except子句可以忽略異常的名稱,它將被當作萬用字元使用。你可以使用這種方法列印一個錯誤資訊,然後再次把異常丟擲(raise)。

try/except...else

必須放在所有的 except 子句之後,else 子句將在 try 子句沒有發生任何異常的時候執行。

使用 else 子句比把所有的語句都放在 try 子句裡面要好,這樣可以避免一些意想不到,而 except 又無法捕獲的異常。

try-finally

無論是否發生異常都將執行最後的程式碼。

丟擲異常

raise語法格式如下:

raise [Exception [, args [, traceback]]]

raise 唯一的一個引數指定了要被丟擲的異常。必須是一個異常的例項或者是異常的類( Exception 的子類)。

如果不想去處理異常,那麼一個簡單的 raise 語句就可以再次把它丟擲。

自定義異常

可以通過建立一個新的異常類來擁有自己的異常。異常類繼承自 Exception 類,可以直接繼承,或者間接繼承。

class MyError(Exception):
    def __init__(self, value):
            self.value = value
    def __str__(self):
            return repr(self.value)

當建立一個模組有可能丟擲多種不同的異常時,一種通常的做法是為這個包建立一個基礎異常類,然後基於這個基礎類為不同的錯誤情況建立不同的子類,大多數的異常的名字都以Error結尾,就跟標準的異常命名一樣。

定義清理行為以及預定義的清理行為

如果一個異常在 try 子句裡(或者在 except 和 else 子句裡)被丟擲,而又沒有任何的 except 把它截住,那麼這個異常會在 finally 子句執行後被丟擲。

一些物件定義了標準的清理行為,無論系統是否成功的使用了它,一旦不需要它了,那麼這個標準的清理行為就會執行。

關鍵詞 with 語句可以保證物件在使用完之後一定會正確的執行他的清理方法:

with open("myfile.txt") as f:
  for line in f:
    print(line, end="")

就算在處理過程中出問題了,檔案 f 總是會關閉。

assert斷言

用於判斷一個表示式,在表示式條件為 false 的時候觸發異常。

斷言可以在條件不滿足程式執行的情況下直接返回錯誤,而不必等待程式執行後出現崩潰的情況

語法格式如下:

assert expression [, arguments]

以下例項判斷當前系統是否為 Linux,如果不滿足條件則直接觸發異常,不必執行接下來的程式碼:

import sys
assert ('linux' in sys.platform), "該程式碼只能在 Linux 下執行"

# 接下來要執行的程式碼

面向物件

Python從設計之初就已經是一門面向物件的語言

面向物件技術介紹此處不再詳細介紹

Python中的類提供了面向物件程式設計的所有基本功能:類的繼承機制允許多個基類,派生類可以覆蓋基類中的任何方法,方法中可以呼叫基類中的同名方法。

物件可以包含任意數量和型別的資料。

**例項變數:**在類的宣告中,屬性是用變數來表示的,這種變數就稱為例項變數,例項變數就是一個用 self 修飾的變數。

類物件

類有一個名為__init__()的特殊方法(構造方法),該方法在類例項化時會自動呼叫。

__init__() 方法可以有引數,引數通過 __init__()傳遞到類的例項化操作上。

def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart
x = Complex(3.0, -4.5)

self代表類的例項,而非類

類的方法與普通的函式只有一個區別——它們必須有一個額外的第一個引數名稱, 一般它的名稱是 self。self 不是 python 關鍵字,我們把他換成 其他 也是可以正常執行的。

繼承

class DerivedClassName(BaseClassName1):
    <statement-1>
    .
    .
    .
    <statement-N>

BaseClassName(示例中的基類名)必須與派生類定義在一個作用域內。除了類,還可以用表示式,基類定義在另一個模組中時:

class DerivedClassName(modname.BaseClassName):

多繼承

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>

父類的順序:若是父類中有相同的方法名,而在子類使用時未指定,python從左至右搜尋 即方法在子類中未找到時,從左到右查詢父類中是否包含方法。

方法重寫

super() 函式是用於呼叫父類(超類)的一個方法。是用來解決多重繼承問題的,直接用類名呼叫父類方法在使用單繼承的時候沒問題,但是如果使用多繼承,會涉及到查詢順序(MRO)、重複呼叫(鑽石繼承)等種種問題。

以下是 super() 方法的語法:

super(type[, object-or-type])
  • type – 類。
  • object-or-type – 類,一般是 self

Python3.x 和 Python2.x 的一個區別是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx

類定義外呼叫父類函式也是super(type[, object-or-type]),self改成類物件

**子類重寫__init__()方法又需要呼叫父類的方法:**使用super關鍵詞:

super(子類,self).__init__(引數1,引數2....)
父類名稱.__init__(self,引數1,引數2...)
class Son(Father):
  def __init__(self, name):   
    super(Son, self).__init__(name)

類屬性與方法

私有屬性

__private_attrs:兩個下劃線開頭,宣告該屬性為私有,不能在類的外部被使用或直接訪問。在類內部的方法中使用時 self.__private_attrs

類的私有方法

__private_method:兩個下劃線開頭,宣告該方法為私有方法,只能在類的內部呼叫 ,不能在類的外部呼叫。self.__private_methods

類的專有方法

  • __init__ : 建構函式,在生成物件時呼叫
  • __del__: 解構函式,釋放物件時使用
  • __repr__ : 列印,轉換
  • __setitem__: 按照索引賦值
  • __getitem__: 按照索引獲取值
  • __len__: 獲得長度
  • __cmp__: 比較運算
  • __call__: 函式呼叫
  • __add__: 加運算
  • __sub__: 減運算
  • __mul__: 乘運算
  • __truediv__: 除運算
  • __mod__: 求餘運算
  • __pow__: 乘方

運算子過載

#!/usr/bin/python3
 
class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b
 
   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)
 
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)

名稱空間和作用域

名稱空間

名稱空間(Namespace)是從名稱到物件的對映,大部分的名稱空間都是通過 Python 字典來實現的。

名稱空間提供了在專案中避免名字衝突的一種方法。各個名稱空間是獨立的,沒有任何關係的,所以一個名稱空間中不能有重名,但不同的名稱空間是可以重名而沒有任何影響。

一般有三種名稱空間:內建名稱(built-in names)——Python 語言內建的名稱,全域性名稱(global names)——模組中定義的名稱,區域性名稱(local names)——函式中定義的名稱

名稱空間查詢順序:區域性的名稱空間 -> 全域性名稱空間 -> 內建名稱空間。找不到就查詢並引發一個 NameError 異常。

名稱空間的生命週期:名稱空間的生命週期取決於物件的作用域,如果物件執行完成,則該名稱空間的生命週期就結束。因此,我們無法從外部名稱空間訪問內部名稱空間的物件。

作用域

作用域就是一個 Python 程式可以直接訪問名稱空間的正文區域。

在一個 python 程式中,直接訪問一個變數,會從內到外依次訪問所有的作用域直到找到,否則會報未定義的錯誤。

Python的作用域一共有4種,分別是:

有四種作用域:L(Local):最內層,包含區域性變數,E(Enclosing):包含了非區域性(non-local)也非全域性(non-global)的變數。G(Global):當前指令碼的最外層,B(Built-in): 包含了內建的變數/關鍵字等。

規則順序: L –> E –> G –> B

全域性變數和區域性變數

定義在函式內部的變數擁有一個區域性作用域,定義在函式外的擁有全域性作用域。

區域性變數只能在其被宣告的函式內部訪問,而全域性變數可以在整個程式範圍內訪問。呼叫函式時,所有在函式內宣告的變數名稱都將被加入到作用域中。

global 和 nonlocal關鍵字

當內部作用域想修改外部作用域的變數時,就要用到global和nonlocal關鍵字了。

def fun1():
    global num  # 需要使用 global 關鍵字宣告
    print(num) 
    num = 123
    print(num)
def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal關鍵字宣告
        num = 100
        print(num)
    inner()
    print(num)

標準庫概覽

作業系統介面

建議使用 import os 風格而非 from os import *。這樣可以保證隨作業系統不同而有所變化的 os.open() 不會覆蓋內建函式 open()。

針對日常的檔案和目錄管理任務,:shutil 模組提供了一個易於使用的高階介面:

>>> import shutil
>>> shutil.copyfile('data.db', 'archive.db')
>>> shutil.move('/build/executables', 'installdir')

檔案萬用字元

glob模組提供了一個函式用於從目錄萬用字元搜尋中生成檔案列表:

>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']

命令列引數

通用工具指令碼經常呼叫命令列引數。這些命令列引數以連結串列形式儲存於 sys 模組的 argv 變數。

>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']

錯誤輸出重定向和程式終止

sys 還有 stdin,stdout 和 stderr 屬性,即使在 stdout 被重定向時,後者也可以用於顯示警告和錯誤資訊。

>>> sys.stderr.write('Warning, log file not found starting a new one\n')

大多指令碼的定向終止都使用 “sys.exit()”。

字串正則匹配

re模組為高階字串處理提供了正則表示式工具。

>>> 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'

如果只需要簡單的功能,應該首先考慮字串方法

數學

math模組為浮點運算提供了對底層C函式庫的訪問,random提供了生成隨機數的工具。

訪問 網際網路

有幾個模組用於訪問網際網路以及處理網路通訊協議。其中最簡單的兩個是用於處理從 urls 接收的資料的urllib.request 以及用於傳送電子郵件的 smtplib:

日期和時間

datetime模組為日期和時間處理同時提供了簡單和複雜的方法。

支援日期和時間演算法的同時,實現的重點放在更有效的處理和格式化輸出。

該模組還支援時區處理

資料壓縮

以下模組直接支援通用的資料打包和壓縮格式:zlib,gzip,bz2,zipfile,以及 tarfile。

效能度量

from timeit import Timer

有些使用者對了解解決同一問題的不同方法之間的效能差異很感興趣。Python 提供了一個度量工具,為這些問題提供了直接答案。

測試模組

doctest模組提供了一個工具,掃描模組並根據程式中內嵌的文件字串執行測試。

[‘primes.py’, ‘random.py’, ‘quote.py’]


### 命令列引數

通用工具指令碼經常呼叫命令列引數。這些命令列引數以連結串列形式儲存於 sys 模組的 argv 變數。

```python
>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']

錯誤輸出重定向和程式終止

sys 還有 stdin,stdout 和 stderr 屬性,即使在 stdout 被重定向時,後者也可以用於顯示警告和錯誤資訊。

>>> sys.stderr.write('Warning, log file not found starting a new one\n')

大多指令碼的定向終止都使用 “sys.exit()”。

字串正則匹配

re模組為高階字串處理提供了正則表示式工具。

>>> 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'

如果只需要簡單的功能,應該首先考慮字串方法

數學

math模組為浮點運算提供了對底層C函式庫的訪問,random提供了生成隨機數的工具。

訪問 網際網路

有幾個模組用於訪問網際網路以及處理網路通訊協議。其中最簡單的兩個是用於處理從 urls 接收的資料的urllib.request 以及用於傳送電子郵件的 smtplib:

日期和時間

datetime模組為日期和時間處理同時提供了簡單和複雜的方法。

支援日期和時間演算法的同時,實現的重點放在更有效的處理和格式化輸出。

該模組還支援時區處理

資料壓縮

以下模組直接支援通用的資料打包和壓縮格式:zlib,gzip,bz2,zipfile,以及 tarfile。

效能度量

from timeit import Timer

有些使用者對了解解決同一問題的不同方法之間的效能差異很感興趣。Python 提供了一個度量工具,為這些問題提供了直接答案。

測試模組

doctest模組提供了一個工具,掃描模組並根據程式中內嵌的文件字串執行測試。

unittest模組不像 doctest模組那麼容易使用,不過它可以在一個獨立的檔案裡提供一個更全面的測試集:

總結

稀裡糊塗地過了一遍菜鳥教程,學習了面向物件,函式,檔案,輸入輸出,錯誤和異常,以及作業系統的操作,基本內容是學完了,再找點題練練手,邊練邊學吧