python物件導向編程 -- 基本概念(python3.5)

來源:互聯網
上載者:User

標籤:als   str   父類   lambda   自動   amp   call   自己的   本地   

 物件導向的編程簡要概括就是將要處理的問題抽象為資料和操作的集合,用類對其進行封裝。其中資料和操作都稱為類的屬性,它們是一般是不變的。

對類進行執行個體化產生我們所說的對象,對象有自己的屬性。對象的屬性一般是個人化的,不同的對象可能具有不同的屬性。同一個類的所有對象都共用類的屬性。

對象屬性的尋找順序為:對象自身 --> 類 --> 類的祖先類

在python中一切皆對象。

以下我們討論python中類相關的概念和文法。

1、類的定義
class ClassName:    <statement-1>    .    .    .    <statement-N>
  • 類定義必須使用class關鍵字
  • 類名最好使用大駝峰,如ClassName, 這是一種約定
  • 當輸入類定義時,一個新的命名空間產生,在類中定義的所有本地變數都放入這個新的命名空間。
  • 命名空間中的所有變數都是類的屬性。類屬性主要分為兩類,資料屬性(變數)和函數。
  • 語句塊執行完成後,產生一個類對象綁定到ClassName。ClassName的範圍由它的定義的位置決定。

python中一切皆對象,類也是對象,它是type類的執行個體。可以用 obj.__class__來查看一個對象是由那個類執行個體化而來的。

類中可以使用任何合法的語句,不過實際應用中,主要是指派陳述式和函數定義。

2、類對象

下面的代碼定義了一個 Chinese 類:

class Chinese:    """A sample example class"""    nationality = ‘China‘    def display(self):        print(self, ‘I am Chinese!‘, sep=‘, ‘)for name, value in sorted(Chinese.__dict__.items(), key=lambda x: x[0]):    print(name, ‘==>‘, value)

類定義會產生一個新的命名空間,其中包含了所有在類本地定義的變數,也就是類的屬性。這些屬性可以在類的 __dict__屬性中查看,可以將其近似等價於類的命名空間。其中 __name__形式的屬性為特殊屬性。

print(type(Chinese.__dict__))   # <class ‘mappingproxy‘>for name, value in sorted(Chinese.__dict__.items(), key=lambda x: x[0]):    print(name, ‘==>‘, value)# __dict__ ==> <attribute ‘__dict__‘ of ‘Chinese‘ objects># __doc__ ==> A sample example class# __module__ ==> __main__# __weakref__ ==> <attribute ‘__weakref__‘ of ‘Chinese‘ objects># display ==> <function Chinese.display at 0x1020759d8># nationality ==> China
  • __dict__  在類定義的時候自動產生。
  • __doc__  類定義的時候自動產生。值為類定義語句塊內第一行,類的文檔字串,由三引號引用。如果沒有值為None。
  • __module__ 類定義所在的模組,自動添加的屬性。如果是正在執行的模組,值為 __main__
  • __weakref__ 
  • display 和 nationality 使用者定義屬性

python中屬性的引用都是通過obj.name 的形式,name為對象 obj 的屬性。類中的所有屬性都可以通過obj.name 的形式引用。比如該類的兩個使用者自訂屬性:資料屬性 nationality 和 函數 display:

print(Chinese.nationality)  # Chinaprint(Chinese.display)      # <function Chinese.display at 0x1021759d8>Chinese.display(1)          # 1, I am Chinese!

通過類引用函數並對其進行調用,與普通的函數調用沒有差異。不過,在類中定義的函數一般是給執行個體使用的,不建議直接通過類引用,下面會進一步說明。

 3、類執行個體化

類的執行個體化使用和函數調用類似的文法。

xm = Chinese()

上面的語句建立了一個新的Chinese類的執行個體,並將其賦值給 xm 變數。執行個體有自己的命名空間:

print(xm.__dict__)  # {}

 可以看到 xm.__dict__ 的傳回值是一個空字典,執行個體 xm沒有自己的屬性。可以直接通過 xm.name = ‘xiaoming‘ 的形式為執行個體添加屬性。也可以通過 del xm.name 刪除該屬性:

 

xm.name = ‘xiaoming‘print(xm.__dict__)      # {‘name‘: ‘xiaoming‘}del xm.nameprint(xm.__dict__)      # {}

 

如果類的所有執行個體都具有某些屬性,只是屬性的值不同,可以通過定義執行個體的初始化方法,在方法中為執行個體添加屬性。

3.1 初始化方法

類的執行個體化過程:

  1. 執行個體化出一個對象
  2. 自動調用特殊方法 __init__對產生的對象初始化。如果類中沒有定義會在父類(父類的概念之後說明)中尋找該方法。

我們稱__init__方法為執行個體的初始化方法。

一般在執行個體初始化方法中會定義執行個體的個人化屬性,這些屬性是執行個體私人的,可以通過執行個體的__dict__屬性查看。執行個體的屬性不會影響類的屬性,換句話說類不能引用執行個體的屬性。

下面是對Chinese類的擴充:

class Chinese:    """A sample example class"""    nationality = ‘China‘    def __init__(self, name, age, gender):        self.name = name        self.age = age        self.gender = gender    def display(self):        print(self, ‘I am Chinese!‘, sep=‘, ‘)xm = Chinese(‘xiaoming‘, 18, ‘male‘)print(xm.__dict__)      # {‘name‘: ‘xiaoming‘, ‘gender‘: ‘male‘, ‘age‘: 18}print(Chinese.__dict__.keys())# dict_keys([‘__weakref__‘, ‘__module__‘, ‘__dict__‘, ‘__init__‘, ‘nationality‘, ‘display‘, ‘__doc__‘])

 self指代引用該方法的執行個體(具體實現在4.1介紹),執行個體化操作的參數列表化傳遞給__init__方法,Chinese(‘xiaoming‘, 18, ‘male‘) --> xm.__init__(‘xiaoming‘, 18, ‘male‘)

3.2 執行個體的類

查看對象的類:

  • obj.__class__
  • type(obj)
print(xm.__class__)print(type(xm))# <class ‘__main__.Chinese‘># <class ‘__main__.Chinese‘>

  判斷一個對象是不是某個類的執行個體:isinstance(obj, ClassName)

print(isinstance(xm, Chinese))# True
4 執行個體

執行個體可以操作兩種屬性:資料屬性和方法

print(xm.name, xm.age, xm.gender, sep=‘, ‘)   # xiaoming, 18, maleprint(xm.nationality, xm.display, sep=‘, ‘)   # China, <bound method Chinese.display of <__main__.Chinese object at 0x10217c898>>

有上面的代碼可以看到執行個體不僅可以引用自己的屬性,也可以引用類的屬性。類屬性可以被它的執行個體共用。

值得注意的是,執行個體對類的函數的引用。其傳回值並不是一個函數對象而是一個"bound method"綁定的方法對象。嘗試調用這個對象:

1 xm.display(1)2 # Traceback (most recent call last):3 #   File "test.py", line 28, in <module>4 #     xm.display(1)5 # TypeError: display() takes 1 positional argument but 2 were given6 xm.display()            # <__main__.Chinese object at 0x10217c7f0>, I am Chinese!

 display函數要求傳入一個位置參數,第1行給方法傳入一個參數1,調用出錯,錯誤資訊告訴我們多傳入了一個位置參數。

再次調用,不傳參,竟然能夠正常調用了!why?函數列印了傳入的值,"<__main__.Chinese object at 0x10217c7f0>",表明出入的是一個Chinese對象,在本例中只能是 xm。這是怎麼實現的呢?

4.1 執行個體方法
print(Chinese.display)print(xm.display)print(Chinese.display is xm.display)# <function Chinese.display at 0x1021759d8># <bound method Chinese.display of <__main__.Chinese object at 0x10217c7f0>># False 

 分別通過類和執行個體引用display屬性,返回的並不是同一個對象:通過類引用返回一個函數對象;通過執行個體引用返回一個"bound method"綁定的方法對象。

  • 方法:屬於某個對象的函數。當通過對象(執行個體)引用一個函數對象,函數和執行個體綁定返回一個方法對象。可以通過方法對象的__self__ 和 __func__ 屬性查看對應的執行個體和方法
    method = xm.displayprint(method.__self__)      # <__main__.Chinese object at 0x10217c7f0>print(method.__func__)      # <function Chinese.display at 0x1021759d8> 

     

  • 方法對象是可調用的,方法的調用即其對應的函數調用,特殊之處在於會將其執行個體作為第一個參數傳給函數,等價形式為:method(*args, **kwargs) ==> method.__func__(method.__self__, **args, **kwargs)。在本例中xm.display() 等價於Chinese.display(xm)。
  • 在類中定義的函數一般至少有一個位置參數,第一個位置參數一般用‘self‘標識,指代引用函數的執行個體。
  • 類中定義的函數對應到執行個體即為執行個體的方法。類中的函數一般都是通過執行個體引用的,為了便於描述下文中我們可能直接稱類中的函數為方法。

 簡要概括來說就是,方法的第一個參數由python自動填滿以引用執行個體對象。

以上是相關的基本概念,下一篇討論類的封裝、繼承相關的概念。

python物件導向編程 -- 基本概念(python3.5)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.