Python封裝和繼承

一福贞、封裝【private】

1.概念

廣義的封裝:函數(shù)和類的定義本身撩嚼,就是封裝的體現(xiàn)

狹義的封裝:一個類的某些屬性,在使用的過程 中挖帘,不希望被外界直接訪問完丽,而是把這個屬性給作為私有的【只有當前類持有】,然后暴露給外界一個訪問的方法即可【間接訪問屬性】

封裝的本質(zhì):就是屬性私有化的過程

封裝的好處:提高了數(shù)據(jù)的安全性拇舀,提高了數(shù)據(jù)的復(fù)用性

說明:舉例:插排逻族,不需要關(guān)心屬性在類的內(nèi)部做了什么樣的操作,只需要關(guān)心將值傳進去骄崩,或者將結(jié)果獲取出來

2.屬性私有化

如果想讓成員變量不被外界直接訪問聘鳞,則可以在屬性名稱的前面添加兩個下劃線__,成員變量則被稱為私有成員變量

私有屬性的特點:只能在類的內(nèi)部直接被訪問,在外界不能直接訪問

代碼演示:

#1.屬性不私有化的時候
class Person():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def myPrint(self):
        print(self.name,self.age)

#通過構(gòu)造函數(shù)給屬性賦值
per = Person("張三",10)
per.myPrint()   #張三 10
#通過對象直接訪問屬性要拂,并且給屬性賦值
per.name = "李四"
per.age = 22
per.myPrint()   #李四 22

#2.屬性私有化
#寫法:在屬性的前面添加兩個下劃線
#用法:只能在類的內(nèi)部被訪問抠璃,外界不能直接訪問
class Person1():
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    def myPrint(self):
        print(self.name,self.__age)

p1 = Person1("abc",10)
p1.myPrint()   #abc 10
p1.name = "hello"
#其實動態(tài)綁定屬性,age和__age其實是兩個不同的變量
p1.age = 222
p1.myPrint()
print(p1.age)

#AttributeError: 'Person1' object has no attribute '__age',私有化了脱惰,在外界不能直接訪問
#print(p1.__age)

3.get函數(shù)和set函數(shù)

get函數(shù)和set函數(shù)并不是系統(tǒng)的函數(shù)搏嗡,而是自定義的,為了和封裝的概念相吻合拉一,起名為getXxx和setXxx

get函數(shù):獲取值

set函數(shù):賦值【傳值】

代碼演示:

#3.get函數(shù)和set函數(shù)
class Person2():
    def __init__(self,name,age):
        self.name = name
        self.__age = age
        #特殊情況一
        self.__weight__ = 20.0
        #特殊情況二
        self._height = 155.0

    def myPrint(self):
        print(self.name,self.__age)

    # 書寫私有屬性age的get函數(shù)和set函數(shù)【通過自定義的函數(shù)進行私有屬性的賦值和獲取值采盒,暴露給外界】
    """
    get函數(shù)和set函數(shù)并不是系統(tǒng)的函數(shù)旧乞,而是自定義的,為了和封裝的概念相吻合纽甘,起名為getXxx和setXxx
    get函數(shù):獲取值
    set函數(shù):賦值【傳值】
    """
    #set函數(shù):給成員變量賦值
    #命名方式:setXxx
    #特點:需要設(shè)置參數(shù)良蛮,參數(shù)和私有成員變量有關(guān)
    def setAge(self,age):
        #數(shù)據(jù)的過濾
        if age < 0:
            age = 0
        self.__age = age
    #get函數(shù):獲取成員變量的值
    #命名方式:getXxx
    #特點:需要設(shè)置返回值抽碌,將成員變量的值返回
    def getAge(self):
        return self.__age

    #注意:有幾個私有屬性悍赢,則書寫幾對get函數(shù)和set函數(shù)

p2 = Person2("abc",10)
p2.myPrint()   #abc 10
#print(p2.__age)
#間接的訪問了私有的成員變量
print(p2.getAge())
p2.setAge(22)
print(p2.getAge())

p2.setAge(-20)
print(p2.getAge())

#總結(jié):通過將屬性私有化之后,然后提供get函數(shù)和set函數(shù)货徙,外部代碼就不能隨意更改成員變量的值左权,這樣在一定程度上保證了數(shù)據(jù)的安全性

#4.工作原理【了解】
#當編譯器加載了程序之后,不能直接訪問p2.__age,Python解釋器把__age解釋成_Person2__age
#p2.__age = 100
p2._Person2__age = 100
print(p2.getAge())

#5.特殊情況:盡量不要直接訪問
#a.在一個變量的前后各加兩個下劃線痴颊,在Python中被認為特殊成員變量赏迟,將不再屬于私有變量
#print(p2.__weight__)
#b.特殊變量
#print(p2._height)

#面試題:下面變量的含義
"""
xxx:普通的變量
_xxx:受保護的變量,不建議使用這種形式
__xxx:表示私有的蠢棱,外界無法直接訪問锌杀,只能通過暴露給外界的函數(shù)訪問
__xxxx__:一般是系統(tǒng)的內(nèi)置變量,比如:__name__,__solts__,自定義標識符的時候盡量不要使用這種形式
"""

4.@property裝飾器

裝飾器的作用:可以給函數(shù)動態(tài)添加功能泻仙,對于類的成員方法糕再,裝飾器一樣起作用

Python內(nèi)置的@property裝飾器的作用:將一個函數(shù)變成屬性使用

@property裝飾器:簡化get函數(shù)和set函數(shù)

使用:@property裝飾器作用相當于get函數(shù),同時玉转,會生成一個新的裝飾器@屬性名.settter,相當于set函數(shù)的作用

作用:使用在類中的成員函數(shù)中突想,可以簡化代碼,同時可以保證對參數(shù)做校驗

代碼演示:

class Person1():
    def __init__(self,name,age):
        self.__name = name
        self.__age = age

    def myPrint(self):
        print(self.__name,self.__age)

    """
   def setAge(self,age):
        #數(shù)據(jù)的過濾
        if age < 0:
            age = 0
        self.__age = age

    def getAge(self):
        return self.__age
    """

    #注意:函數(shù)的命名方式:變量的名稱
    #作用:相當于get函數(shù)究抓,設(shè)置返回值猾担,將成員變量的值返回
    @property
    def age(self):
        return  self.__age

    #注意:函數(shù)的命名方式:需要和@property中函數(shù)的命名保持一致
    #作用:相當于set函數(shù),設(shè)置參數(shù),給成員變量賦值
    @age.setter
    def age(self,age):
        if age < 0:
            age = 0
        self.__age = age

    @property
    def name(self):
        return  self.__name

    @name.setter
    def name(self,name):
        self.__name = name


p1 = Person1("abc",10)
p1.myPrint()   #abc 10
#p1.setAge(20)
#print(p1.getAge())

print(p1.age)  #10
p1.age = 18   #相當于調(diào)用了set函數(shù)刺下,將18傳值绑嘹,實質(zhì)調(diào)用的是@age.setter修飾的函數(shù)
print(p1.age) #相當于調(diào)用了get函數(shù),將成員變量的值獲取出來橘茉,實質(zhì)調(diào)用的是@peoperty修飾的函數(shù)

p1.name = "zhangsan"
print(p1.name)

5.私有方法

如果類中的一個函數(shù)名前面添加__,則認為這個成員函數(shù)時私有化的

特點:也不能在外界直接調(diào)用工腋,只能在類的內(nèi)類調(diào)用

代碼演示:

class Site():
    def __init__(self,name):
        self.name = name

    def who(self):
        print(self.name)
        self.__foo()

    #私有成員方法,只能在當前類的內(nèi)部內(nèi)調(diào)用
    def __foo(self):    #私有函數(shù)
        print("foo")

    def foo(self):    #公開函數(shù)
        print("foo~~~~")

    #注意:以上兩個函數(shù)是兩個不同的函數(shù)捺癞,不存在覆蓋的問題

s = Site("千鋒")
s.who()
#s.__foo()  #AttributeError: 'Site' object has no attribute 'foo'
s.foo()

二夷蚊、繼承【extends】

1.概念

如果兩個或者兩個以上的類具有相同的屬性或者成員方法,我們可以抽取一個類出來髓介,在抽取的類中聲明公共的部分

? 被抽取出來的類:父類惕鼓,基類,超類唐础,根類

? 兩個或者兩個以上的類:子類箱歧,派生類

? 他們之間的關(guān)系:子類 繼承自 父類

注意:

? a.object是所有類的父類矾飞,如果一個類沒有顯式指明它的父類,則默認為object

? b.簡化代碼呀邢,提高代碼的復(fù)用性

2.單繼承

2.1使用

簡單來說洒沦,一個子類只能有一個父類,被稱為單繼承

語法:

父類:

class 父類類名(object):

? 類體【所有子類公共的部分】

子類:

class 子類類名(父類類名):

? 類體【子類特有的屬性和成員方法】

說明:一般情況下价淌,如果一個類沒有顯式的指明父類申眼,則統(tǒng)統(tǒng)書寫為object

代碼演示:

person.py文件【父類】

#1.定義父類
class Person(object):
    #構(gòu)造函數(shù)【成員變量】
    def __init__(self,name,age):
        self.name = name
        self.age = age


    #成員方法
    def show(self):
        print("show")

    def __fun(self):
        print("fun")

worker.py文件【子類1】

from  extends01.person import Person

#2.定義子類
class Worker(Person):
    #構(gòu)造函數(shù)【成員變量】
    def __init__(self,name,age,job):
        """
        self.name = name
        self.age = age
        """
        self.job = job

        #6.在子類的構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù)【從父類中繼承父類中的成員變量】
        #方式一:super(當前子類,self).__init__(屬性列表)
        #super(Worker, self).__init__(name,age)
        #方式二:父類名.__init__(self,屬性列表)
        Person.__init__(self,name,age)
        #方式三:super().__init__(屬性列表)
        #super().__init__(name,age)


    #成員方法
    def work(self):
        print("work")

student.py文件【子類2】

from extends01.person import  Person

class Student(Person):
    # 構(gòu)造函數(shù)【成員變量】
    def __init__(self, name, age, score):

        Person.__init__(self,name,age)
        self.score = score

    # 成員方法
    def study(self):
        print("study")

extendsDemo01.py文件【測試模塊】

#測試模塊
from extends01.person import Person
from extends01.worker import Worker
from extends01.student import Student

#3.創(chuàng)建父類的對象
p = Person("zhangsan",10)
p.show()
#p.__fun()

#4.創(chuàng)建子類的對象
w = Worker("aaa",20,"工人")
w.work()

#5.子類對象訪問父類中的內(nèi)容
#結(jié)論一:子類對象可以調(diào)用父類中的公開的成員方法【因為繼承蝉衣,私有方法除外】
w.show()
#w.__fun()
#結(jié)論二:通過在子類的構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù)括尸,子類對象可以直接訪問父類中的成員變量【私有變量除外】
print(w.name,w.age,w.job)

s = Student("小明",9,90)
s.study()
s.show()
2.2特殊用法

代碼演示:

#6.子類中出現(xiàn)一個和父類同名的成員函數(shù),則優(yōu)先調(diào)用子類中的成員函數(shù)
#子類的成員函數(shù)覆蓋了父類中的同名的成員函數(shù)
s = Student("小明",9,90)
s.study()
s.show()

#7.父類對象能不能訪問子類中特有的成員函數(shù)和成員變量?----->不能
per = Person("gs",10)
#per.work()
#8.slots屬性能否應(yīng)用在子類中
#結(jié)論三:在父類中定義slots屬性限制屬性的定義病毡,子類中是無法使用濒翻,除非在子類中添加自己的限制
#父類
class Student(object):
    __slots__ = ("name","age")

#子類
class SeniorStudent(Student):
    pass


s  = Student()
s.name = "zhangsan"
s.age = 10
#s.score = 90

ss = SeniorStudent()
ss.name = "lisi"
ss.age = 20
ss.score = 60

總結(jié):

繼承的特點:

? a.子類對象可以直接訪問父類中非私有化的屬性

? b.子類對象可以調(diào)用父類中非私有化的成員方法

? c.父類對象不能訪問或者調(diào)用子類 中任意的內(nèi)容

繼承的優(yōu)缺點:

優(yōu)點:

? a.簡化代碼,減少代碼的冗余

? b.提高代碼的復(fù)用性

? c.提高了代碼的可維護性

? d.繼承是多態(tài)的前提

缺點:

? 通常使用耦合性來描述類與類之間的關(guān)系啦膜,耦合性越低有送,則說明代碼的質(zhì)量越高

? 但是,在繼承關(guān)系中僧家,耦合性相對較高【如果修改父類雀摘,則子類也會隨著發(fā)生改變】

3.多繼承

一個子類可以有多個父類

語法:

class 子類類名(父類1,父類2啸臀,父類3.届宠。。乘粒。):

? 類體

代碼演示:

father.py文件【父類1】

class Father(object):
    def __init__(self,money):
        self.money = money

    def play(self):
        print("playing")

    def fun(self):
        print("father中的fun")

mother.py文件【父類2】

class Mother(object):
    def __init__(self,faceValue):
        self.faceValue = faceValue

    def eat(self):
        print("eating")

    def fun(self):
        print("mother中的fun")

child.py文件【子類】

from extends02.father import Father
from extends02.mother import Mother

#定義子類豌注,有多個父類
class Child(Mother,Father):
    def __init__(self,money,faceValue,hobby):
        #調(diào)用父類中的構(gòu)造函數(shù)
        Father.__init__(self,money)
        Mother.__init__(self,faceValue)
        self.hobby = hobby

    def study(self):
        print("study")

extendsDemo03.py文件【測試模塊】

from extends02.father import Father
from extends02.mother import Mother
from extends02.child import Child


f = Father(100000)
m = Mother(3.0)

#創(chuàng)建子類對象
c = Child(1000,3.0,"打游戲")
#子類對象調(diào)用父類中的成員方法
c.play()
c.eat()

#結(jié)論;如果多個父類中有相同的函數(shù),通過子類的對象調(diào)用灯萍,調(diào)用的是哪個父類中的函數(shù)取決于在父類列表中出現(xiàn)的先后順序
c.fun()

4.函數(shù)重寫【override】

在子類中出現(xiàn)和父類同名的函數(shù)轧铁,則認為該函數(shù)是對父類中函數(shù)的重寫

4.1系統(tǒng)函數(shù)重寫
__str__   
__repr__

代碼演示:

class Animal(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

    #重寫__str__函數(shù),重寫之后一般return一個字符串,有關(guān)于成員變量
    def __str__(self):
        return "name=%s age=%d"%(self.name,self.age)

    #重寫__repr__,作用和str是相同的旦棉,優(yōu)先使用str
    def __repr__(self):
        return "name=%s age=%d"%(self.name,self.age)

a = Animal("大黃",10)
print(a)   #<__main__.Animal object at 0x00000226A87AC240>
print(a.__str__())

#當一個類繼承自object的時候齿风,打印對象獲取的是對象的地址,等同于通過子類對象調(diào)用父類中__str__
#當打印對象的時候绑洛,默認調(diào)用了__str__函數(shù)
#重寫__str__的作用:為了調(diào)試程序

"""
總結(jié):【面試題】
a.__str__和__repr__都未被重寫的時候救斑,使用對象調(diào)用的是__str__,此時__str__返回的是對象的地址
b.__str__和__repr__都被重寫之后,使用對象調(diào)用的是__str__真屯,此時__str__返回的是自定義的字符串
c.重寫了__str__脸候,但是沒有重寫__repr__,則使用對象調(diào)用的是__str__,此時__str__返回的是自定義的字符串
d.未重寫__str__运沦,但是重寫了__repr__泵额,則使用對象調(diào)用的是__repr__,此時,__repr__返回的是自定義的字符串
"""

#使用時機:當一個對象的屬性有很多的時候携添,并且都需要打印嫁盲,則可以重寫__str__,可以簡化代碼烈掠,調(diào)試程序
4.2自定義函數(shù)重寫

代碼演示:

#函數(shù)重寫的時機:在繼承關(guān)系中羞秤,如果父類中函數(shù)的功能滿足不了子類的需求,則在子類中需要重寫
#父類
class People(object):
    def __init__(self,name):
        self.name = name

    def fun(self):
        print("fun")

#子類
class Student(People):
    def __init__(self,name,score):
        self.score = score
        super(Student,self).__init__(name)

    #重寫;將函數(shù)的聲明和實現(xiàn)重新寫一遍
    def fun(self):
        #在子類函數(shù)中調(diào)用父類中的函數(shù)【1.想使用父類中的功能向叉,2.需要添加新的功能】
        #根據(jù)具體的需求決定需不需要調(diào)用父類中的函數(shù)
        super(Student,self).fun()
        print("fajfhak")


s = Student("fhafh",10)
s.fun()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锥腻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子母谎,更是在濱河造成了極大的恐慌,老刑警劉巖京革,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奇唤,死亡現(xiàn)場離奇詭異,居然都是意外死亡匹摇,警方通過查閱死者的電腦和手機咬扇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來廊勃,“玉大人绳泉,你說我怎么就攤上這事崭捍。” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵蟀架,是天一觀的道長。 經(jīng)常有香客問我节槐,道長褐奴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任溉卓,我火速辦了婚禮皮迟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘桑寨。我一直安慰自己伏尼,他們只是感情好,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布尉尾。 她就那樣靜靜地躺著爆阶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扰她,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天兽掰,我揣著相機與錄音,去河邊找鬼徒役。 笑死孽尽,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的忧勿。 我是一名探鬼主播杉女,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鸳吸!你這毒婦竟也來了熏挎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤晌砾,失蹤者是張志新(化名)和其女友劉穎坎拐,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體养匈,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡哼勇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了呕乎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片积担。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖猬仁,靈堂內(nèi)的尸體忽然破棺而出帝璧,到底是詐尸還是另有隱情,我是刑警寧澤湿刽,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布的烁,位于F島的核電站,受9級特大地震影響叭爱,放射性物質(zhì)發(fā)生泄漏撮躁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一买雾、第九天 我趴在偏房一處隱蔽的房頂上張望把曼。 院中可真熱鬧,春花似錦漓穿、人聲如沸嗤军。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叙赚。三九已至老客,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間震叮,已是汗流浹背胧砰。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苇瓣,地道東北人尉间。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像击罪,于是被迫代替她去往敵國和親哲嘲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

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