天天看點

python面向對象的特點_Python面向對象基本特征

面向對象基本特征

封裝

封裝是指對外界隐藏資訊,不能随意通路、修改對象的資料和方法

封裝是通過限制類的屬性和方法的通路方式來實作的封裝效果

封裝的三個層次:

類的封裝:外部可以任意通路、修改類中的屬性和方法

私有屬性:外部不可以通路、修改勒種的屬性和方法

公有方法+私有屬性:外部有條件限制的通路、修改屬性,調用方法

封裝表現1:

類的定義:将某些特定屬性和方法進行“隔離”

每個學生有自己的年齡,外部可以任意讀取或者修改

class Student:

def __init__(self,name,age):

self.name = name

self.age = age

s1 = Student("李白",18)

s2 = Student("杜甫",20)

s2.age = 200

print(s1.name)

print(s2.age)

封裝表現2:

屬性私有:隻能在類的内部使用,外部不能使用

不讓外部讀取、修改學生的年齡

class Student:

def __init__(self,name,age):

self.name = name

self.__age = age#使用兩個下劃線開頭的屬性,定義為私有屬性

print(self.__age)

__secret = True

s1 = Student("李白",18)

# print(s1.__age)#外界無法直接通過屬性名稱來通路

#雖然文法可以在外部通過_Student__age通路到私有屬性,但是不推薦使用

print(s1._Student__age)

#__dict__檢視目前對象或者類有哪些屬性

print(s1.__dict__)

print(Student.__dict__)

封裝表現3:

私有屬性+ 公有方法:有限制條件的開放給外部

可以讀取年齡,但不能随意修改年齡

設定年齡必須在(1,125)之間

class Student:

def __init__(self,name,age):

self.name = name

self.__age = age

def getAge(self):

return self.__age

def setAge(self,age):

if 0 < age < 125:

self.__age = age

else:

print("年齡不符合人類")

s1 = Student("李白",18)

print(s1.getAge())

s1.setAge(200)

print(s1.getAge())

私有方法

可以在類的内部使用,有條件的開放給外部

class Person:

def __tellSercert__(self):

print("夏天夏天悄悄過去,留下小秘密~~~~")

def talk(self,object):

if object == "好基友":

self.__tellSercert__()

else:

print("我是一個木得感情木得秘密的人")

ming = Person()

ming.talk("好基友")

ming.talk("隔壁小黑")

封裝的簡化寫法

裝飾器

property裝飾器:把一個方法僞裝成一個屬性,在調用這個方法的時候不需要加()就可以直接得到傳回值

class Dog:

@property#裝飾器

def bark(self):

print("旺旺旺~~~")

return 89757

d = Dog()

num = d.bark #注意這裡沒有括号呦

print(num)

總結

使用@property裝飾器時,方法名不必與屬性名相同

可以更好的防止外部通過猜測私有屬性名稱來通路

凡是指派語句就會觸發set方法,擷取屬性值會觸發get方法

繼承

面臨的問題:

相似類型的定義會産生大量重複的代碼

類的定義沒有很好的擴充性‘

解決的方法:

定義類和類之間的關系,子類擁有父類的全部屬性和方法,并可以為之擴充

示例

class Pet:

def __init__(self,name,age):

self.name = name

self.age = age

print(f"一隻名字叫{self.name}的寵物出生了")

def eat(self):

print(f"{self.name}在吃東西~~~")

def run(self):

print(f"{self.name}在溜達~~~")

class Dog(Pet):

pass

class Cat(Pet):

pass

d = Dog("咯咯",3)

d.run()

c = Cat("布丁",1)

c.eat()

1.繼承的概念:

Dog和Cat繼承了Pet類

Dog和Cat稱為Pet的子類、派生類

Pet稱為Dog和Cat的父類、超類、基類

子類預設擁有父類公有的屬性和方法的定義

2.子類調用方法的順序

調用方法時,子類中有的,調用子類中的

子類中沒有的,調用父類的

一旦在子類中找到,就不在去父類中查找了

子類不能繼承父類的私有屬性或者方法

class Father:

__secret = "小秘密"

story = "從前有座山,山上有座廟"

def tellStory(self):

print(self.story)

def __tellSecret(self):

print(self.__secret)

class Son(Father):

def tell(self):

# self.tellStory()

self.__tellSecret()

s = Son()

s.tell()

3.重寫/覆寫

子類和父類擁有相同名稱的方法

可以了解為子類對于父類行為的擴充和補充

class Pet:

master = True

def __init__(self,name,age):

self.name = name

self.age = age

print(f"一隻名字叫{self.name}的寵物出生了")

def eat(self):

print(f"{self.name}在吃東西~~~")

def run(self):

print(f"{self.name}在溜達~~~")

class Dog(Pet):

#重寫父類方法

def eat(self):

print(f"{self.name}在啃骨頭")

#擴充,定義子類特有功能

def lookAfter(self):

print(f"{self.name}在看門,汪汪汪!")

d = Dog("旺财",2)

d.eat()

d.lookAfter()

4.子類可以在類定義時,可以使用super()調用父類的方法

應用1:和重寫不同,重寫是對父類方法的完全覆寫,這是對父類方法的補充

class Pet:

def __init__(self,name,age):

self.name = name

self.age = age

print(f"一隻名字叫{self.name}的寵物出生了")

def eat(self):

print(f"{self.name}在吃東西~~~")

def run(self):

print(f"{self.name}在溜達~~~")

class Cat(Pet):

def eat(self):

print(f"{self.name}伸了個懶腰")

super().eat()

print(f"{self.name}吃完東西後,舔了舔爪子")

c = Cat("布丁",2)

c.eat()

應用2:對象初始化時,簡化重複屬性的指派

class Cat(Pet):

def __init__(self,name,age,sex):

# self.name = name

# print(f"一隻名叫{self.name}的寵物出生了")

super().__init__(name)#代替了上兩句代碼,簡化了重複屬性的指派

self.age = age

self.sex = sex

5.多繼承

子類可以有多個父類

例如:狗是脊椎動物,哺乳動物,寵物。。。

class Father:

caihua = "有才"

class Mother:

yanzhi = "有貌"

class Child(Father,Mother):

pass

c = Child()

print(c.caihua,c.yanzhi)

print(Child.__bases__)#可以通過類名.__bases__檢視其父類

6.通路子類的屬性或者方法時,解析的路徑(順序)

class Father:

def getMoney(self):

print("爸爸給了零花錢")

class Mother:

def getMoney(self):

print("媽媽給了零花錢")

class Child(Father,Mother):

def getMoney(self):

super().getMoney()

#按照繼承的順序查找父類中的方法,是以先找Father類

print("孩子獲得了零花錢")

c = Child()

c.getMoney()

從第一個父類開始向上查找,直到查找結束都沒有,再對第二個父類進行查找

深度優先:Child -> Father -> GrandFather -> Mother

class GrandFather:

pass

# def getMoney(self):

# print("爺爺給了零花錢")

class Father(GrandFather):

pass

# def getMoney(self):

# print("爸爸給了零花錢")

class Mother:

def getMoney(self):

print("媽媽給了零花錢")

class Child(Father,Mother):

def getMoney(self):

super().getMoney()

#按照繼承的順序查找父類中的方法,是以先找Father類

print("孩子獲得了零花錢")

c = Child()

c.getMoney()

print(Child.mro())#可以通過類名.mro()的方式來檢視類的解析順序

object是所有類的父類

“萬事萬物”皆為對象,因為所有的類都預設繼承object

7.菱形繼承

python面向對象的特點_Python面向對象基本特征

廣度優先:Child -> Father -> Mother -> Human

python面向對象的特點_Python面向對象基本特征

多态

想要解決的問題

讓程式能夠有更強的靈活性

讓程式能夠有更好的适應性

概念:一個類的多種形态

情況1:通過繼承和重寫來實作

class Animal:

def eating(self):

print("動物在吃東西")

class Pet(Animal):

def eating(self):

print("寵物在吃東西")

class Dog(Pet):

def eating(self):

print("狗在啃骨頭~")

class Cat(Pet):

def eating(self):

print("小貓在吃魚")

class Zoo:

def animalEating(self,animal):

animal.eating()

z = Zoo()

a = Animal()

p = Pet()

d = Dog()

c = Cat()

#Dog和Cat都作為Animal的不同形态

#都可以直接調用animal所具有的屬性和方法

z.animalEating(a)

z.animalEating(p)

z.animalEating(d)

z.animalEating(c)

情況2:Python持有

沒有繼承關系,但是也具備相同的特征、方法,也可以直接使用

class venusFlytrap:#捕蠅草

def eating(self):

print("捕蠅草在吃小蟲子")

v = venusFlytrap()

z.animalEating(v)

捕蠅草不繼承于Animal類,但是具有和它相同的特征,在python隻要具有相同的特征和方法,沒有繼承關系也可以直接使用

type和isinstance

#type判斷類型時,隻看直接類型

print(type(c) is Cat)#True

print(type(c) is Animal)#False

print(type(c) is Pet)#False

#isinstance 判斷對象是否為一個類型的執行個體

#判斷執行個體類型時,涵蓋父類的類型

print(isinstance(c,Cat))#True

print(isinstance(c,Pet))#True

print(isinstance(c,Animal))#True

print(isinstance(venusFlytrap,Animal))#False