python面向對象編程(2)

類編寫細節(jié)

1.class 語句

class語句細節(jié)

  • python的class語句是屬于OOP的一種工具(即定義變量名的工具,將數據和邏輯暴露給客戶端),而不是聲明式的
  • class語句是對象的創(chuàng)建者,類似于對象工廠
  • class語句是一種隱含的賦值運算,即執(zhí)行class語句時,會產生類對象并且將其引用存儲到定義的類名稱上
  • class語句與def一樣,都是可執(zhí)行語句,即python還沒有執(zhí)行到class語句時,類是不存在的
  • class是復合語句,所有種類語句都可以位于其主體內,如print, 賦值語句, if, def...

class語句如何得到命名空間

  • 首先,執(zhí)行類語句的時候,會從頭至尾執(zhí)行其主體內的所有語句
  • 其次,是在執(zhí)行過程中的賦值運算會在這個類作用域中創(chuàng)建變量名,從而成為對應的類對象屬性
  • 與函數相比,可以把class語句看成一個本地作用域,在class語句下定義的變量就屬于這個本地作用域
  • 與模塊相比,定義的變量名是可以共享的并且成為當前類的對象屬性

class語句一般形式

## 根據上述所言,className是類對象的一個引用
class className(superclass1,superclass2,...):          
    '''
        定義類屬性,屬于所有實例的共享數據,通過類語句下進行定義和創(chuàng)建
    '''
    class_attr = value 
    
    
    '''
        定義實例方法以及實例屬性
    '''
    def method(self,data):      ## 定義實例方法
        self.attr = data        ## 設置實例屬性,通過帶有self的方法來分配屬性信息

2.方法

實例方法對象調用等價于類方法函數調用

## python自動將實例方法的調用自動轉成類方法函數,并傳遞實例對象作為第一個參數傳遞
class Person:
    def study(self,name):
        print("%s study method in for %s" % (name,self.__class__.__name__)

>>> p = Person()
>>> p.study("keithl")
keithl study method in for Person

>>> Person.study(p,"keithl")
keithl study method in for Person

## instance.method(arg1,arg2,...) == class.method(instance,arg1,arg2,...)

調用超類的構造函數__init__方法

class Person:
    def __init__(self):
        print("call person init ....")

class Student(Person):
    pass
        
>>> s = Student()               ## 創(chuàng)建子類時會調用父類構造函數,原因是子類沒有定義自己的構造函數
call person init ....

## 為子類增加構造函數
class Student(Person):
    def __init__(self):
        print("call student init ....")

>>> s = Student()               ## 只輸出子類的__init__方法,并沒有調用父類方法,原因在于python是根據命名空間來執(zhí)行調用方法
call student init ....

## 若要調用父類構造方法則必須顯示進行調用
class Student(Person):
    """
        必須在子類構造函數中顯式調用父類的構造函數,并傳遞子類的self引用
    """
    def __init__(self):
        print("call student init start....")
        Person.__init__(self)              
        print("call student init end....")

>>> s = Student()               
call student init start....
call person init ....
call student init end....

靜態(tài)方法

  • 使用場景:
    • 目標:為所有類實例提供數據共享的類屬性
    • 執(zhí)行:通過類名稱訪問類屬性
    • 優(yōu)化:其一是使用OOP思想封裝類屬性而對外提供方法,其二是考慮擴展性,通過繼承來定制
    • 落地:使用靜態(tài)方法或者類方法,即不需要傳遞類對象self實例參數的方法
## person.py
class Person:
    num = 1
    """
        定義一個沒有帶參數的普通方法
    """
    def printNum():
        Person.num += 1
        print("the number is %s" % Person.num)
    
    printNum = staticmethod(printNum)                   ## 聲明為靜態(tài)方法
    
    """
        定義一個帶參數的普通方法,此參數為類對象參數
    """
    def clsPrintNum(cls):
        Person.num += 1
        print("the number is %s" % Person.num)         

    clsPrintNum = classmethod(clsPrintNum)              ## 聲明為類方法

>>> Person.printNum()
the number is 2

>>> Person.clsPrintNum()
the number is 3

## person.py 使用裝飾器來聲明靜態(tài)或類方法
class Person:
    num = 1
    
    @staticmethod
    def printNum():
        Person.num += 1
        print("the number is %s" % Person.num)

    @classmethod
    def clsPrintNum(cls):
        Person.num += 1
        print("the number is %s" % Person.num)

靜態(tài)方法、類方法與實例方法

  • 類中帶有實例對象self的參數傳遞的方法稱為實例方法
  • 類中帶有類對象cls的參數傳遞的方法并通過函數classmethod或者裝飾器@classmethod聲明的方法稱為類方法
  • 類中沒有實例對象self和類對象cls參數傳遞的方法,且通過staticmethod或裝飾器@staticmethod什么的方法稱為靜態(tài)方法
class Person:

    @staticmethod
    def static_method():
        print("static method ...")

    @classmethod
    def class_method(cls):
        print("class method ....")

    def instance_method(self):
        print("instance method ...")

    '''
        python3.x可以調用下面的函數,可以說是靜態(tài)方法,但嚴格意義上是屬于類的一個行為方法,但是python2.x無法該方法
    '''
    def fn():
        print("just a fn,if py3.x,it is static method")

## 總結:
1)在類中定義方法一定要規(guī)范化,明確是靜態(tài)方法還是類方法抑或是實例方法
2)避免使用最后一種方式在類中定義方法

3.命名空間與作用域

  • 命名空間:用于記錄變量的軌跡,key是變量名稱,value是變量值,作用就是根據變量名稱搜索變量
    • 使用無點號運算的變量名稱(X),將根據LEGB(local/enclosing/global/builtin)作用域查找法則來搜索變量
    • 使用點號的屬性名稱(object.x)使用的是對象命名空間來搜索變量(對象:類的實例對象和類對象)
    • 有些作用域會對對象的命名空間進行初始化(模塊和類)

無點號運算的變量名稱

  • 賦值語句:在當前作用域創(chuàng)建或更改變量X,除非聲明為全局變量
X = "global X"
def enclosing_fn():
    ## global X             
    X = "enclosing fn"      ## 創(chuàng)建當前enclosing_fn的本地變量X如果沒有聲明為全局變量的話
  • 引用:根據LEGB作用域法則來搜索變量
X = "global X"
def enclosing_fn():
    X = "enclosing fn"      ## 如果注釋此行,將打印全局的變量X
    print(X)
    def local_x()
        x = "local x"       ## 如果僅注釋此行,將會打印嵌套的變量X
        print(x)
    local_x()

點號的屬性變量名稱

  • 賦值語句:在對應的對象命名空間中創(chuàng)建或修改屬性名稱X,即object.X = value
>>> p = Person()

## 在對象實例的命名空間創(chuàng)建或更改屬性名稱name
p.name = "keithl"       ## 并無進行變量名稱的搜索

## 在類的命名空間中創(chuàng)建或更改屬性名稱name
Person.name = "keithl"  ## 并無進行變量名稱的搜索
  • 引用
    • 基于類的對象引用:會在對象內搜索屬性名稱X,若沒有找到則根據繼承搜索來查找
    • 基于模塊對象的引用:先導入模塊,再從模塊中讀取X
>>> p = Person()
>>> p.name          ## 從對象命名空間開始按照繼承樹來搜索
>>> Person.name     ## 從類的命名空間開始按照繼承樹來搜索

命名空間字典

  • 模塊的命名空間是以字典的形式實現(xiàn)的,并且可以由屬性__dict__來顯示
  • 類和對象可以看成一個帶有鏈接的字典,屬性點號就是字典索引運算,屬性繼承就是搜索鏈接的字典
    • 實例與類通過__class__屬性鏈接
    • 類與超類通過__bases__屬性鏈接,可以通過遞歸往上遍歷超類
  • 都可以通過__dict__查看模塊、類或者對象的屬性信息

類與模塊的關系總結

    • 調用類會創(chuàng)建新的對象
    • 由class來創(chuàng)建類對象
    • 通過調用來使用
    • 屬于模塊的一部分
  • 模塊

    • 是數據和邏輯包
    • 通過py抑或其他語言來擴展
    • 必須導入才能使用
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,214評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,781評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,588評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,315評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,699評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,882評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,441評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,189評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,388評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,613評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,023評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,310評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,112評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,334評論 2 377

推薦閱讀更多精彩內容

  • 國家電網公司企業(yè)標準(Q/GDW)- 面向對象的用電信息數據交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 11,067評論 6 13
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,733評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,818評論 18 139
  • 心跳 距離 呼吸 陰影 眼神 吻
    水搖絹閱讀 209評論 1 1
  • 離別是一個傷感的詞,說到離別,心里總會涌起一股憂傷的情緒,即使離別是因為更好的開始。自古離別詩詞數不勝數,卻也沒讀...
    夜鶯方方閱讀 344評論 0 0