python面向?qū)ο缶幊?2)

類(lèi)編寫(xiě)細(xì)節(jié)

1.class 語(yǔ)句

class語(yǔ)句細(xì)節(jié)

  • python的class語(yǔ)句是屬于OOP的一種工具(即定義變量名的工具续挟,將數(shù)據(jù)和邏輯暴露給客戶(hù)端),而不是聲明式的
  • class語(yǔ)句是對(duì)象的創(chuàng)建者蔬啡,類(lèi)似于對(duì)象工廠(chǎng)
  • class語(yǔ)句是一種隱含的賦值運(yùn)算,即執(zhí)行class語(yǔ)句時(shí)镀虐,會(huì)產(chǎn)生類(lèi)對(duì)象并且將其引用存儲(chǔ)到定義的類(lèi)名稱(chēng)上
  • class語(yǔ)句與def一樣星爪,都是可執(zhí)行語(yǔ)句,即python還沒(méi)有執(zhí)行到class語(yǔ)句時(shí)粉私,類(lèi)是不存在的
  • class是復(fù)合語(yǔ)句顽腾,所有種類(lèi)語(yǔ)句都可以位于其主體內(nèi),如print, 賦值語(yǔ)句, if, def...

class語(yǔ)句如何得到命名空間

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

class語(yǔ)句一般形式

## 根據(jù)上述所言窖杀,className是類(lèi)對(duì)象的一個(gè)引用
class className(superclass1,superclass2,...):          
    '''
        定義類(lèi)屬性,屬于所有實(shí)例的共享數(shù)據(jù),通過(guò)類(lèi)語(yǔ)句下進(jìn)行定義和創(chuàng)建
    '''
    class_attr = value 
    
    
    '''
        定義實(shí)例方法以及實(shí)例屬性
    '''
    def method(self,data):      ## 定義實(shí)例方法
        self.attr = data        ## 設(shè)置實(shí)例屬性,通過(guò)帶有self的方法來(lái)分配屬性信息

2.方法

實(shí)例方法對(duì)象調(diào)用等價(jià)于類(lèi)方法函數(shù)調(diào)用

## python自動(dòng)將實(shí)例方法的調(diào)用自動(dòng)轉(zhuǎn)成類(lèi)方法函數(shù),并傳遞實(shí)例對(duì)象作為第一個(gè)參數(shù)傳遞
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,...)

調(diào)用超類(lèi)的構(gòu)造函數(shù)__init__方法

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

class Student(Person):
    pass
        
>>> s = Student()               ## 創(chuàng)建子類(lèi)時(shí)會(huì)調(diào)用父類(lèi)構(gòu)造函數(shù),原因是子類(lèi)沒(méi)有定義自己的構(gòu)造函數(shù)
call person init ....

## 為子類(lèi)增加構(gòu)造函數(shù)
class Student(Person):
    def __init__(self):
        print("call student init ....")

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

## 若要調(diào)用父類(lèi)構(gòu)造方法則必須顯示進(jìn)行調(diào)用
class Student(Person):
    """
        必須在子類(lèi)構(gòu)造函數(shù)中顯式調(diào)用父類(lèi)的構(gòu)造函數(shù),并傳遞子類(lèi)的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)方法

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

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

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

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

## person.py 使用裝飾器來(lái)聲明靜態(tài)或類(lè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)方法漓摩、類(lèi)方法與實(shí)例方法

  • 類(lèi)中帶有實(shí)例對(duì)象self的參數(shù)傳遞的方法稱(chēng)為實(shí)例方法
  • 類(lèi)中帶有類(lèi)對(duì)象cls的參數(shù)傳遞的方法并通過(guò)函數(shù)classmethod或者裝飾器@classmethod聲明的方法稱(chēng)為類(lèi)方法
  • 類(lèi)中沒(méi)有實(shí)例對(duì)象self和類(lèi)對(duì)象cls參數(shù)傳遞的方法,且通過(guò)staticmethod或裝飾器@staticmethod什么的方法稱(chēng)為靜態(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可以調(diào)用下面的函數(shù)入客,可以說(shuō)是靜態(tài)方法,但嚴(yán)格意義上是屬于類(lèi)的一個(gè)行為方法管毙,但是python2.x無(wú)法該方法
    '''
    def fn():
        print("just a fn,if py3.x,it is static method")

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

3.命名空間與作用域

  • 命名空間:用于記錄變量的軌跡,key是變量名稱(chēng),value是變量值,作用就是根據(jù)變量名稱(chēng)搜索變量
    • 使用無(wú)點(diǎn)號(hào)運(yùn)算的變量名稱(chēng)(X),將根據(jù)LEGB(local/enclosing/global/builtin)作用域查找法則來(lái)搜索變量
    • 使用點(diǎn)號(hào)的屬性名稱(chēng)(object.x)使用的是對(duì)象命名空間來(lái)搜索變量(對(duì)象:類(lèi)的實(shí)例對(duì)象和類(lèi)對(duì)象)
    • 有些作用域會(huì)對(duì)對(duì)象的命名空間進(jìn)行初始化(模塊和類(lèi))

無(wú)點(diǎn)號(hào)運(yùn)算的變量名稱(chēng)

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

點(diǎn)號(hào)的屬性變量名稱(chēng)

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

## 在對(duì)象實(shí)例的命名空間創(chuàng)建或更改屬性名稱(chēng)name
p.name = "keithl"       ## 并無(wú)進(jìn)行變量名稱(chēng)的搜索

## 在類(lèi)的命名空間中創(chuàng)建或更改屬性名稱(chēng)name
Person.name = "keithl"  ## 并無(wú)進(jìn)行變量名稱(chēng)的搜索
  • 引用
    • 基于類(lèi)的對(duì)象引用:會(huì)在對(duì)象內(nèi)搜索屬性名稱(chēng)X,若沒(méi)有找到則根據(jù)繼承搜索來(lái)查找
    • 基于模塊對(duì)象的引用:先導(dǎo)入模塊,再?gòu)哪K中讀取X
>>> p = Person()
>>> p.name          ## 從對(duì)象命名空間開(kāi)始按照繼承樹(shù)來(lái)搜索
>>> Person.name     ## 從類(lèi)的命名空間開(kāi)始按照繼承樹(shù)來(lái)搜索

命名空間字典

  • 模塊的命名空間是以字典的形式實(shí)現(xiàn)的,并且可以由屬性__dict__來(lái)顯示
  • 類(lèi)和對(duì)象可以看成一個(gè)帶有鏈接的字典,屬性點(diǎn)號(hào)就是字典索引運(yùn)算,屬性繼承就是搜索鏈接的字典
    • 實(shí)例與類(lèi)通過(guò)__class__屬性鏈接
    • 類(lèi)與超類(lèi)通過(guò)__bases__屬性鏈接,可以通過(guò)遞歸往上遍歷超類(lèi)
  • 都可以通過(guò)__dict__查看模塊桌硫、類(lèi)或者對(duì)象的屬性信息

類(lèi)與模塊的關(guān)系總結(jié)

  • 類(lèi)

    • 調(diào)用類(lèi)會(huì)創(chuàng)建新的對(duì)象
    • 由class來(lái)創(chuàng)建類(lèi)對(duì)象
    • 通過(guò)調(diào)用來(lái)使用
    • 屬于模塊的一部分
  • 模塊

    • 是數(shù)據(jù)和邏輯包
    • 通過(guò)py抑或其他語(yǔ)言來(lái)擴(kuò)展
    • 必須導(dǎo)入才能使用
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夭咬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子铆隘,更是在濱河造成了極大的恐慌卓舵,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膀钠,死亡現(xiàn)場(chǎng)離奇詭異掏湾,居然都是意外死亡裹虫,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)融击,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)筑公,“玉大人,你說(shuō)我怎么就攤上這事尊浪∈ǎ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵际长,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我兴泥,道長(zhǎng)工育,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任搓彻,我火速辦了婚禮如绸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旭贬。我一直安慰自己怔接,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布稀轨。 她就那樣靜靜地躺著扼脐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奋刽。 梳的紋絲不亂的頭發(fā)上瓦侮,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音佣谐,去河邊找鬼肚吏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛狭魂,可吹牛的內(nèi)容都是我干的罚攀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼雌澄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斋泄!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起镐牺,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤是己,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后任柜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體卒废,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沛厨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摔认。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逆皮。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖参袱,靈堂內(nèi)的尸體忽然破棺而出电谣,到底是詐尸還是另有隱情,我是刑警寧澤抹蚀,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布剿牺,位于F島的核電站,受9級(jí)特大地震影響环壤,放射性物質(zhì)發(fā)生泄漏晒来。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一郑现、第九天 我趴在偏房一處隱蔽的房頂上張望湃崩。 院中可真熱鬧,春花似錦接箫、人聲如沸攒读。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)薄扁。三九已至,卻和暖如春废累,著一層夾襖步出監(jiān)牢的瞬間泌辫,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工九默, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留震放,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓驼修,卻偏偏與公主長(zhǎng)得像殿遂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乙各,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 10,871評(píng)論 6 13
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法墨礁,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法耳峦,繼承相關(guān)的語(yǔ)法恩静,異常的語(yǔ)法,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,587評(píng)論 18 399
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)驶乾,斷路器邑飒,智...
    卡卡羅2017閱讀 134,601評(píng)論 18 139
  • 心跳 距離 呼吸 陰影 眼神 吻
    水搖絹閱讀 205評(píng)論 1 1
  • 離別是一個(gè)傷感的詞,說(shuō)到離別级乐,心里總會(huì)涌起一股憂(yōu)傷的情緒疙咸,即使離別是因?yàn)楦玫拈_(kāi)始。自古離別詩(shī)詞數(shù)不勝數(shù)风科,卻也沒(méi)讀...
    夜鶯方方閱讀 330評(píng)論 0 0