1. 程式人生 > >面向對象:反射、內置方法

面向對象:反射、內置方法

是否 val urn 進行 subclass input 補充 sta 系列

反射:通過字符串映射到對象或者類的屬性

反射的方法:

class People:
    country = "China"

    def __init__(self,name,age):
        self.name = name
        self.age = age

    def talk(self):
        print("%s is talking" % self.name)

obj = People("neo",22)

"""
判斷是否擁有某個屬性: hasattr(o,name)  # name是字符串格式
"""
print(hasattr(obj,"
name")) print(hasattr(obj,"talk")) print(hasattr(People,"country")) print(hasattr(People,"talk")) # 運行結果: # True # True # True # True """ 得到某個屬性的值: getattr(o,name,default) # default處寫上“None”,那麽即使沒有這個name程序也不會報錯 """ print(getattr(obj,"name",None)) print(getattr(obj,"talk",None)) print(getattr(obj,"
gender",None)) print(getattr(People,"country",None)) print(getattr(People,"talk",None)) # 運行結果: # neo # <bound method People.talk of <__main__.People object at 0x00000035DB166668>> # None # China # <function People.talk at 0x000000878224BA60> """ 添加、修改某個屬性: setattr(object,"name",value) """ setattr(obj,
"gender","male") setattr(obj,"name","NEO") print(obj.gender) print(obj.name) setattr(People,"nation","Han") print(People.__dict__) print(getattr(People,"nation",None)) print(People.nation) # 運行結果: # male # NEO # {‘__module__‘: ‘__main__‘, ‘country‘: ‘China‘, ‘__init__‘: <function People.__init__ at 0x00000018D460B9D8>, ‘talk‘: <function People.talk at 0x00000018D460BA60>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘People‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘People‘ objects>, ‘__doc__‘: None, ‘nation‘: ‘Han‘} # Han # Han """ 刪除某個屬性: delattr(o,name) """ delattr(obj,"age") print(obj.__dict__) delattr(People,"country") print(People.__dict__) # 運行結果: # {‘name‘: ‘NEO‘, ‘gender‘: ‘male‘} # {‘__module__‘: ‘__main__‘, ‘__init__‘: <function People.__init__ at 0x0000002C1C9BB9D8>, ‘talk‘: <function People.talk at 0x0000002C1C9BBA60>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘People‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘People‘ objects>, ‘__doc__‘: None, ‘nation‘: ‘Han‘}

反射的使用:

"""接收用戶輸入,觸發相應的功能"""
class Service:
    def run(self):
        while True:
            # 輸入的是格式化的內容,如: get a.txt 或者 upload a.txt
            cmd = input(">>>").strip().split() # cmd = ["get","a.txt"]

            if hasattr(self,cmd[0]):
                func = getattr(self,cmd[0])
                func(cmd)

    def get(self,cmd):
        print("get .......%s" %cmd[1])

    def upload(self,cmd):
        print("upload ......%s" %cmd[1])

obj = Service()
obj.run()

內置方法:

一、isinstance(obj,cls)和 issubclass(sub,super)

  isinstance(obj,cls) # 檢查對象obj是否為 類 cls的對象 # 返回Bool值

  issubclass(sub,super) # 檢測sub類是否為 super類的派生類(子類) # 返回Bool值

二、item系列: __getitem__(self, item)、__setitem__(self, key, value)、__delitem__(self, key)

"""通過item系列能夠把對象當做字典去處理"""
class People:

    def __init__(self,name):
        self.name = name

    def __getitem__(self, item):
        print("get item test [%s]" %item)
        return self.__dict__.get(item)

    def __setitem__(self, key, value):
        print("set item test" )
        self.__dict__[key] = value

    def __delitem__(self, key):
        print("del item test")
        self.__dict__.pop(key)
        # del self.__dict__[key]  # 這種方式也可以

"""下面討論這3中item在何種情況下被觸發"""

p = People("neo")

p["age"]  # 對象["name"] 能夠觸發 __getitem__(self,item)  # 跟__getitem__(self,item) 函數體的具體代碼無關
# 運行結果:
# get item test [age]

p["gender"] = "male"  # 對象["key"] = "value" 能夠觸發 __setitem__(self,key,value)  # 同樣, 與其函數體的具體代碼無關
print(p.__dict__)
# 運行結果:
# set item test
# {‘name‘: ‘neo‘, ‘gender‘: ‘male‘}

del p["name"]   # del 對象["name"] 能夠觸發 __delitem__(self,key)  # 與其函數體的具體代碼無關
# 運行結果:
# del item test

三、 __str__(self) 方法:使打印對象的輸出結果格式化

"""
__str__(self)方法:將print(object)的打印結果由對象的內存地址格式化成你需要的字符串形式,從而增加了打印結果的可讀性
print(object)觸發__str__(self),
"""
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def __str__(self):
        print("=====>>>")
        return "aaa"   # __str__只能返回字符串格式
        # return "<name:%s> <age:%s>"%(self.name,self.age)   # 可以自己定義打印結果的格式

p = People("neo",18)
print(p)   # 打印對象能夠觸發__str__(self)
# 運行結果:
# =====>>>
# aaa

四、__del__ 方法

補充知識:

# 以open(file)為例

f = open("setting.py")  # python沒有能力自己打開硬盤文件,打開文件的動作需要操作系統去完成,所以 open其實是個命令:告訴操作系統讓它打開a.txt這個文件;這個賦值過程涉及兩方面的資源:變量f 是應用程序的資源,open("setting.py"):打開硬盤文件是操作系統的資源 
f.read()  # read()也是一個命令,是讓操作系統讀取文件內容 # read()需要在文件關閉之前進行

"""
資源不能一直被占用;python只能回收它自己應用程序的資源(例如python程序結束後資源都會被回收),但python沒有能力回收操作系統的資源,所以在python程序結束前一定要關閉掉文件
"""
f.close()  # close()也是一個對操作系統發出的命令,讓操作系統關閉掉硬盤上的文件,並把操作系統裏面相應的資源回收;註意:python程序結束前一點要關閉掉文件,這一點不要忘

"""
雖然硬盤文件已經關閉掉,但f  還能夠打印,因為f 是應用程序的資源;但文件關閉後就不能再read了
"""
print(f)
# 打印結果:
# <_io.TextIOWrapper name=‘setting.py‘ mode=‘r‘ encoding=‘cp936‘>

__del__(self) 的作用: 讓操作系統回收掉自己的資源

觸發情況:1. del f # del file(file是個對象,如上面示例中的f)能夠自動調用類內部的 __del__(self) (先觸發__del__再刪除f這個對象)

     2. 如果沒有del f,那麽在程序結束的之前會自動調用__del__(self)(或者說在程序運行到最後已經沒有其他代碼要執行了) (也是python先觸發__del__,再刪除python自己的f)

總結: 在類內部定義的內置方法都是綁定給對象的;而且在某種情況下會自動被觸發調用

附: 其他內置方法可參考鏈接: http://www.cnblogs.com/linhaifeng/articles/6204014.html

面向對象:反射、內置方法