一、封裝
私有化
封裝:
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