python—面向對象編程

来源:http://www.cnblogs.com/melonjiang/archive/2016/01/17/5135101.html
-Advertisement-
Play Games

面向對象編程簡單來說就是基於對類和對象的使用,所有的代碼都是通過類和對象來實現的編程就是面向對象編程!面向對象的三大特性:封裝、繼承、多態首先創建一個類#使用class創建一個School類,類中有個student方法class School: def student(self): ...


面向對象編程簡單來說就是基於對  和 對象 的使用,所有的代碼都是通過類和對象來實現的編程就是面向對象編程!

面向對象的三大特性:封裝、繼承、多態

首先創建一個類

#使用class創建一個School類,類中有個student方法
class School:
    def student(self):
        pass
a1=School()

一、封裝

1、封裝:將某些內容先封裝到一個地方,等到需要的時候再去調用

class School:
    def __init__(self,name,age):    #構造方法,創建對象是執行
        self.name=name
        self.age=age

#創建對象a1,a2
a1=School("zhangsan",18)
a2=School("lisi",18)

上面代碼實現的就是封裝的功能,把各自的name和age分別封裝到了self的name和age屬性中,就等於被封裝到了對象a1和a2中

類中定義的函數叫做方法,帶有__init__的函數稱為構造方法,在創建a1,a2對象時會自動執行。

2、調用:調用有兩種方式,通過對象直接調用和通過self間接調用

通過對象直接調用

class School:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):
        print("name:%s,age:%s"%(self.name,self.age))
#創建對象a1,a2
a1=School("zhangsan",18)
a2=School("lisi",18)
#執行結果:
#name:zhangsan,age:18
#name:lisi,age:18

通過self間接調用

class School:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):
        print("name:%s,age:%s"%(self.name,self.age))
#創建對象a1,a2
a1=School("zhangsan",18)
a2=School("lisi",18)

#執行類中的方法時,通過self間接調用被封裝的內容
a1.student()
a2.student()
#執行結果:
#name:zhangsan,age:18
#name:lisi,age:18

二、繼承

1、繼承:既派生類(子類)可以繼承基類(父類)的方法,我們可以將多個類共有的方法提取到父類當中,這樣子類僅需繼承父類而不必一一實現每個方法

在類名後面括弧中寫上另一個類,表示繼承了那個類

#使用class創建一個School類
class School:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):
        print("name:%s,age:%s"%(self.name,self.age))
    def classroom(self):
        print("%s去教室"%self.name)

class SchoolA(School):  #SchoolA繼承School
    def __init__(self,name):
        self.name=name

class SchoolB(SchoolA): #SchoolB繼承SchoolA
    def __init__(self,name):
        self.name=name
#創建對象a1
a1=SchoolA("zhangsan")
a1.classroom()
#創建對象a2
a2=SchoolB("lisi")
a2.classroom()

#執行結果:
#   zhangsan去教室
#   lisi去教室

在上面代碼中我們可以看到,在SchoolA和SchoolB中都沒有classroom方法,但由於SchoolB繼承了SchoolA,而SchoolA又繼承了School,所以他們創建對象後都能

調用School中的classroom方法。

2、多繼承

在python中,類還可以繼承多個類,在繼承多個類時,他對類中的函數查找有兩種方式

  深度優先:類是經典類時,多繼承情況下,會按照深度優先方式查找

  廣度優先:類是新式類時,多繼承情況下,會按照廣度優先方式查找

(在python3.x中)都預設為廣度優先,但還是可以瞭解一下兩個的區別,新式類:當前類或者基類繼承了objiect類就叫新式類,否者就是經典類

在python2.7中

#python2.7中經典類
class A():
    def name(self):
        print("AAAAAA")
class B(A):
    pass
class C(A):
    def name(self):
        print("CCCCCC")
class D(B,C):
    pass
a1=D()
a1.name()   #輸出:AAAAAA
#查找順序:# 首先去自己D類中查找,如果沒有,則繼續去B類中找,沒有則繼續去A類中找,沒有則繼續去C類中找,如果還是未找到,則報錯
#深度優先:D-B-A-C
#python2.7中新式類
class A(object):
    def name(self):
        print("AAAAAA")
class B(A):
    pass
class C(A):
    def name(self):
        print("CCCCCC")
class D(B,C):
    pass
a1=D()
a1.name()   #輸出:CCCCCC
#查找順序:# 首先去自己D類中查找,如果沒有,則繼續去B類中找,沒有則繼續去C類中找,沒有則繼續去A類中找,如果還是未找到,則報錯
#廣度優先:D-B-C-A

上面兩個例子中我們可以看到,經典類和新式類輸出的結果是不一樣的,是因為他們的查找順序不一樣

python2.7中 廣度優先的前提條件:D繼承BC,BC又同時繼承A,只有滿足這個條件,新式類才會遵循廣度優先,否者不會,例:

class A(object):
    def name(self):
        print("AAAAAA")
class B(A):
    pass
class C:
    def name(self):
        print("CCCCCC")
class D(B,C):
    pass
a1=D()
a1.name()   #輸出:AAAAAA

如果C不在繼承A,那麼就算你是新式類,他也會按照深度優先的順序查找

在python3.X之後就沒有了上面的這些區別,它的查找順序都是 廣度優先 

三、多態

python不支持多態,也用不到多態,python是一種多態語言,崇尚鴨子類型

 四、類中的成員

類中的成員:欄位、方法、屬性

1、欄位

欄位:普通欄位、靜態欄位

class School:
    headmaster="王五"
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):
        print("name:%s,age:%s"%(self.name,self.age))

#創建對象a1
a1=School("zhangsan",18)
print(a1.name)  #訪問普通欄位
print(School.headmaster)    #訪問靜態欄位

#執行結果:
#   zhangsan
#   王五

在上面代碼中,__init__函數中的就是普通欄位,headmaster就是靜態欄位

  普通欄位:屬於對象,由對象來訪問,在記憶體中每個對象都要保存一份

  靜態欄位:屬於類,由類直接訪問,在記憶體中只保存一份

2、方法

方法:普通方法、靜態方法、類方法

class School:
    headmaster="王五"
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):  #普通方法 至少一個self
        print("普通方法")

    @staticmethod       #靜態方法 任意參數
    def classroom():
        print("靜態方法")

    @classmethod
    def dormitory(cls):    #類方法 只能一個cls
        print("類方法",cls)

#創建對象a1
a1=School("zhangsan",18)
a1.student()

School.classroom()    #訪問靜態方法
School.dormitory()     #訪問類方法

'''執行結果:
    普通方法
    靜態方法
    類方法 <class '__main__.School'>
    '''

普通方法:先創建一個對象,在用對象去調用這個方法

靜態方法:直接用類調用,可以有任意參數(靜態方法可以讓類直接調用,省去了普通方法創建對象的步驟)

類方法:直接用類調用,只能一個cls參數

    上面我們可以看到執行類方法時,輸出了他傳入的參數等於<class '__main__.School'>,是一個類,意思就是執行時,它會把當前的類當成參數傳進去。

3、屬性

屬性定義:裝飾器定義、靜態欄位定義

(1)裝飾器定義

class School:
    headmaster="王五"
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):  #方法
        print("方法")

    @property
    def classroom(self):    #屬性,加上@property裝飾器,僅有一個self參數
        print("屬性")

#創建對象a1
a1=School("zhangsan",18)
a1.student()    #調用方法
a1.classroom    #調用屬性

#執行結果:
#   方法
#   屬性

在上面代碼中可以看到,在方法上加上@property裝飾器就叫屬性,屬性和方法的區別就是調用時不用加括弧

在新式類中,除了@property,還有另外兩種裝飾器

class School(object):
    def __init__(self,name,age):
        self.name=name
        self.age=age

    @property
    def classroom(self):    #屬性,加上@property裝飾器,僅有一個self參數
        print(self.name,self.age)
    @classroom.setter
    def classroom(self,age):
        self.age=age    #把age修改為傳入的參數
        print("修改",self.name,self.age)
    @classroom.deleter
    def classroom(self):
        del self.age        #刪除age
        print("刪除",self.name,self.age)

#創建對象a1
a1=School("張三",18)
a1.classroom    #1.執行後會自動調用@property方法
a1.classroom=20     #2.執行後會自動調用@classroom.setter的方法,並將20傳給age參數
del a1.classroom    #3.執行後會自動調用@classroom.deleter的方法

'''執行結果:
    張三 18
    修改 張三 20
    在執行3時會報錯,因為age已經在@classroom.deleter下麵的方法里刪除了,所以輸出self.age時會出錯
'''

(2)靜態欄位定義

class School(object):
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def classroom(self):
        print(self.name,self.age)

    def classroom_update(self,age):
        self.age=age    #把age修改為傳入的參數
        print("修改",self.name,self.age)

    def classroom_del(self):
        del self.age        #刪除age
        print("刪除",self.name,self.age)

    obj=property(classroom,classroom_update,classroom_del)  #靜態欄位方式定義屬性

#創建對象a1
a1=School("張三",18)
a1.obj  #1.執行後會自動調用classroom方法
a1.obj=20     #2.執行後會自動調用classroom_update的方法,並將20傳給age參數
del a1.obj    #3.執行後會自動調用classroom_delr的方法

4、公有成員和私有成員

在類中的每一個成員都有兩種形式:公有、私有

公有:都可以訪問      私有:只有在類的內部可以訪問

舉幾個例子

欄位

class School(object):
    deg="" #公有靜態欄位
    __cat=""   #私有靜態欄位
    def __init__(self,name,age):
        self.name=name  #公有普通欄位
        self.__age=age  #私有普通欄位

    def dormitory(self):
        print(self.__age)

    def cat(self):
        print(School.__cat)

#創建對象a1
a1=School("張三",18)
#訪問普通欄位
print(a1.name)  #輸出:張三
print(a1.age)   #報錯,提示沒有age,因為age是私有欄位,只能間接內部訪問
a1.dormitory()  #只能通過類內部訪問私有欄位
#訪問靜態欄位
print(School.deg)   #輸出:狗
print(School.__cat) #報錯
a1.cat()        #輸出:貓   可以間接通過內部的cat方法反問私有靜態欄位

方法

class School(object):

    def __init__(self,name,age):
        self.name=name
        self.__age=age

    def cat(self):  #公有方法
        print("cat")

    def __dog(self):   #私有方法
        print("dog")

    def doo(self):  #內部訪問私有方法
        a1.__dog()
#創建對象a1
a1=School("張三",18)
a1.cat()    #輸出:cat
a1.dog()    #報錯
a1.doo()    #輸出:dog  間接通過doo方法反問私有方法__dog

類中的其他成員也和上面的類似

5、類中的特殊成員

(1)__doc__

class School(object):
    """類的描述信息"""
    def __init__(self,name,age):
        self.name=name
        self.__age=age

print(School.__doc__)   #輸出:類的描述信息

(2)__init__

在上面已經說過,在創建對象是自動執行

(3)__del__

當對象在記憶體中被釋放時,自動觸發執行

(4)__call__

在創建的對象後面加括弧執行時,會自動執行類里的__call__方法

class School(object):

    def __call__(self, *args, **kwargs):
        print("觸發__call__方法")

a1=School()
a1()    #輸出:觸發__call__方法
School()()  #輸出:觸發__call__方法

(5)__dict__

獲取類或對象的所有成員

class School(object):
    """類的描述信息"""
    cat=""
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def dog(self):
        print("dog")

print(School.__dict__)  #獲取類中的成員
a1=School("張三",18)
print(a1.__dict__)  #獲取對象中的成員
'''
輸出:
{'cat': '貓', '__init__': <function School.__init__ at 0x000000000226C950>, '__dict__': <attribute '__dict__' of 'School' objects>, '__weakref__': <attribute '__weakref__' of 'School' objects>, '__module__': '__main__', 'dog': <function School.dog at 0x000000000226CAE8>, '__doc__': '類的描述信息'}
{'name': '張三', '_School__age': 18}
'''

(6)__str__

沒有__str__

class School(object):
    def __init__(self,name,age):
        self.name=name
        self.__age=age
a1=School("張三",18)
print(a1)   #輸出:<__main__.School object at 0x000000000222B278>

有__str__

class School(object):
    def __init__(self,name,age):
        self.name=name
        self.__age=age

    def __str__(self):
        return("print對象時的返回值")
a1=School("張三",18)
print(a1)   #輸出:print對象時的返回值

其他的特殊成員就不一一列舉了,因為大多數情況下也不會用到

詳細請看:http://www.cnblogs.com/wupeiqi/p/4766801.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第九章 在N層結構的應用程式中使用EF不是所有的應用都能完全地寫入到一個單個的過程中(就是駐留在一個單一的物理層中),實際上,在當今不斷發展的網路世界,大量的應用程式的結構包含經典的表現層,應用程,和數據層,並且它們可能分佈在多台電腦上,被分佈到一臺單獨的電腦上的應用程式的某個領域的邏輯層,並不...
  • 在Web開發過程中,會產生很多的js/css文件,傳統的引用外部文件的方式會產生多次的http請求,從而加重伺服器負擔且網頁載入緩慢,如何在一次請求中將多個文件一次載入出來?接下來給大家介紹在ASP.NET中動態合併載入多個js或css文件。原理:減少請求伺服器的次數達到優化效果先給大家看一下傳統引...
  • 本次給大家分享的是ajaxfileupload文件上傳插件,百度一大堆功能超炫的文件上傳插件,為什麼我們會選擇這個插件呢?原因是在此之前,我們嘗試使用過很多基於flash的上傳插件,但由於相容性,適用性等諸多問題,最終我們選擇了—ajaxfileupload.js,由於它使用的原生input標簽實現...
  • 前不久產品經理提出一個X的需求,說上傳office文件的時候需要將首頁自動截圖,用於顯示文件列表的時候將文件第一頁縮略圖展示給用戶。實現的方式有多種,這裡給大家介紹一個簡單實用的方案,用起來非常方便。1.Aspose.Pdf實現將pdf轉換為圖片功能,獲取pdf文件流 通過aspose讀取第一頁保存...
  • 1.概述 Windows Script Host除了提供一個對象模型之外,還提供了一種腳本框架,這就是WSF腳本。通過WSF約定的標記元素,可以將多種腳本語言寫的代碼塊組合起來,完成任務。除此之外,還可以實現一些DOS沒有的命令功能,通過CScript xxx.wsf /?來查看幫助文檔,幫助文檔....
  • 常用命令mvn clean:清除maven的編譯結果mvn compile:編譯mvn package:編譯、打包mvn install:編譯、打包、部署–DskipTests:編譯測試用例,但不執行測試-Dmaven.test.skip:不編譯測試用例且不執行測試–Dcheckstyle.skip...
  • 一、配置在需要上傳的工程中的pom.xml文件中加入下麵的配置releaseRelease Repositoryhttp://ip/nexus/content/repositories/releasessnapshotSnapshot Repositoryhttp://ip/nexus/conten...
  • 對於一個學過C和Objective-C的程式猿來講,Swift編程語言的語法基礎非常簡單。但是Swift也是添加了很多新的語法,比如元組、可選類型等等。一、類型轉換和C、Objective-C中的類型強轉類似,只需要將常量或者變數放進 '()' 內,然後在括弧前面加上目標類型就可以了。 1 let ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...