---python基礎(二十七):反射與內置方法

下面是小凰凰的簡介,看下吧!
💗人生態度:珍惜時間,渴望學習,熱愛音樂,把握命運,享受生活
💗學習技能:網絡 -> 雲計算運維 -> python全棧( 當前正在學習中)
💗您的點贊、收藏、關注是對博主創作的最大鼓勵,在此謝過!
有相關技能問題可以寫在下方評論區,我們一起學習,一起進步。
後期會不斷更新python全棧學習筆記,秉着質量博文爲原則,寫好每一篇博文。

一、反射

1、引言

首先假設我們要搞一個程序項目對接,對方向你扔過來了一個對象數據,但是他並不會告訴你這個對象數據有哪些數據屬性、函數屬性,如果試的話就會出現報錯的情況。我們怎樣解決這種情況呢?這就要用到反射了,然而說反射之前,我先說下動態語言這一概念!

python是一門動態語言,如何理解?

答:舉個例子,python:x = 10,java: int x = 10# 這就是動態語言與靜態語言的區別,python這句代碼,程序只有在執行的時候,你才知道它是整型還是啥,因此python是動態語言。然而java在定義時就指明瞭類型,因此它是靜態語言。

# 注意:我聽有人說反射機制對動態語言很重要,靜態語言好多都沒有。但是我感覺有無反射,這應該與動態還是靜態並沒有什麼聯繫。

2、根據現有知識實現反射機制(反射應用的具體場景)

>>> class People:
...     def __init__(self,name,age,gender):
...         self.name=name
...         self.age=age
...         self.gender=gender
>>> obj=People('egon',18,'male')
>>> dir(obj) # 下面全是obj這個對象能'.'出來的屬性,它們全爲字符串
[......,'age', 'gender', 'name']
# 假如我們程序對接需要obj這個對象的name屬性
>>> obj.dir(obj)[-1] # 相當於obj.'name',這個可以這樣嗎,顯然是不行的。
# ---- 怎麼辦?-----
>>> obj.__dict__[dir(obj)[-1]] # 這樣我們就實現了反射,但是這樣太複雜了,我們有專門的方法,更簡單的實現反射!
'egon'

3、採用反射機制的專用方法實現反射

class Teacher:
    def __init__(self,full_name):
        self.full_name =full_name

t=Teacher('Egon Lin')

# hasattr(object,'name')
hasattr(t,'full_name') # 按字符串'full_name'判斷有無屬性t.full_name

# getattr(object, 'name', default=None)
getattr(t,'full_name',None) # 等同於t.full_name,不存在該屬性則返回默認值None

# setattr(x, 'y', v)
setattr(t,'age',18) # 等同於t.age=18

# delattr(x, 'y')
delattr(t,'age') # 等同於del t.age

基於反射可以十分靈活地操作對象的屬性,比如將用戶交互的結果反射到具體的功能執行

>>> class FtpServer:
...     def serve_forever(self):
...         while True:
...             inp=input('input your cmd>>: ').strip()
...             cmd,file=inp.split() # 看下下方的輸入,就明白了爲什麼cmd,file
...             if hasattr(self,cmd): # 根據用戶輸入的cmd,判斷對象self有無對應的方法屬性
...                 func=getattr(self,cmd) # 根據字符串cmd,獲取對象self對應的方法屬性
...                 func(file) # 上面這句代碼等同於sever.去掉字符串的cmd,因此還需要傳參file
...     def get(self,file):
...         print('Downloading %s...' %file)
...     def put(self,file):
...         print('Uploading %s...' %file)
... 
>>> server=FtpServer()
>>> server.serve_forever()
input your cmd>>: get a.txt
Downloading a.txt...
input your cmd>>: put a.txt
Uploading a.txt...

二、內置方法

Python的Class機制內置了很多特殊的方法來幫助使用者高度定製自己的類,這些內置方法都是以雙下劃線開頭和結尾的,會在滿足某種條件時自動觸發,我們以常用的__str____del__爲例來簡單介紹它們的使用。

1、__str__

__str__方法會在對象被print打印時自動觸發,即是說print功能打印就調用的是這個方法,並打印這個方法的返回值,我們通常基於方法來定製對象的打印信息,該方法必須返回字符串類型

>>> class People:
...     def __init__(self,name,age):
...         self.name=name
...         self.age=age
...     def __str__(self):
...         return '<Name:%s Age:%s>' %(self.name,self.age) #返回類型必須是字符串
... 
>>> p=People('lili',18)
>>> print(p) #觸發p.__str__(),拿到返回值後進行打印
<Name:lili Age:18>

如果不定製的話就會打印對象的內存地址,我們要內存地址有什麼用?因此我們通過str定製,打印對象時,打印我們想看到的有用信息。

2、__del__

__del__會在對象被刪除時自動觸發。由於Python自帶的垃圾回收機制會自動清理Python程序的資源,所以當一個對象只佔用應用程序級資源時,完全沒必要爲對象定製__del__方法,但在產生一個對象的同時涉及到申請系統資源(比如系統打開的文件、網絡連接等)的情況下,關於系統資源的回收,Python的垃圾回收機制便派不上用場了,需要我們爲對象定製__del__方法,用來在對象被刪除時,自動觸發回收系統資源的操作

# 這裏我們用打開文件爲例,使其回收打開文件佔用的內存資源
class MySQL:
    def __init__(self):
        self.read_f=open ('a.txt',mode = 'r') # 打開文件
    def __del__(self):
        self.read_f.close() # 關閉文件,回收系統內存資源

obj=MySQL() # 在對象obj被刪除時,自動觸發obj.__del__()

對象被刪除有兩種情況:

  • 執行del obj代碼,主動刪除
  • 程序運行完畢,全部對象都被刪除

有人可能會認爲還有引用計數爲0,既然有對象,怎麼可能會引用計數爲0?而且引用計數爲0,只是針對堆內存中的變量存的內容而言,obj這個變量名是在棧內存裏,兩者沒聯繫!

注意:最後送大家一套2020最新企業Pyhon項目實戰視頻教程,點擊此處 進來獲取 跟着練習下,希望大家一起進步哦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章