Python學(xué)習(xí) day9-2021.3.7(面對(duì)對(duì)象基礎(chǔ)·下)


Python入門(mén)課程系列:


目標(biāo):

  1. 通過(guò)聲明私有化屬性谍咆、方法虹统,保護(hù)和控制數(shù)據(jù)(重點(diǎn))
  2. 通過(guò)property屬性的使用,即控制好數(shù)據(jù)又方便訪(fǎng)問(wèn)(重點(diǎn)童叠、難點(diǎn))
  3. 明確 _ new _ 方法的作用和用法(重點(diǎn))
  4. 通過(guò)單例模式控制實(shí)例個(gè)數(shù)(難點(diǎn))
  5. 使用異常處理機(jī)制鲜结,處理異常媒至,提高代碼健壯性
  6. 利用動(dòng)態(tài)語(yǔ)言特點(diǎn)今膊,動(dòng)態(tài)添加屬性和方法
  7. 利用 _ slot _ 屬性控制可動(dòng)態(tài)的屬性

1. 私有化屬性

前面學(xué)習(xí)面對(duì)對(duì)象過(guò)程中崎苗,修改類(lèi)屬性都是直接通過(guò)類(lèi)名修改的狐粱。如果有些重要屬性不想被被人修改,或者防止意外修改胆数,就可以將屬性定義為私有屬性肌蜻,并添加一個(gè)可調(diào)用的方式去訪(fǎng)問(wèn)。
語(yǔ)法:兩個(gè)下劃線(xiàn)開(kāi)頭必尼,聲明該屬性為私有蒋搜,不能在類(lèi)的外部被使用或直接訪(fǎng)問(wèn)。
使用私有屬性的場(chǎng)景:1. 把特定的一個(gè)屬性隱藏起來(lái)判莉,不想被類(lèi)的外部直接調(diào)用豆挽;2. 保護(hù)屬性的值不被隨意改變;3. 保護(hù)屬性不被派生類(lèi)【子類(lèi)】繼承

class Person:
    def __init__(self):
        self.__name='lele' #實(shí)例屬性前加兩個(gè)下劃線(xiàn)將其私有化
        self.age=14
        pass
    def __str__(self):
        return '{}的年齡是{}'.format(self.__name,self.age) #私有化的屬性在內(nèi)部可以使用
yt=Person()
print(yt.__name) #私有化后不能在類(lèi)的外部直接訪(fǎng)問(wèn)
# AttributeError: 'Person' object has no attribute '__name'
print(yt)  #在類(lèi)的內(nèi)部依然可以使用
#lele的年齡是14

class Student(Person):
    pass
stu=Student()
print(stu.__name) #父類(lèi)的私有化屬性券盅,子類(lèi)不能繼承
# AttributeError: 'Person' object has no attribute '__name'

小結(jié):

  1. 私有化的【實(shí)例】屬性不能在外部直接訪(fǎng)問(wèn)帮哈,但可以在類(lèi)的內(nèi)部可以訪(fǎng)問(wèn)、修改锰镀。
  2. 子類(lèi)不能繼承父類(lèi)的私有化屬性娘侍,只能繼承父類(lèi)公共的屬性和行為
  3. 在屬性前面加兩個(gè)下劃線(xiàn)就可以定義私有屬性

2. 私有化方法

私有化方法與私有化屬性一樣咖刃,有些重要的方法,不允許外部調(diào)用憾筏,防止子類(lèi)意外重寫(xiě)僵缺,把普通的方法設(shè)置成私有化方法。
語(yǔ)法:在方法名前面加兩個(gè)下劃線(xiàn)

class Animal:
    def __eat(self):  #實(shí)例方法
        print('乖乖吃')
        pass
    def run(self):
        print('飛快跑')
        pass
class Bird(Animal):
    pass
b1=Bird()
b1.run()
#飛快跑
b1.__eat()
#AttributeError: 'Bird' object has no attribute '__eat'

訪(fǎng)問(wèn)和修改私有變量:

一般寫(xiě)兩個(gè)方法一個(gè)訪(fǎng)問(wèn)踩叭,一個(gè)修改磕潮,由方法去控制訪(fǎng)問(wèn)。

class Person:
    def __init__(self):
        self.__age=18 #定義一個(gè)私有化屬性容贝,屬性名字前面加兩個(gè)__下劃線(xiàn)
    def get_age(self): #訪(fǎng)問(wèn)私有類(lèi)屬性
        return self.__age
    def set_age(self,age): #修改私有屬性
        if age<0:
            print('年齡不能小于0')
        else:
            self.__age=age

(這樣操作給調(diào)用者的感覺(jué)就是調(diào)用了一個(gè)方法自脯,并不是訪(fǎng)問(wèn)屬性。如何讓調(diào)用者直接以訪(fǎng)問(wèn)屬性的方式訪(fǎng)問(wèn)而且以我們能控制的方式提供給調(diào)用者斤富?這是就可以使用屬性函數(shù)property膏潮。)

單下劃線(xiàn)、雙下劃線(xiàn)满力、頭尾下劃線(xiàn)說(shuō)明:

  • _ xxx前面加一個(gè)下劃線(xiàn)焕参,以單下劃線(xiàn)開(kāi)頭的表示是protected類(lèi)型的變量,即保護(hù)類(lèi)型只允許其本身與子類(lèi)訪(fǎng)問(wèn)油额,不能使用from xxx import*的方式導(dǎo)入叠纷。(一般使用雙前下劃線(xiàn))
  • _ xxx _ 前后兩個(gè)下劃線(xiàn),為魔法方法潦嘶,一般是python自有涩嚣,開(kāi)發(fā)者不要?jiǎng)?chuàng)建這類(lèi)型的方法。
  • xxx _ 后單下劃線(xiàn)掂僵,避免屬性名與python關(guān)鍵字沖突

3. Property屬性

前面學(xué)習(xí)中航厚,我們一直在用“類(lèi)對(duì)象.屬性”的方式訪(fǎng)問(wèn)類(lèi)中定義的屬性,其實(shí)這種做法是欠妥的锰蓬,因?yàn)樗茐牧祟?lèi)的封裝原則幔睬。正常情況下,類(lèi)包含的屬性應(yīng)該是隱藏的芹扭,只允許通過(guò)類(lèi)提供的方法來(lái)間接實(shí)現(xiàn)對(duì)類(lèi)屬性的訪(fǎng)問(wèn)和操作麻顶。因此,在不破壞類(lèi)封裝原則的基礎(chǔ)上冯勉,為了能夠有效操作類(lèi)中的屬性澈蚌,類(lèi)中應(yīng)包含讀(或?qū)懀╊?lèi)屬性的多個(gè) getter(或 setter)方法,這樣就可以通過(guò)“類(lèi)對(duì)象.方法(參數(shù))”的方式操作屬性灼狰。此外宛瞄,Python 中提供了 property() 函數(shù),可以實(shí)現(xiàn)在不破壞類(lèi)封裝原則的前提下,讓開(kāi)發(fā)者依舊使用“類(lèi)對(duì)象.屬性”的方式操作類(lèi)中的屬性份汗。
實(shí)現(xiàn)方式:
1.在類(lèi)型定義值為property對(duì)象的類(lèi)屬性

property() 函數(shù)的基本使用格式:
屬性名=property(fget=None, fset=None, fdel=None, doc=None)盈电。
fget 參數(shù):用于指定獲取該屬性值的類(lèi)方法。
fset 參數(shù):用于指定設(shè)置該屬性值的方法杯活。
fdel 參數(shù):用于指定刪除該屬性值的方法
doc 參數(shù):是一個(gè)文檔字符串匆帚,用于說(shuō)明此函數(shù)的作用。
在使用 property() 函數(shù)時(shí)旁钧,以上 4 個(gè)參數(shù)可以?xún)H指定第 1 個(gè)吸重、或者前 2 個(gè)、或者前 3 個(gè)歪今,當(dāng)前也可以全部指定嚎幸。也就是說(shuō),property() 函數(shù)中參數(shù)的指定并不是完全隨意的寄猩。

#方法1
class Person(object):
    def __init__(self):
        self.__age=18  # 定義一個(gè)函數(shù)嫉晶,屬性名字前面加兩個(gè)下劃線(xiàn)
    def get_age(self):  # 訪(fǎng)問(wèn)私有化實(shí)例屬性
        return self.__age
    def set_age(self,age):  # 修改私有化實(shí)例屬性
        if age < 0:
            print('年齡不能小于0')
        else:
            self.__age=age
    age=property(get_age,set_age)
    # 定義一個(gè)類(lèi)屬性,當(dāng)對(duì)這個(gè)age設(shè)置值時(shí)調(diào)用set_age田篇,當(dāng)獲取值時(shí)調(diào)用get_age.注意:必須時(shí)以get,set開(kāi)頭的方法名替废,才能被調(diào)用。
    #通過(guò)調(diào)用函數(shù)property并將存取方法作為參數(shù)創(chuàng)建了一個(gè)特性泊柬,然后將名稱(chēng)age關(guān)聯(lián)到這個(gè)特性椎镣。這樣就能以同樣的方式對(duì)待get_age、set_age和age彬呻,而無(wú)需關(guān)心它們是如何實(shí)現(xiàn)的衣陶。
xiaoming=Person()
print(xiaoming.age) #若不設(shè)置property,這一行會(huì)報(bào)錯(cuò)
#18
xiaoming.age=15 #只需設(shè)置age即可闸氮,不必管類(lèi)的內(nèi)部get_age和set_age是如何運(yùn)作。通過(guò)property封裝的age是類(lèi)的接口
print(xiaoming.age)
#15

#方法2
class Person(object):
    def __init__(self):
        self.__age=18  # 定義一個(gè)函數(shù)教沾,屬性名字前面加兩個(gè)下劃線(xiàn)
    @property #使用裝飾器對(duì)age進(jìn)行裝飾蒲跨,提供一個(gè)getter方法
    def age(self):  # 訪(fǎng)問(wèn)私有化實(shí)例屬性
        return self.__age

    @age.setter  # 使用裝飾器進(jìn)行裝飾,提供一個(gè)setter方法
    def age(self,age):  # 修改私有實(shí)例屬性
        if age < 0:
            print('年齡不能小于0')
        else:
            self.__age=age
xiaoming=Person()
print(xiaoming.age)
#18
xiaoming.age=15
print(xiaoming.age)
#15

修改私有屬性的途徑:

  1. 通過(guò)方法去實(shí)現(xiàn)(set get)
  2. 借助屬性函數(shù)property去實(shí)現(xiàn)

4. _ new _ 方法

  • _ new _ 方法的作用是:創(chuàng)建并返回一個(gè)實(shí)例對(duì)象授翻,如果 _ new _ 方法只調(diào)用了一次或悲,就會(huì)得到一個(gè)對(duì)象。繼承自object的新式類(lèi)才有new這一魔法方法堪唐。
  • 注意事項(xiàng)
    1. _ new _ 是在一個(gè)對(duì)象實(shí)例化的時(shí)候所調(diào)用的第一個(gè)方法
    2. _ new _ 至少必須要有一個(gè)參數(shù)cls巡语,代表要實(shí)例化的類(lèi) ,此參數(shù)在實(shí)例化時(shí)由Python解釋器自動(dòng)提供淮菠,其他參數(shù)是要來(lái)直接傳遞給_ init _ 方法
    3. _ new _ 決定是否要使用該 _ init _ 方法男公,因?yàn)?_ new _ 可以調(diào)用其他類(lèi)的構(gòu)造方法或者直接返回別的實(shí)例對(duì)象來(lái)作為本類(lèi)的實(shí)例,如果 _ new _ 沒(méi)有返回實(shí)例對(duì)象合陵,則 _ init _ 不會(huì)被調(diào)用
    4. 在 _ new _ 方法中枢赔,不能調(diào)用自己的 _ new _ 方法澄阳,即:return cls. _ new _ (cls),否則會(huì)報(bào)錯(cuò)(RescursionError: maximum recursion depth exceeded:超過(guò)最大遞歸深度)
  • 盡管沒(méi)有添加標(biāo)識(shí)踏拜,但new方法是一個(gè)靜態(tài)方法
class Animal():
    def __init__(self):
        self.color='紅色'
        pass
    #在python當(dāng)中碎赢,如果不重寫(xiě)new方法,如下是默認(rèn)的new
    def __new__(cls, *args, **kwargs):  #cls表示當(dāng)前class
        #方法1 用super來(lái)創(chuàng)建 
        return super().__new__(cls, *args, **kwargs)  #super是調(diào)用父類(lèi)
        #方法2 用object來(lái)創(chuàng)建
        return object.__new__(cls, *args, **kwargs)
    pass
tiger=Animal() #實(shí)例化的過(guò)程中會(huì)自動(dòng)調(diào)用new去創(chuàng)建實(shí)例
print(tiger.color)
#紅色

在新式類(lèi)(python3)中速梗,_ new _ 才是真正的實(shí)例化方法肮塞,為類(lèi)提供外殼制造出實(shí)例框架,然后調(diào)用該框架內(nèi)的構(gòu)造方法 _ init _ 來(lái)進(jìn)行豐滿(mǎn)操作姻锁。
以建房子來(lái)比喻峦嗤,new方法負(fù)責(zé)開(kāi)發(fā)地皮,打地基屋摔,并將原料存放在工地上烁设,而init負(fù)責(zé)從工地取原料,建造出地皮開(kāi)發(fā)圖紙規(guī)定的大樓钓试,并負(fù)責(zé)細(xì)節(jié)設(shè)計(jì)装黑、建造、最終完成弓熏。

5. 單例模式

單例模式要求一個(gè)類(lèi)有且只有一個(gè)實(shí)例恋谭,并且提供了一個(gè)全局的訪(fǎng)問(wèn)點(diǎn)。

  • 單例模式是常用設(shè)計(jì)模式的一種挽鞠。目的:確保某一個(gè)類(lèi)只有一個(gè)實(shí)例存在疚颊。就比如我們打開(kāi)電腦的回收站 ,在系統(tǒng)中只能打開(kāi)一個(gè)回收站信认,也就是說(shuō)這整個(gè)系統(tǒng)中只有一個(gè)實(shí)例材义,重復(fù)打開(kāi)也是使用這個(gè)實(shí)例。
  • 簡(jiǎn)單的說(shuō)就是不管創(chuàng)建多少次對(duì)象嫁赏,類(lèi)返回的對(duì)象都是最初創(chuàng)建的其掂,不會(huì)再新建其他對(duì)象。
#基于 _ new _ 方法實(shí)現(xiàn)單例對(duì)象的創(chuàng)建
#例1
class SingleCase(object):
    __instance=None #保存實(shí)例對(duì)象
    def __init__(self,name,age):
        print(name,age)
    def __new__(cls, *args, **kwargs):
        #如果類(lèi)屬性__instance的值為None,那么創(chuàng)建一個(gè)對(duì)象
        #如果類(lèi)屬性__instance的值不為None,返回 __instance保存的對(duì)象
        if not cls.__instance:
            cls.__instance=super(SingleCase, cls).__new__(cls) #調(diào)用父類(lèi)_new_方法生成一個(gè)實(shí)例對(duì)象
            return cls.__instance
        else:
            return cls.__instance

obj1=SingleCase('huahua',18)
obj2=SingleCase('miao',8)
print(id(obj1))
print(id(obj2))
#huahua 18
#miao 8
#140691412397840   #id相同潦蝇,說(shuō)明實(shí)例化兩次對(duì)象款熬,實(shí)際上都是一個(gè)對(duì)象
#140691412397840

#例2
class DataBaseClass(object):
    def __new__(cls, *args, **kwargs):
        # cls._instance=cls.__new__(cls)   不能使用自身的new方法,容易造成一個(gè)深度遞歸攘乒,應(yīng)該調(diào)用父類(lèi)的new方法
        if not hasattr(cls,'_instance'): #如果不存在就開(kāi)始創(chuàng)建
        #hasattr()函數(shù)用于判斷對(duì)象是否包含對(duì)應(yīng)的屬性
            cls._instance=super().__new__(cls, *args, **kwargs)
        return cls._instance
    pass
db1=DataBaseClass()
print(id(db1))
db2=DataBaseClass()
print(id(db2))
#140663654493968
#140663654493968   #并不是只能返回同一個(gè)對(duì)象贤牛,而是每次返回相同的對(duì)象

利用類(lèi)屬性保存初次創(chuàng)建的實(shí)例對(duì)象,第二次實(shí)例化的 時(shí)候就判斷類(lèi)屬性是否有保存實(shí)例對(duì)象 则酝,如果有就返回類(lèi)屬性保存的殉簸,如果沒(méi)有就調(diào)用父類(lèi) _ new _ 方法創(chuàng)建新的實(shí)例對(duì)象

  • 應(yīng)用 :網(wǎng)站的計(jì)數(shù)器模塊、權(quán)限驗(yàn)證模塊、windows資源管理器喂链、系統(tǒng)回收站返十、數(shù)據(jù)庫(kù)連接池等等

6. 錯(cuò)誤與異常處理

在代碼出現(xiàn)錯(cuò)誤時(shí) ,當(dāng)程序執(zhí)行到錯(cuò)誤代碼的時(shí)候椭微,程序會(huì)直接終止并報(bào)錯(cuò)洞坑,這是因?yàn)?python檢測(cè)到一個(gè)錯(cuò)誤時(shí),解釋器就無(wú)法繼續(xù)執(zhí)行了 蝇率,出現(xiàn)了錯(cuò)誤的提示迟杂,這就是“異常”本慕。

語(yǔ)法格式:

  • try:可能出現(xiàn)錯(cuò)誤的代碼塊
  • except:出錯(cuò)之后執(zhí)行的代碼塊
  • else:沒(méi)有出錯(cuò)的代碼塊
  • finally:不管有沒(méi)有出錯(cuò)都執(zhí)行的代碼塊
  1. try ... except語(yǔ)句:
    將可能出錯(cuò)的代碼放到try里面 排拷,except可以指定類(lèi)型捕獲異常。用來(lái)檢測(cè)try語(yǔ)句塊中的錯(cuò)誤锅尘,從而讓except語(yǔ)句捕獲異常信息并處理监氢。如果你不想在異常發(fā)生時(shí)結(jié)束你的程序,只需在try里捕獲它藤违。這樣程序員就不會(huì)因?yàn)橐欢未a包異常而導(dǎo)致整個(gè)程序崩潰
  • except在捕獲錯(cuò)誤異常的時(shí)候浪腐,是需要根據(jù)具體的錯(cuò)誤類(lèi)型來(lái)捕獲的。
  • 用一個(gè)塊可以捕獲多個(gè)不同類(lèi)型的異常顿乒,但一次只能捕獲一個(gè)異常
print(b) #因?yàn)檫@一步的錯(cuò)誤導(dǎo)致后面的代碼都無(wú)法運(yùn)行
print('你好')
print(3333)

try:
    print(b) 
    pass
except NameError as msg:
    #捕獲到的錯(cuò)誤才會(huì)在這里執(zhí)行
    print(msg) #輸出異常
    pass
except IndexError as msg:
    #多設(shè)置幾種類(lèi)型的錯(cuò)誤议街,就可以多捕獲幾種類(lèi)型的錯(cuò)誤 
    print(msg) #輸出異常
    pass
except Exception as result: #??可以捕獲所有的錯(cuò)誤類(lèi)型,使用這個(gè)就不必設(shè)置要捕獲的錯(cuò)誤類(lèi)型
    print(result)
    #在此去處理捕獲到的錯(cuò)誤
    pass
print('你好')
print(3333)
#name 'b' is not defined
#你好
#3333
  • 不需要在每個(gè)可能出錯(cuò)的地方去捕獲璧榄,只要在合適的層次去捕獲錯(cuò)誤就可以了
def A(s):
    return 10/int(s)
    pass
def B(s):
    return A(s)*2
def main():
    try:
        B('0')
        pass
    except Exception as msg:
        print(msg)
        pass
    pass
main()
#division by zero

異常的拋出機(jī)制:
如果在運(yùn)行時(shí)發(fā)生異常特漩,解釋器會(huì)查找相應(yīng)的異常捕獲類(lèi)型。如果在當(dāng)前函數(shù)里面沒(méi)有找到的話(huà)骨杂,它會(huì)將異常值傳遞給上層的調(diào)用函數(shù)涂身,看能否處理。如果在最外層沒(méi)有找到的話(huà) 腊脱,解釋器就會(huì)退出访得,程序down掉。

  1. try ... except...else語(yǔ)句:
try:
    print (aa)
    pass
except Exception as msg:
    print(msg)
else:
    print('當(dāng)try里面的代碼沒(méi)有出現(xiàn)異常的情況下陕凹,我才會(huì)執(zhí)行')
#name 'aa' is not defined

try:
    print ('我是沒(méi)有錯(cuò)誤的')
    pass
except Exception as msg:
    print(msg)
else:
    print('當(dāng)try里面的代碼沒(méi)有出現(xiàn)異常的情況下,我才會(huì)執(zhí)行')
#我是沒(méi)有錯(cuò)誤的
#當(dāng)try里面的代碼沒(méi)有出現(xiàn)異常的情況下鳄炉,我才會(huì)執(zhí)行
  1. try ... except...finally語(yǔ)句:
try:
    int('fff')
    pass
except Exception as msg:
    print(msg)
    pass
finally:
    print('釋放文件的資源杜耙、數(shù)據(jù)庫(kù)的資源等等')
    print('不管有沒(méi)有出錯(cuò)都執(zhí)行的代碼塊')
#invalid literal for int() with base 10: 'fff'
#釋放文件的資源、數(shù)據(jù)庫(kù)的資源等等
#不管有沒(méi)有出錯(cuò)都執(zhí)行的代碼塊
  1. 自定義異常
  • 自定義異常都要直接或間接即成Error或Exception類(lèi)
  • 由開(kāi)發(fā)者主動(dòng)拋出自定義異常拂盯,在python中使用raise關(guān)鍵字
class ToolongException(Exception): ##自定義異常類(lèi)型需要繼承Exception
    def __init__(self,leng):
        '''
        :param leng: 長(zhǎng)度
        '''
        self.len=leng
        pass
    def __str__(self):
        return '您輸入的姓名數(shù)據(jù)長(zhǎng)度是'+str(self.len)+'超出限定長(zhǎng)度'
    pass
def name_Test():
    name=input('請(qǐng)輸入姓名:')
    try:
        if len(name)>5:
            raise ToolongException(len(name))
        else:
            print(name)
            pass
        pass
    except ToolongException as result:
        print(result)
        pass
    finally:
        print('')
name_Test()

??python中常見(jiàn)的異常錯(cuò)誤類(lèi)型:

異常名稱(chēng) 描述
BaseException 所有異常的基類(lèi)
ArithmeticError 所有數(shù)值計(jì)算錯(cuò)誤的基類(lèi)
AssertionError 斷言語(yǔ)句失敗
AttributeError 對(duì)象沒(méi)有這個(gè)屬性
DeprecationWarning 關(guān)于被棄用的特征的警告
EnvironmentError 操作系統(tǒng)錯(cuò)誤的基類(lèi)
EOFError 沒(méi)有內(nèi)建輸入,到達(dá)EOF 標(biāo)記
Exception 常規(guī)錯(cuò)誤的基類(lèi)
FloatingPointError 浮點(diǎn)計(jì)算錯(cuò)誤
FutureWarning 關(guān)于構(gòu)造將來(lái)語(yǔ)義會(huì)有改變的警告
GeneratorExit 生成器(generator)發(fā)生異常來(lái)通知退出
ImportError 導(dǎo)入模塊/對(duì)象失敗
IndentationError 縮進(jìn)錯(cuò)誤
IndexError 序列中沒(méi)有此索引(index)
IOError 輸入/輸出操作失敗
KeyboardInterrupt 用戶(hù)中斷執(zhí)行(通常是輸入^C)
KeyError 映射中沒(méi)有這個(gè)鍵
LookupError 無(wú)效數(shù)據(jù)查詢(xún)的基類(lèi)
MemoryError 內(nèi)存溢出錯(cuò)誤(對(duì)于Python 解釋器不是致命的)
NameError 未聲明/初始化對(duì)象 (沒(méi)有屬性)
NotImplementedError 尚未實(shí)現(xiàn)的方法
OSError 操作系統(tǒng)錯(cuò)誤
OverflowError 數(shù)值運(yùn)算超出最大限制
OverflowWarning 舊的關(guān)于自動(dòng)提升為長(zhǎng)整型(long)的警告
PendingDeprecationWarning 關(guān)于特性將會(huì)被廢棄的警告
ReferenceError 弱引用(Weak reference)試圖訪(fǎng)問(wèn)已經(jīng)垃圾回收了的對(duì)象
RuntimeError 一般的運(yùn)行時(shí)錯(cuò)誤
RuntimeWarning 可疑的運(yùn)行時(shí)行為(runtime behavior)的警告
StandardError 所有的內(nèi)建標(biāo)準(zhǔn)異常的基類(lèi)
StopIteration 迭代器沒(méi)有更多的值
SyntaxError Python 語(yǔ)法錯(cuò)誤
SyntaxWarning 可疑的語(yǔ)法的警告
SystemError 一般的解釋器系統(tǒng)錯(cuò)誤
SystemExit 解釋器請(qǐng)求退出
TabError Tab 和空格混用
TypeError 對(duì)類(lèi)型無(wú)效的操作
UnboundLocalError 訪(fǎng)問(wèn)未初始化的本地變量
UnicodeDecodeError Unicode 解碼時(shí)的錯(cuò)誤
UnicodeEncodeError Unicode 編碼時(shí)錯(cuò)誤
UnicodeError Unicode 相關(guān)的錯(cuò)誤
UnicodeTranslateError Unicode 轉(zhuǎn)換時(shí)錯(cuò)誤
UserWarning 用戶(hù)代碼生成的警告
ValueError 傳入無(wú)效的參數(shù)
Warning 警告的基類(lèi)
WindowsError 系統(tǒng)調(diào)用失敗
ZeroDivisionError 除(或取模)零 (所有數(shù)據(jù)類(lèi)型)

7.Python動(dòng)態(tài)添加屬性和方法

動(dòng)態(tài)語(yǔ)言:運(yùn)行時(shí)可以改變其結(jié)構(gòu)的語(yǔ)言佑女,例如新的函數(shù)、對(duì)象、甚至代碼可以被引進(jìn)团驱,已有的函數(shù)可以被刪除或事其他結(jié)構(gòu)上的變化摸吠。如 php、JavaScript嚎花、Python都是動(dòng)態(tài)語(yǔ)言寸痢,C、C#紊选、java是靜態(tài)語(yǔ)言
所以python可以在程序運(yùn)行過(guò)程中添加屬性和方法

  • 動(dòng)態(tài)添加類(lèi)屬性和實(shí)例屬性
class Animal(object):
    def __init__(self,name,age):
        self.name=name
        self.age=age
    pass
#定義了兩個(gè)初始屬性name和age啼止,但沒(méi)有顏色,想去添加顏色又不能修改類(lèi)
cat=Animal('小白',5)
cat.color='白色'  #動(dòng)態(tài)綁定color屬性(只針對(duì)實(shí)例對(duì)象兵罢,類(lèi)本身不改變)
print(cat.color)
#白色

Animal.size='mini' #動(dòng)態(tài)添加類(lèi)屬性
print(cat.size) 
#mini
  • 動(dòng)態(tài)添加實(shí)例方法(需要用到types)
#案例1
class Animal(object):
    def __init__(self,name,age):
        self.name=name
        self.age=age
    pass
cat=Animal('kitty',3)
import types #添加方法的庫(kù)
def run(self): #動(dòng)態(tài)添加實(shí)例方法
    print('飛快跑')
cat.run=types.MethodType(run,cat) #動(dòng)態(tài)方法的綁定方式 run是要綁定的方法献烦,cat是要綁定的實(shí)例
cat.run()
#飛快跑

#案例2
import types
def dynamicMethod(self):
    print('{}的體重是{}kg,在{}讀大學(xué)'.format(self.name,self.weight,Student.school))
    pass

class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    pass
    def __str__(self):
        return '{}今年{}歲了'.format(self.name,self.age)
    pass
zyh=Student('小華',20)
print(zyh)
#小華今年20歲了
zyh.weight=50 #動(dòng)態(tài)添加實(shí)例屬性
Student.school='北航' #動(dòng)態(tài)添加類(lèi)屬性
zyh.printInfo=types.MethodType(dynamicMethod,zyh) #動(dòng)態(tài)的綁定方式
zyh.printInfo()
#小華的體重是50kg卖词,在北航讀大學(xué)
  • 動(dòng)態(tài)添加類(lèi)方法和靜態(tài)方法
    (綁定到對(duì)象就僅限那個(gè)對(duì)象使用巩那,綁定到類(lèi)里面就以后從這個(gè)類(lèi)實(shí)例化出的對(duì)象都可以使用)
    使用方法:類(lèi)名.方法名=xxxx
class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    pass
    def __str__(self):
        return '{}今年{}歲了'.format(self.name,self.age)
    pass
@classmethod
def classTest(cls):
    print('這是一個(gè)類(lèi)方法')
    pass
Student.TestMethod=classTest
Student.TestMethod()
#這是一個(gè)類(lèi)方法
xx=Student('maomao',20)
xx.TestMethod()
#這是一個(gè)類(lèi)方法
@staticmethod
def staticTest():
    print('這是一個(gè)靜態(tài)方法')
    pass
Student.StaticTest=staticTest
Student.StaticTest()
#這是一個(gè)靜態(tài)方法
hh=Student('huihui',20)
hh.StaticTest()
#這是一個(gè)靜態(tài)方法

8. _ slots _ 屬性

python是動(dòng)態(tài)語(yǔ)言,在運(yùn)行的時(shí)候可以動(dòng)態(tài)添加屬性此蜈。如果要限制在運(yùn)行的時(shí)候給類(lèi)添加屬性即横,python允許在定義class的時(shí)候,定義一個(gè)特殊的 _ slots _ 變量舶替,來(lái)限制該class實(shí)例能添加的屬性令境。
只有在 _ slots _ 變量中的屬性才可以被添加,沒(méi)有在 _ slots _ 變量中的屬性會(huì)添加失敗顾瞪√蚴可以防止其他人在調(diào)用類(lèi)的時(shí)候胡亂添加屬性或方法。 _ slots _ 屬性子類(lèi)不會(huì)繼承陈醒,只在當(dāng)前類(lèi)中有效惕橙。

作用:

  1. 限制要添加的實(shí)例屬性
  2. 節(jié)約內(nèi)存空間
class Animal(object):
   __slots__ = ('name','age') #元組類(lèi)型
   pass
dog=Animal()
dog.name='旺財(cái)'
print(dog.name)
#旺財(cái)
# dog.color='白色'
# print(dog.color)
# #AttributeError: 'Animal' object has no attribute 'color'
print(dog.__dict__) #所有可用的屬性都在這里儲(chǔ)存,非常占用內(nèi)存钉跷。
#可以看到弥鹦,在定義了slots變量之后,student類(lèi)的實(shí)例已經(jīng)不能隨意創(chuàng)建不在_slots_定義的屬性了
#同時(shí)爷辙,實(shí)例當(dāng)中也不再有__dict__結(jié)構(gòu)

在繼承關(guān)系當(dāng)中使用slots:子類(lèi)未聲明 _ slots _ 時(shí)彬坏,不會(huì)繼承父類(lèi)的 _ slots _ ,此時(shí)子類(lèi)是可以隨意進(jìn)行屬性賦值的

class Student(object):
    __slots__=('name','age')
    pass
class subStudent(Student):
    pass
ln=subStudent()
ln.gender='男'
ln.pro='計(jì)算機(jī)信息管理'
print(ln.gender,ln.pro)
#男 計(jì)算機(jī)信息管理

如果子類(lèi)聲明了 _ slots _ 時(shí) 膝晾,也會(huì)繼承父類(lèi)的 _ slots _ 栓始,這時(shí)子類(lèi) _ slots _ 的范圍為自身+父類(lèi)的 _ slots _ 。

class Student(object):
    __slots__=('name','age')
    pass
class subStudent(Student):
    __slots__ = ('gender')
    pass
ln=subStudent()
ln.name='lili'
print(ln.name)
#lili
ln.pro='計(jì)算機(jī)信息管理'
#AttributeError: 'subStudent' object has no attribute 'pro'
print(ln.pro)

總結(jié):

  • 私有化屬性:兩個(gè)下劃線(xiàn)開(kāi)頭血当,聲明該屬性為私有幻赚,不能在類(lèi)的外部被使用或訪(fǎng)問(wèn)
  • 私有化方法:即在方法名前加兩個(gè)下劃線(xiàn)
  • Property屬性:
    類(lèi)屬性禀忆,即在類(lèi)中定義為property對(duì)象的類(lèi)屬性
    裝飾器,即在方法上使用裝飾器
  • _ new _ 方法:: _ new _方法的作用是創(chuàng)建 并返回一個(gè)實(shí)例對(duì)象
  • 單例模式:不管創(chuàng)建多少次對(duì)象落恼,類(lèi)返回的對(duì)象都是最初創(chuàng)建的箩退,不會(huì)再新建其他對(duì)象
  • 錯(cuò)誤與異常處理:
    try:可能出現(xiàn)錯(cuò)誤的代碼塊
    except:出錯(cuò)之后執(zhí)行的代碼塊
    else:沒(méi)有出錯(cuò)的代碼塊
    finally:不管有沒(méi)有出錯(cuò)都執(zhí)行的代碼塊
  • python動(dòng)態(tài)添加屬性和方法:在程序運(yùn)行過(guò)程中添加屬性和方法
  • _ slots _ 方法: 在定義class的時(shí)候,定義一個(gè)特殊的 _ slots _ 變量佳谦,來(lái)限制該class實(shí)例能添加的屬性

課后作業(yè)·問(wèn)答題

  1. Python中的new方法作用是什么戴涝?
  2. 什么是單例模式?單例模式適用于什么場(chǎng)景吠昭?
  3. 私有化方式與私有化屬性在子類(lèi)中能否繼承喊括?
  4. 在Python中什么是異常?
  5. Python中是如何處理異常的矢棚?
  6. Python中異常處理語(yǔ)句的一般格式郑什,可以使用偽代碼的形式描述。
  7. _ slots _ 屬性的作用
  8. 私有化屬性的作用蒲肋?
  9. 在類(lèi)外面是否能修改私有屬性
  10. 如果一個(gè)類(lèi)中蘑拯,只有指定的屬性或者方法能被外部修改,那么該如何限制外部修改

課后作業(yè)·實(shí)操題

  1. 編寫(xiě)一段代碼已完成下面的要求:
    定義一個(gè)Person類(lèi)兜粘,類(lèi)中要有初始化方法申窘,方法中要有人的姓名和年齡兩個(gè)私有屬性
    提供獲取用戶(hù)信息的函數(shù)
    提供獲取私有屬性的方法
    提供可以設(shè)置私有屬性的方法
    設(shè)置年齡的范圍在0-120的方法,如果不在這個(gè)范圍內(nèi)孔轴,不能設(shè)置成功
  2. 請(qǐng)寫(xiě)一個(gè)單例模式
  3. 創(chuàng)建一個(gè)類(lèi)剃法,并定義兩個(gè)私有化屬性,提供一個(gè)獲取屬性的方法和設(shè)置屬性的方法路鹰。利用property屬性給調(diào)用者提供屬性方法的調(diào)用獲取和設(shè)置私有屬性方法的方式
  4. 創(chuàng)建一個(gè)Animal類(lèi)贷洲,實(shí)例化一個(gè)cat對(duì)象,請(qǐng)給cat對(duì)象動(dòng)態(tài)綁定一個(gè)run方法晋柱,給類(lèi)綁定一個(gè)類(lèi)屬性color优构,給類(lèi)綁定一個(gè)類(lèi)方法打印字符串“ok”。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載雁竞,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者钦椭。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市碑诉,隨后出現(xiàn)的幾起案子彪腔,更是在濱河造成了極大的恐慌,老刑警劉巖进栽,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漫仆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡泪幌,警方通過(guò)查閱死者的電腦和手機(jī)盲厌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)祸泪,“玉大人吗浩,你說(shuō)我怎么就攤上這事∶话” “怎么了懂扼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)右蒲。 經(jīng)常有香客問(wèn)我阀湿,道長(zhǎng),這世上最難降的妖魔是什么瑰妄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任陷嘴,我火速辦了婚禮,結(jié)果婚禮上间坐,老公的妹妹穿的比我還像新娘灾挨。我一直安慰自己,他們只是感情好竹宋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布劳澄。 她就那樣靜靜地躺著,像睡著了一般蜈七。 火紅的嫁衣襯著肌膚如雪秒拔。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,578評(píng)論 1 305
  • 那天飒硅,我揣著相機(jī)與錄音砂缩,去河邊找鬼。 笑死狡相,一個(gè)胖子當(dāng)著我的面吹牛梯轻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播尽棕,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼喳挑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了滔悉?” 一聲冷哼從身側(cè)響起伊诵,我...
    開(kāi)封第一講書(shū)人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎回官,沒(méi)想到半個(gè)月后曹宴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡歉提,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年笛坦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了区转。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡版扩,死狀恐怖废离,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情礁芦,我是刑警寧澤蜻韭,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站柿扣,受9級(jí)特大地震影響肖方,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜未状,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一俯画、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧娩践,春花似錦活翩、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吨岭,卻和暖如春拉宗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辣辫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工旦事, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人急灭。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓姐浮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親葬馋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卖鲤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

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