1. 程式人生 > 其它 >學習Python進階!!!

學習Python進階!!!

技術標籤:技術棧python正則表示式字串

類與物件

類,簡單理解就相當於一個圖紙,在程式中需要根據類來建立物件,類就是物件的圖紙,而物件是類的例項

物件的建立流程
  1. 建立一個變數
  2. 在記憶體中建立一個新物件
  3. 執行類中程式碼塊中的程式碼
  4. init__(self)方法執行
  5. 將物件的id賦值給變數

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-L005Elha-1611136578559)(images/圖片1.png)]

類的定義

類和物件都是對現實生活的或者程式中的內容的抽象

類的組成:

  • 資料(屬性)
  • 行為(方法)

呼叫方法,物件.方法名()

方法呼叫和函式呼叫的區別:

  • 函式呼叫,則呼叫時傳幾個引數,就會有幾個實參
  • 方法呼叫,預設傳遞一個引數,所以方法中至少有一個形參
class Person:
    name = 'May'

    def sayHello(param):
        print("世界", '你好')


per = Person()

print(per.sayHello())

類的特殊方法init

類的基本結構:

class 類名([父類]):
    
    公共的屬性...
    
    # 物件的初始化方法
    def _init_(self,...):
        ...
        
    # 其它方法
def mothod(self,..): ...

例項:

class Person:

    def __init__(self, name):
        # print('特殊方法執行')
        self.name = name

    def sayHello(self):
        print("%s 你好" % self.name)

per = Person("世界")

per.sayHello()


封裝

封裝指的是隱藏物件中一些不希望被外部所訪問到的屬性和方法

封裝方法一

需要提供一個getter和setter方法使外部可以訪問到屬性

  • getter:獲取物件中的指定屬性
  • setter:用來設定物件的指定屬性
class Dog:
    
    def _init_(self, name):
        self.hidden_name = name
        
    def sayHello(self):
        print("我是 %s" % self.hidden_name)
        
    def getName(self):
        return self.hidden_name
    
    def setName(self, name):
        self.hidden_name = name
        
dog = Dog("小黑")
dog.sayHello()
封裝方法二

可以為物件的屬性使用雙下劃線開頭,_XXX雙下劃線開頭的屬性,是物件的隱藏屬性,隱藏屬性只能在類的內部訪問,無法通過物件訪問

注意:其實隱藏屬性只不過是Python自動為屬性改的一個名字,實際上是將名字修改為,_類名__屬性名

class Person:
    
    def __init__(self, name):
        self.__name = name
        
    def getName(self):
        return self.__name
    
    def setName(self, name):
        self.__name = name
        
per = Person("May")
封裝方法三

property裝飾器:用來將一個get方法轉換為物件的屬性,新增property裝飾器以後我們就可以像呼叫屬性一樣使用get方法,使用property裝飾的方法,必須和屬性名一樣

class Person:

    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    # setter 方法的裝飾器:@name.setter
    @name.setter
    def name(self, name):
        self._name = name

per = Person("May")

per.name = 'May五月'
print(per.name)

繼承

繼承的簡介

繼承可以使一個類獲取其它類中的屬性和方法,在定義類時,可以在類名後的括號中指定當前類的父類(超類、基類、super),通過繼承之後子類可以直接繼承父類中的所有的屬性和方法

class Animal:

    def run(self):
        print('跑跑跑.....')

    def bark(self):
        print('叫叫叫.....')

class Dog(Animal):

    def sleep(self):
        print('睡覺時間到了.....')

class Hashiqi(Dog):

    def name(self):
        print('我是哈士奇.....')

animal = Dog()
dog = Hashiqi()
animal.bark()
dog.name()

當我們呼叫一個物件的方法時:

​ 會優先去當前物件中尋找是否具有該方法,如果有則直接呼叫

​ 如果沒有,則去當前物件的父類中尋找,如果父類中有則直接呼叫父類中的方法

​ 如果沒有,則去父類的父類中尋找,以此類推,直到找到object,如果依然沒有找到,則報錯

super()
class Animal:

    def __init__(self, name):
        self._name = name

    def run(self):
        print('跑跑跑.....')

    def bark(self):
        print('叫叫叫.....')


class Dog(Animal):

    def __init__(self, name, age):
        super().__init__(name)
        self._age = age

    def sleep(self):
        print('睡覺時間到了.....')

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age


animal = Dog('May', 18)
print(animal.name)
print(animal.age)

在Python中支援多繼承,也就是我們可以為一個類同時指定多個父類,可以在類名的()後邊新增多個類,來實現多重繼承,多重繼承,會使子類同時擁有多個父類,並且會獲取到所有父類中方法

類名._bases_這個屬性可以用來獲取當前類的所有父類

在開發中沒有特殊的情況下,應該避免使用多繼承,因為多重繼承會讓我們的程式碼過於複雜

多型

簡介

一個物件可以以不同的形態去呈現

面向物件三大特徵:

  • 封裝
    • 確保物件中的資料安全
  • 繼承
    • 保證了物件的可擴充套件性
  • 多型
    • 保證了程式的靈活性

屬性和方法

類屬性和方法
類屬性:

定義:直接在類中定義的屬性是類屬性

類屬性可以通過類或者類的例項訪問到,但是類屬性只能通過類物件來修改,無法通過例項物件來修改

類方法:

在類內部使用@classmethod來修飾的方法屬於類方法

類方法的第一個引數是cls,也會被自動傳遞,cls就是當前的類物件

​ 類方法和例項方法的區別,例項方法的第一個引數是self,類方法的第一個引數是cls

​ 類方法可以通過類方法呼叫,也可以通過例項呼叫,沒有區別

例項屬性

定義:通過例項物件新增的屬性屬於例項屬性

例項屬性只能通過例項物件來訪問和修改,類物件無法訪問修改

例項方法:

在類中定義,以self為第一個引數的方法都是例項方法

例項方法在呼叫時,Python會將呼叫物件作為self傳入

例項方法可以通過通過例項和類去呼叫

​ 當通過例項呼叫時,會自動將當前呼叫物件作為self傳入

​ 當通過類呼叫時,不會自動傳遞self,此時我們必須手動傳遞self

靜態方法

在類中使用@staticmethod來修飾的方法屬於靜態方法

靜態方法不需要指定任何的預設引數,靜態方法可以通過類和例項去呼叫

靜態方法,基本上是一個和當前類無關的方法,它只是一個儲存在當前類中函式

靜態方法一般都是一些工具方法,和當前類無關

class Person:
    """
    類屬性可以通過類或者類的例項訪問到,
    但是類屬性只能通過類物件來修改,
    無法通過例項物件來修改
    """
    count = 0
    # 類方法可以通過類方法呼叫,也可以通過例項呼叫
    @classmethod
    def person(cls):
        print("該方法是類方法...")

    # 例項方法
    # 例項方法可以通過通過例項和類去呼叫
    #   當通過例項呼叫時,會自動將當前呼叫物件作為self傳入
    #   當通過類呼叫時,不會自動傳遞self,此時我們必須手動傳遞self
    def instance(self):
        print(self, "呼叫該方法...")


per = Person()
per.count = 5
# 通過例項物件和類物件呼叫類屬性
print(per.count)
print(Person.count)
# 通過例項物件和類物件呼叫類方法
per.person()
Person.person()
# 通過例項物件和類物件呼叫例項方法
per.instance()
Person.instance(per)

特殊方法

特殊方法也稱為魔術方法。

特殊方法都是使用____開頭和結尾的,特殊方法一般不需要手動呼叫,需要在一些特殊的情況下自動執行

  • r_str_()這個特殊方法會在嘗試將物件轉換為字串的時候呼叫
    • 它的作用可以用來指定物件轉換為字串的結果
  • r_repr_()這個特殊方法會在對當前物件使用repr()函式時呼叫
    • 它的作用是指定物件在“互動模式”中直接輸出的效果
  • r_gt_()會在物件做大於比較的時候呼叫,該方法的返回值將會作為比較的結果
    • 它需要兩個引數,一個self表示當前物件,other表示和當前物件比較的物件
  • ….特殊方法有很多

模組化

模組化:將一個程式分解為一個一個小的模組

模組化的特點:

  1. 方便開發
  2. 方便維護
  3. 模組可以複用

在一個模組中引入外部模組

  • import 模組名(模組名就是python檔案的名字)

  • import 模組名 as 模組別名

    • 可以引入同一個模組多次,但是模組的例項只會建立一個
    • import可以在程式的任何位置呼叫,但是在一般情況下,import語句都會統一寫在程式的開頭
    • 在每一個模組的內部都會有一個__name__屬性,通過這個屬性可以獲取模組的名字
    • 主模組就是我麼直接通過 python 執行的模組
  • from 模組名 import 模組中需要的部分

  • from 模組名 import *

    • 匯入模組中的所有內容
    • 但是如果想限制獲取的內容,可以在模組中使用____all = [使用*可以訪問到的內容]
包中init檔案

只要匯入包,包中的init檔案就會首先執行

作用:

  • 但匯入包的時候,把一些初始化的函式、變數、類定義在__init__.py檔案中
  • 此檔案中函式,變數等的訪問,只需要通過包名.函式…
  • 結合__all__= [通過 * 可以訪問的模組]

正則表示式

正則表示式是對字串操作的一種邏輯公式,就是事先定義一些特定的字元,及這些字元的組合,組成一個規則字串,這個規則字串就稱為正則表示式

正則表示式又稱為正則表式式,規則表示式,常規表示式

正則表示式的作用:
  • 給定的字串是否符合正則表示式的過濾邏輯
  • 可以通過正則表示式,從字串中獲取我們想要的特定部分
正則表示式的特點:
  • 靈活性、邏輯性和功能性非常強
  • 可以迅速的用極簡單的方式達到字串的複雜控制
  • 對於剛接觸的人來說,比較難懂
正則表示式模組中方法

match 匹配方法是從頭進行匹配,如果匹配不成功就返回None

search 方法進行正則字串匹配方法,匹配的是整個字串

group 用來提取匹配到的內容部分

sub 替換

split 分割

# 匯入正則表示式模組
import re

str = '五月六月七月'

# match 匹配方法是從頭進行匹配,如果匹配不成功就返回None
result = re.match('五月', str)
print(result.span())

# search 方法進行正則字串匹配方法,匹配的是整個字串
result1 = re.search('七月', str)
print(result1.span())

#  group 用來提取匹配到的內容部分
print(result.group())
print(result1.group())

匹配字元:

  • . 表示任意的字元

  • ^是開頭

  • $表示的是結尾

  • [] 表示的是一個範圍

  • *用於將前面的模式匹配零次或者是多次

  • +用於將前面的模式匹配一次或者是多次

  • ?用於將前面的模式匹配一次或者是零次

  • {m} 用於驗證前面的模式匹配 m 次

  • {m,}用於驗證將前面的模式匹配 m 次或者大於 m 次

  • {m, n}用於驗證前面的模式匹配大於等於 m 小於等於 n 次

# 匯入正則表示式模組
import re

str = 'adsa46da56'

# [] 表示的是一個範圍
# search 方法匹配到一個就不在繼續往下找
result = re.search('[a-z][0-9][0-9]', str)
print(result.group())

# findall 方法匹配整個字串,找到一個繼續向下找,一直找到字串的結尾
result1 = re.findall('[a-z][0-9][0-9]', str)
print(result1)

result2 = re.findall('[a-z][0-9]+', str)
print(result2)

\A:表示從字串的開始出匹配
\Z:表示從字串的結束處開始匹配,如果存在換行,只匹配到換行前的結束字串。
\b:匹配一個單詞邊界,也就是指單詞和空格間的位置。例如'py\b'可以匹配到'python'中的'py'
\B:匹配非單詞邊界
\d:匹配任意數字,等價於[0-9]
\D:匹配任意非數字字元
\s:匹配任意空白字元
\S:匹配任意非空白字元
\w:匹配任意字母數字及下劃線
\W:匹配任意非字母數字及下劃線
\\:匹配原意的反斜槓

分組匹配

()表示分組,group(1) 表示第一組的內容,group(2) 表示第二組的內容

import re

msg = '<html>abc</html>'

result = re.match(r'<[0-9a-zA-Z]>(.+)</\1>')
print(result.group(1))

起名

起名的方式為:(?P<起的名字>)

引用:</(?P=起的名字)>

貪婪和非貪婪

貪婪:總是嘗試匹配儘可能多的字元

非貪婪:總是匹配儘可能少的字元

如果貪婪模式想轉變為非貪婪模式,只需要在正則表示式的後面加上==?==,預設是貪婪的

import re
# 預設是貪婪的,如果想將貪婪模式變為非貪婪模式,只需要在正則表示式後面加上?即可
msg = 'abc123as'

result = re.match(r'abc(\d+?)', msg)

print(result)

程序

異常

處理異常的語句:

try:
    程式碼塊(可以出現錯誤的語句)
except:
    程式碼塊(出現錯誤之後的處理方式)
else:
    程式碼塊(沒有錯誤是要執行的語句)
finally:
    程式碼塊(該程式碼塊總會執行)

異常傳播:當在函式中出現異常時,如果對異常進行處理,則異常不會再繼續傳播,如果沒有對異常進行處理,則異常會繼續向函式呼叫處傳播,如果函式呼叫處處理了異常,則不會傳播,如果沒有處理則繼續向呼叫處傳播,直到傳遞到全域性作用域(主模組)如果依然沒有處理異常,則程式終止,顯示異常資訊。

當程式執行過程中出現異常後,所有的異常資訊都會儲存到一個專門的異常物件中,而異常傳播就是異常物件拋給了呼叫處

異常物件
  • 如果except後面不跟任何內容,則此時會捕獲到所有的異常;
  • 如果在except後面跟上一個異常的型別,則此時只會捕獲該型別的異常;
print('異常執行前:')

try:
    print(May)
    # print(10/0)
except NameError:
    print('出現 NameError 錯誤')
except ZeroDivisionError:
    print('出現 ZeroDivisionError 錯誤')
except IndexError:
    print('出現 IndexError 錯誤')
    # Exception 是所有異常類的父類,所以如果except後跟的是Exception,它也會捕捉到所有的異常
    #  可以在異常類後面跟著一個 as xx 此時 xx 就是異常物件
except Exception as e:
    print('未知異常', e)
finally:
    print('該段程式總會執行')

print('異常出現後')

自定義異常物件

自定義異常的格式:

class 類名(Exception):
    程式碼塊

raise:可以向外部丟擲異常,後面可以跟一個異常類,或者是異常類的例項

# 自定義異常
class MyException(Exception):
    pass

# 求兩個數的和,要求兩個數不能是負數
def add(a, b):
    if a < 0 or b < 0:
        raise MyException('出現負數')
    r = a + b
    return r

print(add(-23, 32))

檔案

開啟檔案

python通過呼叫open()來開啟一個檔案,可以將檔案分成兩種型別

  • 純文字檔案(使用utf-8等編碼編寫的檔案)
  • 二進位制檔案(圖片、mp3、PPT等檔案)

open()開啟檔案時預設是以文字的形式開啟的,但是open(),預設的編碼是None所以處理檔案時,補習指定檔案的編碼

file_name = 'File.txt'
try:
    with open(file_name, encoding = 'utf-8') as file_obj:
        print(file_obj.read())
except Exception as e:
    print('未知錯誤', e)

讀取檔案和關閉檔案

**read()**方法用來讀取檔案中的內容,它會將內容全部儲存為一個字串返回。read()引數預設是-1,一次讀取所有的字元,如果給read()寫入引數n,則一次讀取n個字元

**close()**用來關閉已經開啟的檔案

# 開啟檔案
file_name = 'File.txt'

file_obj = open(file_name)

# 當我們獲取了檔案物件以後,所有的檔案的操作都應該通過物件進行
# read()方法用來讀取檔案中的內容,它會將內容全部儲存為一個字串返回
centent = file_obj.read()

print(centent)
# 關閉檔案
file_obj.close()

讀取大檔案:

file_name = 'File.txt'

try:
    with open(file_name, encoding="utf-8") as file_obj:
        # 定義一個變數,來指定每次讀取的大小
        chunk = 100
        
        while True:
            content = file_obj.read(chunk)
            # 檢查是否讀取到了內容
            if not content:
                break
            print(content)
except FileNotFoundError:
    print(f'{file_name} 這個檔案不存在')

with…as 語句

在with語句中可以直接使用file_obj來做檔案操作,此時這個檔案只能在with中使用,一旦with結束後文件自動關閉

file_name = 'File.txt'
try:
    with open(file_name) as file_obj:
        print(file_obj.read())
except Exception as e:
    print('未知錯誤', e)

寫入檔案

引數表示的含義:

  • r 表示只讀

  • x 表示用來建立檔案,如果檔案不存在就建立,存在則報錯

  • w 表示可以,使用 w 來寫入檔案時,如果檔案不存在會建立檔案,如果檔案存在則會截斷檔案

    截斷檔案指的是刪除原來檔案中的所有內容

  • a 表示追加內容,如果檔案不存在會建立檔案,如果檔案存在會向檔案中追加內容

  • +為操作符增加功能

    • r+ 即可讀又可寫,檔案不存在會報錯

    • w+ 即可寫又可讀

    • a+ 即可追加又可讀

file_name = 'File.txt'

# 使用open()開啟檔案必須要指定開啟檔案所需要做的操作(讀、寫、追加)
# 如果不指定操作型別,則預設是讀取檔案,而讀取檔案是不能向檔案中寫入的
# r 表示只讀
# x 表示用來建立檔案,如果檔案不存在則建立愛你,存在則報錯
# w 表示可以,使用 w 來寫入檔案時,如果檔案不存在會建立檔案,如果檔案存在則會截斷檔案
#   截斷檔案指的是刪除原來檔案中的所有內容
# a 表示追加內容,如果檔案不存在會建立檔案,如果檔案存在會向檔案中追加內容
# + 為操作符增加功能
# r+ 即可讀又可寫,檔案不存在會報錯
# w+ 即可寫又可讀
# a+ 即可追加又可讀
with open(file_name, 'w', encoding='utf-8') as file_obj:
    file_obj.write("有時候,我們活得累,")
    file_obj.write('並非生活過於刻薄,而是我們太容易被外界的氛圍所感染,')
    file_obj.write('被他人的情緒所左右')

二進位制檔案
  • b 表示讀取二進位制檔案

  • 讀取文字檔案時,是以字元為單位的

  • 讀取二進位制檔案時,是以位元組為單位的

file_name = '二進位制檔案的路徑'

# t 讀取文字檔案
# b 讀取二進位制檔案

with open(file_name, 'rb') as file_obj:
    # 讀取文字檔案時,size是以字元為單位的
    # 讀取二進位制檔案時,size是以位元組為單位的
    
    # 將讀到的二進位制檔案再寫入檔案中
    new_name = '寫入檔案的名稱'
    
    with open(new_name, 'ab') as new_obj:
        # 定義每次讀取的大小
        chunk = 100 *  1024
        
        while True:
            # 從已有物件中讀取資料
            content = file_obj.read(chunk)
            
            if not content:
                break
                
            new_obj.write(content)

seek()和tell()

seek():可以修改當前讀取的位置

seek():需要兩個引數

  • 第一個 引數,是要切換到的位置
  • 第二個引數,計算位置的方式
    • 0 從頭計算,預設值
    • 1 從當前位置計算
    • 2 從最後位置開始計算