Python系列之反射、面向對象
一、反射
說反射之前先介紹一下__import__方法,這個和import導入模塊的另一種方式
1. import commons 2. __import__(‘commons‘)
如果是多層導入:
1. from list.text import commons 2. __import__(‘ list.text.commons‘,fromlist=True) #如果不加上fromlist=True,只會導入list目錄
反射即想到4個內置函數分別為:getattr、hasattr、setattr、delattr 獲取成員、檢查成員、設置成員、刪除成員下面逐一介紹先看例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class Foo( object ):
def __init__( self ):
self .name = ‘abc‘
def func( self ):
return ‘ok‘
obj = Foo()
#獲取成員
ret = getattr (obj, ‘func‘ ) #獲取的是個對象
r = ret()
print (r)
#檢查成員
ret = hasattr (obj, ‘func‘ ) #因為有func方法所以返回True print (ret)
#設置成員
print (obj.name) #設置之前為:abc
ret = setattr (obj, ‘name‘ , 19 )
print (obj.name) #設置之後為:19
#刪除成員
print (obj.name) #abc
delattr (obj, ‘name‘ )
print (obj.name) #報錯
|
對於反射小節:
1.根據字符串的形式導入模塊。 2.根據字符串的形式去對象(某個模塊)中操作其成員
實例:基於反射實現類Web框架的路由系統
實現思路:規定用戶輸入格式 模塊名/函數名 通過__import__的形式導入模塊並通過 hasattr和getattr 檢查並獲取函數返回值。
二、面向對象
面向對象簡稱OOP,面向對象的程序設計把計算機程序視為一組對象的集合,而每個對象都可以接收其他對象發過來的消息,並處理這些消息,計算機程序的執行就是一系列消息在各個對象之間傳遞。
語法格式見下圖:
關鍵字class 和函數def 是一樣的。類名通常是大寫開頭的單詞,定義號類後就可以創建實例如上圖的類加()就相當於創建一個類的實例obj
- def Bar(self) 其中self 為形式參數
- 和實例化對象obj的內存地址相同
類的三大特性:封裝、繼承、多態
1、封裝
面向對象編程的一個重要特點就是數據封裝。例如:
class Foo: def fetch(self): print(self.beckend) #self 直接在對象裏面取值 obj = Foo() obj.beckend = ‘www.baidu.com‘ #把beckend封裝在對象裏面 obj.fetch()
class Foo : ‘‘‘構造方法‘‘‘ def __init__(self,bk): self.backend = bk # 把obj對象的參數封裝在 init 方法裏 def fetch(self): print(self.backend) def add(self): print(self.backend) obj = Foo(‘www.xxx.com‘) obj.fetch() obj.add()
通過代碼我們看到__init__:稱之為構造方法,需要註意__init__的第一個參數永遠是self,表示的實例本身
封裝的意義:當同一類型的方法具有相同的參數時,可以直接封裝到對象裏減少代碼量。
使用場景把類當作模版,創建多個對象並且對象內封裝的數據可以不同。
2、繼承
當我們定義一個class的時候,可以從某個現有的class繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類(Base class、Super class),有幾點要註意:
- 繼承要在子類加上父類的類名
- 子類和父類都有的方法,優先找子類的方法
- python裏面可以繼承多個類C#,java 不可以多繼承
- 如果繼承多個類,繼承順序為從左至右
例如下面的例子:
class Animals: def chi(self): print(self.Name + ‘ 吃‘) def he(self): print(self.Name + ‘ 喝‘) class Dog(Animals): def __init__(self,name): self.Name = name def jiao(self): print(self.Name + ‘ 叫‘) xxoo =Dog(‘某某某‘) xxoo.chi() xxoo.he() xxoo.jiao()
class Animals: def chi(self): print(self.Name +‘ 吃‘) def he(self): print(self.Name + ‘ 喝‘) class Uncle: def du(self): print(self.Name + ‘ 賭‘) class Dog(Animals,Uncle): def __init__(self,name): self.Name = name xxoo = Dog(‘某某某‘) xxoo.chi() xxoo.du()
關於繼承順序需要註意例如 E繼承(C,D) -->C繼承(A)-->D繼承(B) 如下圖(python3):
class A: def f1(self): print(‘A‘) class B: def f(self): print(‘B‘) class C(A): def f(self): print(‘C‘) class D(B): def f1(self): print(‘D‘) class E(C,D): def f(self): print(‘E‘) aa = E() aa.f1()
第二種查找順序:E繼承(C,D)-->C繼承(A),D繼承(B)-->A和B都繼承(Boos) ,查找順序如下(python3):
class Boos: def f1(self): print(‘Boos‘) class A(Boos): def f(self): print(‘A‘) class B(Boos): def f(self): print(‘B‘) class C(A): def f(self): print(‘C‘) class D(B): def f1(self): print(‘D‘) class E(C,D): def f(self): print(‘E‘) aa = E() aa.f1()
下面說下python27的查找順序是什麽那?
未繼承object為經典類查找順序--> 深度優先
3、多態
即多種形態....
補充:
關於繼承如何執行父類的構造方法那?有兩種方法如下代碼:
class Annimal: def __init__(self): print(‘Annimal的構造方法‘) self.ty = ‘動物‘ class Cat(Annimal): def __init__(self): print(‘Cat的構造方法‘) self.n = ‘貓‘ super(Cat, self).__init__() #推薦用這種 # Annimal.__init__(self) #第二種方式 c = Cat()
查找源碼的過程(self.xxxx(),從底層開始找)
三、成員
分別有靜態字段、靜態方法、類方法、特性、普通字段、普通方法、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
class Provice:
#靜態字段
country = ‘China‘
def __init__( self ,name):
#普通字段
self .name = name
#普通方法
def show( self ):
print ( ‘show‘ )
@staticmethod #靜態方法
def xo(arg):
print ( ‘xo‘ )
print (arg)
@classmethod #類方法,必須要有個cls參數:自動傳入類名
def xxoo( cls ):
print ( ‘xxoo‘ , cls )
def start( self ):
print ( ‘start‘ )
@property #特性
def end( self ):
print ( ‘end‘ )
@end .setter
def end( self ,values):
print (values)
self .name = values #也可以更改內存裏的值
Provice.country #類訪問靜態字段
Provice.xo( ‘alex‘ ) #類訪問靜態方法
Provice.xxoo() #訪問類方法
#獲取特性值
obj = Provice( ‘alex‘ )
obj.end
#設置特性值
obj1 = Provice( ‘alex‘ )
obj1.end = ‘123‘
print (obj1.name)
#普通方法
obj1 = Provice( ‘alex‘ )
obj1.show()
#普通字段
obj1 = Provice( ‘alex‘ )
print (obj1.name)
|
成員小節:
- 自己去訪問自己的成員,除了類中的方法
-
通過類訪問的有:靜態字段、靜態方法、類方法
-
通過對象訪問:普通字段、普通方法 、特性
靜態字段:存在類中 ,靜態字段存在的意:把對象裏面重復的數據只在類裏保存一份 靜態方法 :沒有self 可以傳參數,調用的時候也需要傳入參數 ,存在的意義:不需要創建對象,就可以訪問此方法 ,為類而生 類方法:必須要有個cls參數:自動傳入類名 特性 對象調用 、不能加參數,執行不用加括號 普通字段,存放在對象中 普通方法 存在的意義:普通方法如果要想被調用就需要創建self ,為對象而生
四、成員修飾符
公有成員:任何地方都能訪問
私有成員:只有在類的內部才能訪問,定義方式為命名時,前兩個字符為下劃線,如 "__test"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Person:
country = ‘China‘ #靜態字段,屬於公有成員
__planet = ‘Earth‘ #靜態字段,屬於私有成員
def __init__( self ,name):
print ( ‘Person build self.name‘ )
self .name = name
def say( self ):
print ( ‘The planet is %s‘ % Person.__planet) #在類的內部訪問私有靜態字段
p1 = Person( ‘Nothing‘ )
p1.say()
print (p1.country) #訪問公有靜態字段
print (p1.__planet) #訪問私有靜態字段
#執行結果:
Person build self .name
The planet is Earth #在類的內部可以訪問
print (p1.__planet)
China #外部可以訪問公有靜態字段
AttributeError: ‘Person‘ object has no attribute ‘__planet‘ #外部無法訪問私有靜態字段
|
小節:私有成員只能在類內部使用,其他的都不能使用包括繼承的子類,也不是絕對 也可以通過訪問,但是不推薦
對象._類名__字段名
類的特殊成員:
1 2 3 4 5 6 7 8 9 10 |
__doc__ 表示類的描述信息
__module__ 表示當前操作的對象在那個模塊
__class__ 表示當前操作的對象的類是什麽
__init__ 構造方法,通過類創建對象時,自動觸發執行
__call__ 對象後面加括號,觸發執行。
__dict__ 類或對象中的所有成員
__str__ 如果一個類中定義了__str__方法,那麽在打印 對象 時,默認輸出該方法的返回值。
__init__ 構造方法,通過類創建對象時,自動觸發執行
__setitem__,__getitem__,__delitem__ 用於索引操作,如字典。分別表示獲取、設置、刪除數據
|
五、異常處理
異常即是一個事件,該事件會在程序執行過程中發生,影響了程序的正常執行。
一般情況下,在Python無法正常處理程序時就會發生一個異常。
異常是Python對象,表示一個錯誤。
當Python腳本發生異常時我們需要捕獲處理它,否則程序會終止執行。
語法:
1 2 3 4 5 6 7 8 9 10 11 |
try :
<語句> #運行別的代碼
except <名字>:
<語句> #如果在try部份引發了‘name‘異常
except <名字>,<數據>:
<語句> #如果引發了‘name‘異常,獲得附加的數據
else :
<語句> #如果沒有異常發生
finally :
xxxx
|
標準的異常有:
+ View Code五、單例模式
單例模式,也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行為。
用裝飾器方式實現
def wapper(cls): instances = {} def inner(): if cls not in instances: instances[cls] = cls() return cls return inner @wapper def Foo(): pass f1 =Foo() f2 =Foo() print(f1 is f2)
靜態方法實現:
class ConnectPool: __instatnce=None @staticmethod def get_instance(): if ConnectPool.__instatnce: return ConnectPool.__instatnce else: ConnectPool.__instatnce = ConnectPool() return ConnectPool.__instatnce obj =ConnectPool.get_instance() print(obj) obj1 =ConnectPool.get_instance() print(obj1)
Python系列之反射、面向對象