寫給編程高手的Python教程(11) 深入類和對象

學(xué)習(xí)使我快樂

鴨子類型和多態(tài)

當(dāng)看到一只鳥走起來像鴨子、游泳起來像鴨子捆探、叫起來也像鴨子然爆,那么這只鳥就可以被稱為鴨子。

例如下面三個類(Cat黍图、Dog曾雕、Duck)的定義中都定義了say方法

class Cat:
def say(self):
print("I am a cat!")

class Dog:
def say(self):
print("I am a dog! ")

class Duck:
def say(self):
print("I am a duck! ")

我們就可以如下面的方法助被,使用這三個類的定義翻默。

animals = [Cat, Dog, Duck]
for Animal in animals:
Animal().say();
復(fù)制代碼
要在Java、C++那些靜態(tài)語言中恰起,要實現(xiàn)上述效果,通常要使用如下的多態(tài)機制趾牧。

class Animal:
def say(self):
print("I am a animal检盼!")

class Cat(Animal):
def say(self):
print("I am a cat!")

a_animal = Cat()
a_animal.say() # 多態(tài)

擴展:列表的extend方法傳遞可迭代的對象即可翘单,它會調(diào)用getitem方法

抽象基類 (abc模塊)

首先看看如下定義:

class Company:
def init(self, employee_list):
self.employee = employee_list
def len(self):
return len(self.employee)

com = Company(["bobby1", "bobby2"])

抽象基類通常有以下幾個優(yōu)點:

判斷類型
我們要判定某個類型是否是“某個鴨子”吨枉,通常有如下兩種方法。

print(hasattr(com, "len"))
print(isinstance(com, Company)) # 這種方式更好

擴展:abc模塊collections.abc哄芜,和全局abc

強制某個子類必須實現(xiàn)某些方法
例如要實現(xiàn)了一個web框架貌亭, 集成Cache(redis、cache认臊、圃庭、),需要設(shè)計一個抽象基類失晴, 指定子類必須實現(xiàn)某些方法

from abc import abstractmethod
class Cache:
@abstractmethod
def get(self, key):
pass
@abstractmethod
def set(self, key, value):
pass

class RedisCache(Cache):
def get(self, key):
pass
def set(self, key, value):
pass

redis = RedisCache()
redis.set("key", "value")

擴展:isinstance和type的區(qū)別 首先看看如下定義:

class A:
pass
class B(A): #A剧腻、B可以看成是模板對象,全局只有一個
pass
b = B()

print(isinstance(b, A)) #True

python中的is是判斷兩個對象的地址是否一樣涂屁,==是判斷兩個對象的內(nèi)容是否一樣书在。

print(type(b) is B) #判斷地址是否相同 True
print(type(b) == B) #判斷值是否相同 True
print(type(b) is A) #False

類變量和實例變量

class A:
aa = 1
def init(self, x, y):
self.x = x
self.y = y

a = A(2, 3)
A.aa = 11
a.aa = 100 # 添加新的屬性到a對象上
print(a.x, a.y, a.aa) # 100
print(A.aa) # 11

print(A.x) #拋異常

b = A(4, 6)
print(b.aa)

類和實例屬性的查找順序—mro查找

多繼承子類屬性的查找問題,如下所述拆又,采用廣度和深度搜索都是有問題的儒旬。 父類 子類 D---->B---->A E---->C---->A

DFS: A->B->D->C->E BFS: A->B->C->D->E, 如果D和C有重名方法栏账,C會覆蓋D

菱形繼承 D---->B---->A D---->C---->A

DFS: A->B->D->C, C的方法無法覆蓋D的方法 BFS: A-->B->C->D

python采用一種C3的算法查找屬性和函數(shù)。

class D:
  pass
class C(D):
  pass
class B(D):
  pass
class A(B, C):
  pass

print(A.mro) # 獲取查詢順序

類方法栈源、靜態(tài)方法和實例方法

class Date:
#構(gòu)造函數(shù)
def init(self, year, month, day):
self.year = year
self.month = month
self.day = day

def tomorrow(self):  #實例方法
    self.day += 1

@staticmethod  # 不需要cls類型的信息
def vaild_str(date_str):
    year, month, day = tuple(date_str.split("-"))
    if int(year) > 0 and int(month) > 0 and int(month) <= 12 and int(day) > 0 and int(day) <= 31:
        return True
    else:
        return False

@staticmethod
def parse_from_string(date_str): #靜態(tài)方法
    year, month, day = tuple(date_str.split("-"))
    return Date(year, month, day)

@classmethod
def parse_from(cls, date_str):  #類方法
    year, month, day = tuple(date_str.split("-"))
    return cls(year, month, day)  #cls不用硬編碼了

def __str__(self):
    return "{year}/{month}/{day}".format(year=self.year, month=self.month, day=self.day)

擴展:元組是可以拆包的

date_str = "2018-12-31"
year, month, day = tuple(date_str.split("-"))

數(shù)據(jù)封裝和私有屬性

class User: def init(self, birthday): self.__birthday = birthday

def age(self):
return 2020 - self.__birthday.year

user = User(Date(1990, 2, 1))

print(user.__birthday) #報錯挡爵,到達私有目的, 子類也沒辦法獲取
print(user._User__birthday) #變形規(guī)則 print(user.age())

class Student(User): def init(self, birthday): self.__birthday = birthday

stu = Student(Date(1995, 4, 1))

print(stu._Student__birthday)

python對象的自省機制

自省是通過一定的機制查詢到對象的內(nèi)部結(jié)構(gòu)
class Person: """ 人 """ name = "person"

class Student(Person): def init(self, school): self.school = school

stu = Student("慕課網(wǎng)") print(stu.dict) print(stu.name) # name屬于Person類 print(Person.dict)

stu.dict["addr"] = "北京市" print(stu.addr) print(dir(stu)) # 列出對象所有屬性

4-10 super真的是調(diào)用父類嗎凉翻?
class A: def init(self): print("A")

class B(A): def init(self): print("B") super().init()

class C(A): def init(self): print("C") super().init()

class D(B, C): def init(self): print("D") super().init() b = B() print("-------------------") d = D() #按MRO算法 super調(diào)用順序 from threading import Thread

class MyThread(Thread): def init(self, name, user): self.user = user super().init(name=name) # MRO算法

mixin繼承案例
python中的with語句
try except finally
try: print("code started") raise KeyError # raise IndexError except KeyError as e: print("key error") else: print("other error") finally: print("finally...")

上下文管理器(協(xié)議)

class Sample: def enter(self): print("enter") return self

def exit(self, exc_type, exc_val, exc_tb):
print("exit")

def do_something(self):
print("doing something.....")

with Sample() as sample: sample.do_something()

from contextlib import contextmanager

@contextmanager def openFile(file): print("file open....") yield {} print("file close....")

print("-------------") with openFile("hao.txt"): print("file processing...")

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末了讨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子制轰,更是在濱河造成了極大的恐慌前计,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垃杖,死亡現(xiàn)場離奇詭異男杈,居然都是意外死亡,警方通過查閱死者的電腦和手機调俘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門伶棒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人彩库,你說我怎么就攤上這事肤无。” “怎么了骇钦?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵宛渐,是天一觀的道長。 經(jīng)常有香客問我眯搭,道長窥翩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任鳞仙,我火速辦了婚禮寇蚊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘棍好。我一直安慰自己仗岸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般斯碌。 火紅的嫁衣襯著肌膚如雪坤邪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音,去河邊找鬼贝润。 笑死积糯,一個胖子當(dāng)著我的面吹牛掂墓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播看成,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼君编,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了川慌?” 一聲冷哼從身側(cè)響起吃嘿,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎梦重,沒想到半個月后兑燥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡琴拧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年降瞳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚓胸。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡挣饥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沛膳,到底是詐尸還是另有隱情扔枫,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布茧吊,位于F島的核電站,受9級特大地震影響八毯,放射性物質(zhì)發(fā)生泄漏瞄桨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一芯侥、第九天 我趴在偏房一處隱蔽的房頂上張望泊交。 院中可真熱鬧,春花似錦柱查、人聲如沸廓俭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淋硝。三九已至雹熬,卻和暖如春宽菜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背竿报。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工铅乡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人阵幸。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓芽世,卻偏偏與公主長得像挚赊,于是被迫代替她去往敵國和親捂襟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344