python编程高手教程_写给编程高手的Python教程(11) 深入类和对象
學習使我快樂
鴨子類型和多態
當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子。
例如下面三個類(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();
復制代碼
要在Java、C++那些靜態語言中,要實現上述效果,通常要使用如下的多態機制。
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() # 多態
擴展:列表的extend方法傳遞可迭代的對象即可,它會調用getitem方法
抽象基類 (abc模塊)
首先看看如下定義:
class Company:
def init(self, employee_list):
self.employee = employee_list
def len(self):
return len(self.employee)
com = Company(["bobby1", "bobby2"])
抽象基類通常有以下幾個優點:
判斷類型
我們要判定某個類型是否是“某個鴨子”,通常有如下兩種方法。
print(hasattr(com, "len"))
print(isinstance(com, Company)) # 這種方式更好
擴展:abc模塊collections.abc,和全局abc
強制某個子類必須實現某些方法
例如要實現了一個web框架, 集成Cache(redis、cache、、),需要設計一個抽象基類, 指定子類必須實現某些方法
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的區別 首先看看如下定義:
class A:
pass
class B(A): #A、B可以看成是模板對象,全局只有一個
pass
b = B()
print(isinstance(b, A)) #True
python中的is是判斷兩個對象的地址是否一樣,==是判斷兩個對象的內容是否一樣。
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的算法查找屬性和函數。
class D:
pass
class C(D):
pass
class B(D):
pass
class A(B, C):
pass
print(A.mro) # 獲取查詢順序
類方法、靜態方法和實例方法
class Date:
#構造函數
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): #靜態方法
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("-"))
數據封裝和私有屬性
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) #變形規則 print(user.age())
class Student(User): def init(self, birthday): self.__birthday = birthday
stu = Student(Date(1995, 4, 1))
print(stu._Student__birthday)
python對象的自省機制
自省是通過一定的機制查詢到對象的內部結構
class Person: """ 人 """ name = "person"
class Student(Person): def init(self, school): self.school = school
stu = Student("慕課網") print(stu.dict) print(stu.name) # name屬于Person類 print(Person.dict)
stu.dict["addr"] = "北京市" print(stu.addr) print(dir(stu)) # 列出對象所有屬性
4-10 super真的是調用父類嗎?
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調用順序 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...")
上下文管理器(協議)
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...")
總結
以上是生活随笔為你收集整理的python编程高手教程_写给编程高手的Python教程(11) 深入类和对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java contains_Java基础
- 下一篇: docker删除镜像命令_第三章 Doc