1. 程式人生 > >Python系列之反射、面向對象

Python系列之反射、面向對象

exp post 用戶輸入 裝飾器 場景 comment ebe alt 新的

一、反射

說反射之前先介紹一下__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

  1. def Bar(self) 其中self 為形式參數
  2. 和實例化對象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),有幾點要註意:

  1. 繼承要在子類加上父類的類名
  2. 子類和父類都有的方法,優先找子類的方法
  3. python裏面可以繼承多個類C#,java 不可以多繼承
  4. 如果繼承多個類,繼承順序為從左至右

例如下面的例子:

技術分享圖片 技術分享圖片
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)

成員小節:

  1. 自己去訪問自己的成員,除了類中的方法
  2. 通過類訪問的有:靜態字段、靜態方法、類方法

  3. 通過對象訪問:普通字段、普通方法 、特性

技術分享圖片 技術分享圖片
靜態字段:存在類中 ,靜態字段存在的意:把對象裏面重復的數據只在類裏保存一份
靜態方法 :沒有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系列之反射、面向對象