自定義元類
抽象基類
自省機制
__ slots __
python一切皆物件 linux一切皆檔案
定義:元類是類的類,是類的模板。元類的例項為類,正如類的例項為物件。
類的本質是物件, 於是可以對類做如下的操作:
你可以將它賦值給乙個變數
你可以拷⻉它
你可以為它增加屬性
你可以將它作為函式引數進行傳遞
type函式功能一: 判斷物件的型別。
type函式功能二: 動態的建立類。type可以接受乙個類的描述作為引數,然後返回乙個類。
type函式語法: type(類名, 父類名稱的元組, 屬性資訊)
def hello(self):
print('hello')
person1=type('person',(object,),) #動態建立類給person1,類的名稱、父類(寫成元組)、類的屬性與屬性值、類的方法名與方法
p1=person1() #例項化物件
print(p1.country)
p1.hello()
執行結果:
china
hello
總結:
1). 元類就是建立類的類。函式type就是是元類。
2). python中一切皆物件。包括整數、字串、函式以及類都是物件,且都是從type類建立而來。
3). 動態生成類,不能控制類是如何生成的。python3 的metaclass可動態建立類。
4). 很多web框架都會使用metaclass 來建立類。掌握元類對理解源**至關重要。eg: orm框架類
metaclass的原理是什麼呢? 應用場景: django(orm)、元類實現單例模式等。 元類本身而言,實現的功能是:
攔截類的建立
修改類返回修改之後的類
自定義元類實現單例模式:指定建立person類的元類是singleton,使得person類例項化物件只能有乙個。
class singleton(type): #singleton用於建立實現單例模式的類person
"""自定義元類實現單例模式,父類是type
"""cache={} #儲存 類:類例項化物件即
def __call__(cls):
#判斷person是否例項化,有直接返回person的物件,沒有就找singleto的父類建立乙個物件返回給使用者
if cls not in cls.cache:
cls.cache[cls]=super(singleton, cls).__call__() #找父類建立乙個物件
return cls.cache[cls]#返回乙個物件
class person(object,metaclass=singleton):#指定建立person類的元類是singleton,singleton中沒有new方法,因此尋找singleton的父類type的new方法建立類person,此時返回person為物件,因此可以呼叫call方法.
pass
p1=person() #person為type中的new方法返回的物件,person()就會呼叫call方法
p2=person()
print(p1,p2)
執行結果:
<__main__.person object at 0x00000244d4a70d08> <__main__.person object at 0x00000244d4a70d08>
抽象基類有兩個特點:
1.規定繼承類必須具有抽象基類指定的方法
2.抽象基類無法例項化
基於上述兩個特點,抽象基類主要用於介面設計
實現抽象基類可以使用內建的abc模組
抽象基類理解:
import abc
class human(metaclass=abc.abcmeta):#當指定human類的元類為abc.abcmeta時,human為乙個抽象基類
@abc.abstractmethod #抽象方法,加此裝飾器表示繼承類也必須要有相同的方法introduce
def introduce(self):
print('introducing..')
def hello(self): #沒有加抽象方法裝飾器,繼承類可以沒有相同的方法hello
print('hello')
class person(human):
#規定繼承類必須具有抽象基類指定的方法
def introduce(self):
print('person')
def hello(self):
print('person hello')
#抽象基類無法例項化
#h=human() 報錯:can't instantiate abstract class human with abstract methods hello, introduce
p=person() #如果子類沒有抽象基類指定的方法introduce就不能例項化物件:can't instantiate abstract class person with abstract methods introduce
p.introduce() #繼承類有抽象方法introduce,子類必須要有introduce方法(方法體內可以不一樣),沒有會報錯。
p.hello() #繼承類有hello方法時執行繼承類hello方法內容,繼承類沒有hello方法尋找父類human的hello方法。
執行結果:
person
person hello
檢查某些事物以確定它是什麼、它知道什麼以及 它能做什麼。自省向程式設計師提供了極大的靈活性和控制力。例如python, ruby, object-c, c++都有自省的能力,這裡面的c++的自省的能力最弱, 只能夠知道是什麼型別,而像python可以知道是什麼型別,還有什麼屬性。
python中比較常見的自省(introspection)機制(函式用法)有: dir()、type()、 hasattr(),、setattr()、getattr()、delattr()、isinstance(),通過這些函式,我們能夠 在程式執行時得知物件的型別,判斷物件是否存在某個屬性,訪問物件的屬性。
動態語言與靜態語言的不同?
動態語言:可以在執行的過程中,修改**
靜態語言:編譯時已經確定好**,執行過程中不能修改
如果我們想要限制例項的屬性怎麼辦?
python允許在定義class的時候,定義乙個特殊的__slots__變數,來限制該class例項能新增的屬性
使用__slots__要注意,__slots__定義的屬性僅對當前類例項起作用,對繼承的子類是不起作用的
#slot限制物件屬性
import time
from datetime import date
class date(object):
#slot限制該物件能新增的屬性資訊
__slots__ = '__year','__month','__day' #slot限定該物件只能有三個屬性資訊:'__year','__month','__day'
def __init__(self, year,month,day):
self.__year=year
self.__month=month
self.__day=day
@property #只能檢視屬性不能修改
def year(self):
return self.__year
@property
def month(self):
return self.__month
@property
def day(self):
return self.__day
@classmethod #類方法傳入類名稱
def today(cls):
time_t=time.localtime()
return cls(time_t.tm_year,time_t.tm_mon,time_t.tm_mday)# date(2019, 1, 5)例項化物件,傳入3個引數給new方法
def __str__(self):
return '%s-%s-%s'%(self.__year,self.__month,self.__day)
d=date(2019,10,10) #找date的new方法建立物件,但是date中沒有new方法,就會找date的父類object的new方法建立物件讓date的init方法接收
print('物件型別:',type(d))#type(d)返回類名,d由此類建立
print('判斷是否有year屬性:',hasattr(d,'year'))
print('判斷是否有time屬性:',hasattr(d,'time')) #當前沒有time屬性
# setattr(d,'time','10:10:10') #slot限制了屬性的新增,因此不可以給d新增屬性time
# print('time:',getattr(d,'time')) #無法找到d的time屬性對應的值
print(date.today())
#注意使用new方法的條件為:需要在例項化物件前執行一些操作時使用例如判斷等.
#在例項化物件時如果date中有new方法,就需要先例項化乙個物件並返回這個物件.
執行結果:
物件型別: 判斷是否有year屬性: true
判斷是否有time屬性: false
2020-1-6
初始物件導向終
前面我們介紹了物件導向一些 封裝 繼承。今天我們繼續介紹物件導向最後乙個大塊,多型。什麼是多型,多型是一種事物的多種形態 多種表現形式。多型的前提是 類的繼承 介面實現 所以多型就是父類型別的引用指向子類的物件 public class test class person class student...
物件導向 初識物件導向
面向過程思想 步驟清晰簡單,第一步做什麼,第二步做什麼.面向過程適合處理一些較為簡單的問題 物件導向思想 物以類聚,分類的思維模式,思考問題首先會解決問題需要分哪些類,然後對這些類進行單獨思考,最後才是對某個分類下的細節進行面向過程的思索 物件導向適合處理複雜的問題,適合處理需要多人協作的問題 對於...
物件導向程式設計01 面向過程 物件導向
前面12講我已經寫完了從零開始學j ase 慶祝完結撒花!那麼從今天開始正式步入物件導向程式設計。建議開啟本章之前先回顧 j ase010方法詳解和 j a變數與方法的呼叫 同類操作中與跨類操作中的對比 物件導向程式設計 oop object oriented programming 物件導向程式設...