學(xué)了面向?qū)ο笕筇匦岳^承,多態(tài),封裝。今天我們看看面向?qū)ο蟮囊恍┻M(jìn)階內(nèi)容,反射和一些類的內(nèi)置函數(shù)。
一、isinstance和issubclass
class Foo: pass class Son(Foo): pass s = Son() #判斷一個(gè)對象是不是這個(gè)類的對象,傳兩個(gè)參數(shù)(對象,類) print(isinstance(s,Son)) print(isinstance(s,Foo)) #type更精準(zhǔn) print(type(s) is Son) print(type(s) is Foo) #判斷一個(gè)類是不是另一類的子類,傳兩個(gè)參數(shù)(子類,父類) print(issubclass(Son,Foo)) print(issubclass(Son,object)) print(issubclass(Foo,object)) print(issubclass(int,object))
二、反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態(tài)或行為的一種能力(自省)。這一概念的提出很快引發(fā)了計(jì)算機(jī)科學(xué)領(lǐng)域關(guān)于應(yīng)用反射性的研究。它首先被程序語言的設(shè)計(jì)領(lǐng)域所采用,并在Lisp和面向?qū)ο蠓矫嫒〉昧顺煽儭?
python面向?qū)ο笾械姆瓷洌? 通過字符串的形式操作對象相關(guān)的屬性。python中的一切事物都是對象(都可以使用反射)
四個(gè)可以實(shí)現(xiàn)反射的函數(shù): hasattr,getattr,setattr,delattr
下列方法適用于類和對象(一切皆對象,類本身也是一個(gè)對象)
class Foo: def __init__(self): self.name = 'egon' self.age = 73 def func(self): print(123) egg = Foo() #常用: #hasattr #getattr # print(hasattr(egg,'name')) print(getattr(egg,'name')) if hasattr(egg,'func'): #返回bool Foo_func = getattr(egg,'func') #如果存在這個(gè)方法或者屬性,就返回屬性值或者方法的內(nèi)存地址 #如果不存在,報(bào)錯(cuò),因此要配合hasattr使用 Foo_func() #不常用: #setattr # setattr(egg,'sex','屬性值') # print(egg.sex) # def show_name(self): # print(self.name + ' sb') # setattr(egg,'sh_name',show_name) # egg.sh_name(egg) # show_name(egg) # egg.sh_name() #delattr # delattr(egg,'name') # print(egg.name) # print(egg.name) # egg.func() # print(egg.__dict__) #反射 #可以用字符串的方式去訪問對象的屬性、調(diào)用對象的方法 反射舉例1
class Foo: f = 123 #類變量 @classmethod def class_method_demo(cls): print('class_method_demo') @staticmethod def static_method_demo(): print('static_method_demo') # if hasattr(Foo,'f'): # print(getattr(Foo,'f')) print(hasattr(Foo,'class_method_demo')) method = getattr(Foo,'class_method_demo') method() print(hasattr(Foo,'static_method_demo')) method2 = getattr(Foo,'static_method_demo') method2() #類也是對象反射舉例2
import my_module # print(hasattr(my_module,'test')) # # func_test = getattr(my_module,'test') # # func_test() # getattr(my_module,'test')() #import其他模塊應(yīng)用反射 from my_module import test def demo1(): print('demo1') import sys print(__name__) #'__main__' print(sys.modules) #'__main__':module_obj =sys.modules[__name__] #sys.modules['__main__'] # module_obj : print(module_obj) print(hasattr(module_obj,'demo1')) getattr(module_obj,'demo1')() #在本模塊中應(yīng)用反射 反射舉例3
#對象 #類 #模塊 : 本模塊和導(dǎo)入的模塊 def register(): print('register') def login(): pass def show_shoppinglst(): pass # print('注冊,登錄') ret = input('歡迎,請輸入您要做的操作: ') import sys print(sys.modules) # my_module = sys.modules[__name__] # if hasattr(my_module,ret): # getattr(my_module,ret)() if ret == '注冊': register() elif ret == '登錄': login() elif ret == 'shopping': show_shoppinglst() 反射舉例4
def test(): print('test')
三、類的內(nèi)置函數(shù)
1、__str__和__repr__
class Foo: def __init__(self,name): self.name = name def __str__(self): return '%s obj info in str'%self.name def __repr__(self): return 'obj info in repr' f = Foo('egon') # print(f) print('%s'%f) print('%r'%f) print(repr(f)) # f.__repr__() print(str(f)) #當(dāng)打印一個(gè)對象的時(shí)候,如果實(shí)現(xiàn)了str,打印中的返回值 #當(dāng)str沒有被實(shí)現(xiàn)的時(shí)候,就會調(diào)用repr方法 #但是當(dāng)你用字符串格式化的時(shí)候 %s和%r會分別去調(diào)用__str__和__repr__ #不管是在字符串格式化的時(shí)候還是在打印對象的時(shí)候,repr方法都可以作為str方法的替補(bǔ) #但反之不行 #用于友好的表示對象。如果str和repr方法你只能實(shí)現(xiàn)一個(gè):先實(shí)現(xiàn)repr
2、__del__
class Foo: def __del__(self): print('執(zhí)行我啦') f = Foo() print(123) print(123) print(123) #析構(gòu)方法,當(dāng)對象在內(nèi)存中被釋放時(shí),自動觸發(fā)執(zhí)行。 #注:此方法一般無須定義,因?yàn)镻ython是一門高級語言,程序員在使用時(shí)無需關(guān)心內(nèi)存的分配和釋放,因?yàn)榇斯ぷ鞫际墙唤oPython解釋器來執(zhí)行,所以,析構(gòu)函數(shù)的調(diào)用是由解釋器在進(jìn)行垃圾回收時(shí)自動觸發(fā)執(zhí)行的。
3、item系列
__getitem__\__setitem__\__delitem__
class Foo: def __init__(self): self.name = 'egon' self.age = 73 def __getitem__(self, item): return self.__dict__[item] def __setitem__(self, key, value): # print(key,value) self.__dict__[key] = value def __delitem__(self, key): del self.__dict__[key] f = Foo() print(f['name']) print(f['age']) f['name'] = 'alex' # del f['name'] print(f.name) f1 = Foo() print(f == f1)
4、__new__
# class A: # def __init__(self): #有一個(gè)方法在幫你創(chuàng)造self # print('in init function') # self.x = 1 # # def __new__(cls, *args, **kwargs): # print('in new function') # return object.__new__(A, *args, **kwargs) # a = A() # b = A() # c = A() # d = A() # print(a,b,c,d) #單例模式 class Singleton: def __new__(cls, *args, **kw): if not hasattr(cls, '_instance'): cls._instance = object.__new__(cls, *args, **kw) return cls._instance one = Singleton() two = Singleton() three = Singleton() go = Singleton() print(one,two) one.name = 'alex' print(two.name)
5、__call__
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 執(zhí)行 __init__ obj() # 執(zhí)行 __call__ Foo()() # 執(zhí)行 __init__和執(zhí)行 __call__ #構(gòu)造方法的執(zhí)行是由創(chuàng)建對象觸發(fā)的,即:對象 = 類名() ;而對于 __call__ 方法的執(zhí)行是由對象后加括號觸發(fā)的,即:對象() 或者 類()()
6、__len__,__hash__
class Foo: def __len__(self): return len(self.__dict__) def __hash__(self): print('my hash func') return hash(self.name) f = Foo() print(len(f)) f.name = 'egon' print(len(f)) print(hash(f))
7、__eq__
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return True a = A() b = A() print(a == b) #__eq__控制著==的結(jié)果
8、內(nèi)置函數(shù)實(shí)例
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['紅心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck)) 紙牌游戲
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['紅心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] def __setitem__(self, key, value): self._cards[key] = value deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck)) from random import shuffle shuffle(deck) print(deck[:5]) 紙牌游戲2
class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash(self.name+self.sex) def __eq__(self, other): if self.name == other.name and other.sex == other.sex:return True p_lst = [] for i in range(84): p_lst.append(Person('egon',i,'male')) print(p_lst) print(set(p_lst)) #只要姓名和年齡相同就默認(rèn)為一人去重 去重
以上這篇python進(jìn)階_淺談面向?qū)ο筮M(jìn)階就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
