第六章 類-面向對象

Python支持面向對象,可以自己構建數據結構。

Python支持的OOP風格:

  • 封裝:將基本類結構的細節隱藏起來,通過接口實現對實例變量的所有必須訪問。
  • 繼承:允許基於類的特點創建另一個類。實現代碼共享。
  • 多態:指使用運算符或者方法時,根據調用他們的對象執行不同
  • 的操作過程。

類&對象

類是一種類型,創建新類的同時也創建了一個新的類型。

類是建立新對象的模板,對象是通過類創建的。

Python支持面向對象,通過以下方式實現:

class ClassName(BaseClasses): # class 關鍵字告訴Python定義一個類對象,支持多繼承用,分割

"""class doc""" # 通過 ClassName.__doc__ 可以查看

block

BaseClasses是基類,所有類的基類都應該是object。

對象是類的實例,類是抽象的,對象代表具體事物。通過以下方式創建一個對象:

Obj = ClassName([params])

type(ClassName) #

type(Obj) # Obj表示ClassName的對象

類和實例都有命名空間。

說明:

1、類定義

Python2.x class ClassName(object):

Python3 class ClassName():

屬性&方法

  • 屬性:

分為類和對象的兩種屬性。

針對對象的屬性,可以使用 object.__dict__ 打印當前對象擁有的屬性

類中的每個屬性必須有初始值,哪怕這個值是0或者空字符串一般在__init__完成此操作。

Python判斷某個類是否存在某個屬性的方式:

  • hasattr(class, "attr_name")
  • 靜態指定屬性

class ClassName():

class_var=0 # class_var 屬於類的屬性,類似於c++的static,通過 ClassName.class_var 在類內或者類外來訪問

def __init__(self): #self 表示調用當前方法的類對象

self.obj_var #obj_var 屬於對象的屬性

通過 . 來訪問屬性。還可以通過內置函數操作屬性,其中name為屬性的str形式,如delattr(obj, "age"):

  1. getattr(obj, name[, default]) : 訪問對象的屬性。
  2. hasattr(obj,name) : 檢查是否存在一個屬性。
  3. setattr(obj,name,value) : 設置一個屬性。如果屬性不存在,會創建一個新屬性。
  4. delattr(obj, name) : 刪除屬性
  • 動態創建屬性

在實例創建之後可以動態的給實例的命名空間增加屬性。

new_object = ClassName()

new_object.new_value = 10 # 將new_value 添加到 new_object的命名空間中,但僅存在於new_object

類也可在定義之後動態添加屬性到自己的命名空間,會對已經創建以及即將創建的所有對象生效。

  • 方法,類實例的接口(Python可對數據執行的操作):

類中的函數稱為方法。通過def定義第一個參數為 self。類內部方法調用通過self. 調用,不需要傳遞 self作為第一個參數。

def func1(self):

pass

def func2(self):

self.func1()

self表示類對象“本身”,每個方法的第一個參數必須是self。Python自動將方法的第一個參數映射到調用該方法的對象上。

print self #<__main__.classname instance="" at=""/>

print self.__class__ #__main__.ClassName

Python內置了一些類的屬性和方法。

屬性:訪問方式 ClassName.__xxx__

  1. __dict__ : 類的命名空間(包含一個字典,由類的數據屬性組成)
  2. __doc__ :類的文檔字符串,也可以使用 obj.__doc__訪問
  3. __name__: 類名
  4. __module__: 類定義所在的模塊(類的全名是'__main__.className',如果類位於一個導入模塊mymod中,那麼className.__module__ 等於 mymod)
  5. __bases__ : 類的所有父類構成元素(包含了一個由所有父類組成的元組)

基礎方法,Python內置方法

  1. __init__(self):構造函數,創建對象時調用,obj = className(args),過程:當調用className(args)時,首先創建默認實例,然後查找__init__(self, params)方法,如果存在則將默認實例映射到 self,將args傳遞給params。如果不存在__init__(self)則將默認實例返回。

通過該方法,將屬性添加到類的任何實例中。

  1. __del__(self):析構函數,使用 del 刪除變量與對象的關聯時會被調用,del obj
  2. __repr__(self):轉化為供解釋器讀取的形式,repr(obj)
  3. __str__( self ):用於將值轉化為可閱讀的形式,str(obj)
  4. __cmp__ ( self, x ):對象比較,cmp(obj, x)

類似於c++的個訪問權限的屬性和方法,Python中所有的方法和屬性(實例變量)都是公共的:

1、private:__attr、__func

以雙下劃線開始,訪問權限為私有的,不能在類的外部被使用或直接訪問。在類內部的方法中使用時 self.

上述Python通過改變名稱的方式實現。但不是絕對的,可以通過dir查看更換的名稱為_className__attrName 。可以通過修改之後的名稱訪問 instance._className__attrName。

2、protected:_attr、_func

以單下劃線開頭的表示的是 protected 類型的變量,即保護類型只能允許其本身與子類進行訪問。

3、public:

以字母開頭的屬性和方法

內置方法

1、__init__ 構造函數

2、__call__ 使用方式為 object()

垃圾回收

Python 使用引用計數實現對象跟蹤與垃圾回收。內部記錄著所有使用中的對象各有多少引用。當對象的引用計數變為0 時,會被垃圾回收。但是回收不是"立即"的,由解釋器在適當的時機,將垃圾對象佔用的內存空間回收。

繼承

Python 支持多繼承,通過繼承列表實現。所有類的祖先類是 object,自己定義的類需要繼承自object,Python採用object對象來表示類層次結構的頂層對象。所有內置對象(list、tuple等)的父類都是object>

class ClassName(BaseClass, BaseClass2, ...):

pass

1、子類的初始化需要顯示調用父類的初始化方法。

2、現在當前類查找方法,然後再去父類查找。

3、子類可以重寫父類的同名方法,這個過程叫方法的覆蓋(override),也稱為方法的重寫。

說明:子類調用父類的原理見附錄。

方法重載

Python支持運算符重載,需要實現特定的內置方法。並且提供了可重載的特殊運算符集合。

Python基於正在使用的對象類型來區分應用的運算符和方法。

1、==/!=,__eq__

屬性函數property()和@property

  • property()

函數原型:property(fget=None,fset=None,fdel=None,doc=None),用於創建和返回一個property對象。定義時在類內部創建 property 對象,將設置與獲取方法關聯到 property。可以實現 方法類屬性的調用方式。

pro_object = property(getxxx,setxxx,fdel=None,doc=None)

其中 pro_object 是一個porperty對象,。Property對象有三個方法,getter(), setter()和delete(),用來在對象創建後設置fget,fset和fdel。

def set_name(self, name):

pass

def get_name(self):

pass

name = property(get_name, set_name)

obj.set_name 等價 obj.name = 'new_name' ,實際調用 obj.set_name('new_name')

obj.get_name等價 print obj.get_name

說明:print type(Class.name ) #

  • @property (Python裝飾器實現方式)

@property廣泛應用在類的定義中,負責把一個方法變成屬性調用,即調用函數方式跟調用屬性一樣。同時@property又創建了另一個裝飾器@xx.setter,@property通過getter和setter方法來實現。可以看出@property與property功能一樣。

@property

def xxx(self): # getter

retrun self.__xxx

@xxx.setter

def xxx(self, yyy): # setter

self.__xxx = yyy

說明:print type(Class.xxx) #


分享到:


相關文章: