python(12)面向對象 封裝、繼承、多態

一、封裝

私有化
封裝:
1、私有化屬性
2、定義公有的set和get方法

__屬性:將屬性私有化,訪問範圍僅僅限於類中

優點:
1、隱藏屬性,不被外界隨意修改
2、也可以修改,通過函數
def setXXX(self, xxx):
    3、篩選賦值的內容
    if xxx是否符合條件:
        賦值
    else:
        不賦值
4、如果想獲取具體的某一個屬性
使用get函數
def getXXX(self):
    return self.__xxx


attribute setName getName setAge getAge

在開發中,看到一些私有化處理:裝飾器
class Student:
    # __age = 18  #類屬性

    def __init__(self, name, age):
        self.name = name
        self.__age = age
        self.__score = 59

    def __str__(self):
        return '姓名{},年齡{},考試分數{}'.format(self.name, self.__age, self.__score)

    #舊版set、get方法
    #定義公有的set和get方法
    #set是爲了賦值
    # def setAge(self, age):
    #     if age > 0 and age < 120:
    #         self.__age = age
    #     else:
    #         print("年齡不在規定範圍內")

    # #get是爲了取值
    # def getAge(self):
    #     return self.__age

    #新版
    #先定義get的xxx,再有xxx.set,因爲set依賴get
    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        if age > 0 and age < 100:
            self.__age = age
        else:
            print("年齡賦值錯誤")

#舊版
s = Student('name1', 18)
print(s)
# s.setAge(20)
# print(s)

print(dir(Student)) #獲取類中所有屬性
print(s.__dir__())  #獲取類中所有屬性,包括私有
print(s._Student__age)  #系統自動將私有屬性改名, _Student__age其實就是__age
print(__name__)

print("*" * 80)


#新版
s1 = Student('name333', 15)
print(s1.name)
#私有化的賦值
# s1.setAge(30)
# print(s1.getAge())

print(s1.age)

 

二、繼承

繼承: is a, has a
例如:
公路(Road) 屬性:公路名稱、公路長度

車(Car) 屬性:車名、時速
方法:
1、求車名在那條公路上以多少的時速行駛了多長get_time(self, road)
2、初始化車屬性信息 __init__方法
3、打印對象顯示車的屬性信息

1、has a  包含, 類中有...
1)、一個類中使用了另外一種自定義的類型
2)、類型:
系統類型:
str int float
list dic tuple set
自定義類型:
自定義的類,都可以將其當成一種類型
s = Student()
s是Student類型的對象
import random
class Road:
    def __init__(self, name, len):
        self.name = name
        self.len = len

class Car:
    def __init__(self, road, brand, speed):
        self.road = road
        self.brand = brand
        self.speed = speed

    def get_time(self):   #road 與 r指向同一個地址空間
        ran_time = random.randint(1, 10)
        msg = '{}品牌的車在{}上,以{}的時速行駛{}時間'.format(self.brand, self.road.name, self.speed, ran_time)
        print(msg)

    def __str__(self):
        return '{}品牌的,速度{}'.format(self.brand, self.speed)

#創建實例化對象
r = Road("青藏公路", 12000)
c = Car(r, "奧迪", 120)  #此處  Car類中使用了另一個自定義類Road 爲 has a

print(c)
c.get_time()

 

2、is a   base class 基類 父類
父類  子類
ValueError Exception BaseException

Student, Employee, Doctor  都屬於人類
相同代碼--->代碼冗餘,可讀性不高

將相同代碼提取--->Person類
Student, Employee, Doctor  繼承 Person
父類
class Person:
    pass

子類
class Student(Person):
    pass

特點:
1、如果類中不定義__init__,默認調用父類 super class的__init__
2、如果類繼承父類,也需要定義自己的__init__,就需要在子類__init__中
調用父類的__init__
3、如何調用父類__init__:
    super().__init__(參數)
    super(類名, self).__init__(參數)
4、如果父類有eat(),子類也定義一個eat()方法,搜索的原則:
先找當前類,沒有再去找父類
override 重寫(覆蓋)
父類提供的方法,不能滿足子類的需求,就需要在子類中定義一個同名的方法,
這種行爲爲:重寫
5、子類的方法中,也可以調用父類的方法
    super().方法名(參數)
#將每個類共同的屬性和方法提取出來
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = 20
        print("------> Person的init")
    
    def run(self):
        print("{}正在跑步".format(self.name))

    def eat(self):
        print("{}正在喫飯".format(self.name))

class Student(Person):
    def __init__(self, name, age, clazz):
        print('--->Student的init')
        #如何調用父類__init__     super() 父類對象
        super().__init__(name, age)
        self.clazz = clazz

    def study(self, course):
        print("{}正在學習{}課程".format(self.name, course))

    #子類中與父類同名的方法,直接調用自己的方法,優先找自己的方法,不去找父類的方法
    def eat(self, food):
        super().eat()  #先調用父類的代碼
        print("{}正在喫飯,喜歡喫{}".format(self.name, food))

class Employee(Person):
    def __init__(self, name, age, salary, manager):
        super().__init__(name, age)
        self.salary = salary
        self.manager = manager

class Doctor(Person):
    def __init__(self, name, age, patient):
        super(Doctor, self).__init__(name, age)
        self.patient = patient

s = Student("stu", 20, "一年級")
s.run()
s.study('python')
s.eat('滿漢全席')
e = Employee('ee', 40, 10000, 'king')
e.run()
list1 = ['aaa', 'bbb', 'ccc']
d = Doctor('d', 40, list1)
d.run()

 

3、多繼承
python允許多繼承
def 子類(父類1, 父類2, ...)

類名.__mro__    輸出搜索順序
import inspect
inspect.getmro(類名)

如果父類中有相同名稱的方法,搜索順序  經典類  新式類

python2.7 -- 從左至右,深度優先  一個父類搜索完再搜索其它的父類

python3 -- 廣度優先   現在執行的環境   子類所有父類,其中一個父類所有父類...
class Base:
    def test(self):
        print("-------Base---------")

class A(Base):
    def test(self):
        print("--->AAAAAAA")

class B(Base):
    def test(self):
        print("--->BBBBBB")

class C(Base):
    def test(self):
        print("------>CCCCCC")

class D(A, B, C):
    pass

c = C()
c.test()  #輸出:------>CCCCCC
d = D()
d.test()
print(D.__mro__)  #查看搜索順序

import inspect
print(inspect.getmro(D))  #查看繼承搜索順序

 

三、多態

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

    def feed_pet(self, pet):  #既可以接收cat,也可以接收dog,還可以接受tiger
        # isinistance(obj, 類)  --->驗證obj是不是類的對象,或者判斷obj是不是該類子類的對象
        if isinstance(pet, Pet):
            print("{}喜歡養寵物:{},暱稱是{}".format(self.name,pet.role, pet.nickname))
        else:
            print("不是寵物")

#寵物
class Pet:
    role = "寵物"
    def __init__(self, nickname, age):
        self.nickname = nickname
        self.age = age

    def show(self):
        print("暱稱是:{}, 年齡:{}".format(self.nickname, self.age))

class Cat(Pet):
    role = "貓"
    def catch_mouse(self):
        print("抓老鼠")

class Dog(Pet):
    role = "狗"
    def watch_house(self):
        print("看門")

class Tiger:
    def eat(self):
        print("喫人")

#創建對象
cat = Cat('小貓', 2)
dog = Dog('小狗', 3)
tiger = Tiger()

p = Person('人')
p.feed_pet(cat)

p.feed_pet(tiger)
Pet
pet 父類   cat dog 子類
pet 大類型 cat dog 小類型

 

四、總結

面向對象的特點:
封裝、繼承、多態
1、封裝:
私有化屬性,定義公有set和get方法
class Student:
    def __init__(self, age):
        self.__age = age

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age)
        self.__age = age

s = Student()
s.age = 10


繼承:
父類中的私有屬性,子類無法繼承
is a:
父類(提取出來的共同的特徵) 子類
class Student(Person):
    pass

has a:
class Student:
    def __init__(self, 參數)
        參數是自定義類型

s = Student()

多繼承:
class C(A, B):
    pass

C.__mro__  查看搜索順序


多態:  
class Person:
    def feed_pet(self, pet)  #只要是pet的子類,都可以
        if isinstance(pet, Pet):
            pass
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章