isinstance()
判斷isinstance(obj,cls)中obj是否是cls類的對象
class Person: def __init__ (self,name): self.name = name p = Person( ' Jane ' ) print (isinstance(p,Person)) # True
issubclass()
判斷issubclass(sub,super)中sub是否是super類的派生類
class Person: def __init__ (self,name): self.name = name class Father(Person): pass print (issubclass(Father,Person)) # True print (issubclass(Person,Father)) # False
反射
反射就是用字符串類型的名字去操作變量,python中的一切事物皆為對象(都可以使用反射)
1.hasattr()
函數(shù)用于判斷對象是否包含對應(yīng)的屬性,通常和getattr一起搭配使用,先用hasattr判斷是否這個對象含有這個屬性,如果有就通過getattr來拿值,如果沒有就提示沒有這個屬性
class Person: age = 20 def __init__ (self,name,height,weight): self.name = name self.height = height self.weight = weight def fuc(self): print ( ' weight...height... ' ) #1 if hasattr(Person, ' age ' ): print (getattr(Person, ' age ' )) # 20 else : print ( ' 沒有這個類屬性! ' ) #2 p = Person( ' Adson ' ,1.6,75 ) if hasattr(p, ' bmi ' ): print (getattr(p, ' bmi ' )) else : print ( ' 沒有這個屬性! ' ) # 沒有這個屬性! #3 if hasattr(p, ' fuc ' ): getattr(p, ' fuc ' )() # weight...height... else : print ( ' 沒有這個方法! ' )
2.getattr()
函數(shù)用于返回一個對象屬性值
(1)反射對象的屬性
class A: def __init__ (self,name): self.name = name a = A( ' Adson ' ) ret = getattr(a, ' name ' ) print (ret) # Adson
(2)反射對象的方法
class A: def fuc(self): print ( ' This is fuc! ' ) a = A() ret = getattr(a, ' fuc ' ) print (ret) #<__main__.A object at 0x00000000024E1C88>> 獲得一個綁定方法的地址 ret() # This is fuc! 在ret后加上括號去調(diào)用方法
(3)反射類的屬性
class A: age = 18 ret = getattr(A, ' age ' ) print (ret) # 18
(4)反射類的方法(classmethod、staticmethod)
一般的調(diào)用方式是類名.方法名
class A: @classmethod def fuc(cls): print ( ' This is class fuc! ' ) ret = getattr(A, ' fuc ' ) print (ret) #ret() # This is class fuc! getattr(A, ' fuc ' )() # This is class fuc! 簡寫 > 獲得一個綁定方法
(5)反射模塊的變量
先建立一個模塊,模塊名pyfile.py,增加一個變量
dic = { ' apple ' : 18, ' banana ' : 20}
然后通過我的模塊反射pyfile模塊的變量
import pyfile print (pyfile.dic) # {'apple': 18, 'banana': 20} ret = getattr(pyfile, ' dic ' ) print (ret) # {'apple': 18, 'banana': 20}
(6)反射模塊的方法
先建立一個模塊,模塊名pyfile.py,增加一個方法
def fuc(): print ( ' abc123aaa!!! ' )
然后通過我的模塊反射pyfile模塊方法
import pyfile ret = getattr(pyfile, ' fuc ' ) print (ret) #ret() # abc123aaa!!! getattr(pyfile, ' fuc ' )() # abc123aaa!!!
(7)反射模塊的類
先建立一個模塊,模塊名pyfile.py,增加一個類
class B: price = 200 def __init__ (self,name): self.name = name def fuc(self): print ( ' This classB fuc.. ' + self.name)
然后通過我的模塊反射pyfile模塊方法
import pyfile b = getattr(pyfile, ' B ' )( ' Josn ' ) # getattr相當(dāng)于拿到了這個模塊的B類 并進(jìn)行實(shí)例化了一個b對象 print (b. __dict__ ) # {'name': 'Josn'} print (b.price) # 200 b.fuc() # This classB fuc..Josn
(8)反射自身模塊的變量
通過sys.modules['__main__']找到當(dāng)前的模塊
import time import sys t = time.asctime(time.localtime(time.time())) print (t) # Mon Sep 9 22:36:40 2019 print (sys.modules[ ' __main__ ' ]) #print (sys.modules[ ' __main__ ' ].t) # Mon Sep 9 22:38:01 2019 ret = getattr(sys.modules[ ' __main__ ' ], ' t ' ) print (ret) # Mon Sep 9 22:39:05 2019
(9)反射自身模塊的方法
import sys def fuc(): print ( ' abc123... ' ) ret = getattr(sys.modules[ ' __main__ ' ], ' fuc ' ) print (ret) #ret() # abc123... getattr(sys.modules[ ' __main__ ' ], ' fuc ' )() # abc123...
3.setattr()
用于設(shè)置屬性值,該屬性不一定是存在的
class Person: age = 20 def __init__ (self,name,height,weight): self.name = name self.height = height self.weight = weight # 對一個對象修改 p = Person( ' Adson ' ,1.6,75 ) setattr(p, ' name ' , ' Jane ' ) setattr(p, ' height ' ,1.7 ) setattr(p, ' gender ' , ' male ' ) print (p. __dict__ ) # {'name': 'Jane', 'height': 1.7, 'weight': 75, 'gender': 'male'} # 對一個類修改 print (Person. __dict__ ) # {'__module__': '__main__', 'age': 20, '__init__':, setattr(Person, ' age ' ,21 ) setattr(Person, ' name ' , ' Jane ' ) setattr(Person, ' height ' ,1.7 ) setattr(Person, ' gender ' , ' male ' ) print (Person. __dict__ ) # {'__module__': '__main__', 'age': 21, '__init__':
'__dict__':, '__weakref__':
, '__doc__': None} ,
'__dict__':, '__weakref__':
, '__doc__': None,
'name': 'Jane', 'height': 1.7, 'gender': 'male'}
這里的不同之處在于對象和類它們存放值的命名空間不同
4.delattr()
用于刪除屬性
class Person: age = 20 def __init__ (self,name,height,weight): self.name = name self.height = height self.weight = weight p = Person( ' Adson ' ,1.6,75 ) print (p. __dict__ ) # {'name': 'Adson', 'height': 1.6, 'weight': 75} delattr(p, ' height ' ) print (p. __dict__ ) # {'name': 'Adson', 'weight': 75}
print (Person. __dict__ [ ' age ' ]) # 20 delattr(Person, ' age ' ) print (Person. __dict__ [ ' age ' ]) # KeyError: 'age'
?
內(nèi)置類方法
內(nèi)置的類方法和內(nèi)置函數(shù)之間有著千絲萬縷的關(guān)系
1.__str__
當(dāng)我們定義一個類,并實(shí)例化一個對象,再對這個對象去print
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types a = A( ' AAA ' ,200, ' A ' ) print (str(a)) # <__main__.A object at 0x00000000020D7A58>
這里返回了這個對象的內(nèi)存地址,我們再在A類里面添加一個__str__方法,看一看結(jié)果是什么
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __str__ (self): return ' name = %s,price = %s,types = %s ' % (self.name,self.price,self.types) a = A( ' AAA ' ,200, ' A ' ) print (a) # name = AAA,price = 200,types = A
可以這么說我們在每次打印一個對象的時候就是在調(diào)用obj.__str__,且__str__方法需要返回一個字符串,當(dāng)做這個類的描寫;當(dāng)我們使用print這個對象時會打印出__str__方法return出來的字符串
2.__repr__
先說一下repr()方法,它能讓我們輸入的數(shù)據(jù)原形畢露
print (repr(1)) # 1 print (repr( ' 1 ' )) # '1' print (repr( ' aaa ' )) # 'aaa' print (repr({ ' a ' :1, ' b ' :2})) # {'a': 1, 'b': 2}
和__str__一樣我們在定義一個類后去print它實(shí)例化的對象,會獲得到一個對象的內(nèi)存地址
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types a = A( ' AAA ' ,200, ' A ' ) print (repr(a)) # <__main__.A object at 0x00000000024E7A58>
然后我們再在A中添加__repr__方法看一下print的結(jié)果
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __repr__ (self): return ' name = %s,price = %s,types = %s ' % (self.name, self.price, self.types) a = A( ' AAA ' ,200, ' A ' ) print (repr(a)) # name = AAA,price = 200,types = A print (a) # name = AAA,price = 200,types = A
因?yàn)槲覀冊陬愔卸x了一個__repr__方法,這里我們print對象a的時候就相當(dāng)于是調(diào)用了里面的__repr__方法即a.__repr__
如果一個類中的__str__和__repr__同時存在的話,那么最后的打印結(jié)果是什么呢?
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __str__ (self): return ' str(name = %s,price = %s,types = %s) ' % (self.name,self.price,self.types) def __repr__ (self): return ' repr(name = %s,price = %s,types = %s) ' % (self.name, self.price, self.types) a = A( ' AAA ' ,200, ' A ' ) print (repr(a)) # repr(name = AAA,price = 200,types = A) 即a.__repr__ print ( ' %r ' %a) # repr(name = AAA,price = 200,types = A) print (str(a)) # str(name = AAA,price = 200,types = A) 即a.__str__ print ( ' %s ' %a) # str(name = AAA,price = 200,types = A) print (a) # str(name = AAA,price = 200,types = A)
如果一個類中 有 __str__方法,那么它就會先找__str__, 沒有 的話就再找__repr__方法,再 沒有 的話就會找它父類的__str__方法
__str__方法和__repr__方法能夠返回該對象一個規(guī)范化的信息
3.__len__
我們將一個實(shí)例化的對象直接print它的len看一看會出現(xiàn)什么結(jié)果
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types a = A( ' AAA ' ,200, ' A ' ) print (len(a)) # TypeError: object of type 'A' has no len()
結(jié)果報(bào)錯說A少了一個len函數(shù),也就是我們只有在A中加上一個__len__的方法才能去計(jì)算長度相關(guān)的東西
計(jì)算屬性的長度:
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __len__ (self): return len(self.name) a = A( ' AAA ' ,200, ' A ' ) print (len(a)) # 3
計(jì)算一個列表屬性有幾個元素:
class A: def __init__ (self,goods = []): self.goods = [] def __len__ (self): return len(self.goods) a = A() print (len(a)) # 0 a.goods.append( ' Banana ' ) a.goods.append( ' Apple ' ) a.goods.append( ' Orange ' ) a.goods.append( ' Pear ' ) print (len(a)) # 4
4.__call__
用于打印這個對象的屬性
class A: gender = ' male ' def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __call__ (self, *args, ** kwargs): return self.name,self.price,self.types,self.gender a = A( ' AAA ' ,200, ' A ' ) print (a()) # ('AAA', 200, 'A', 'male') print (A( ' AAA ' ,200, ' A ' )()) # ('AAA', 200, 'A', 'male')
5.__eq__
class A: __instance = False def __init__ (self,name,age,height): self.name = name self.age = age self.height = height def __eq__ (self, other): if self.name == other.name and self.height == other.height: return True else : return False a1 = A( ' Jane ' ,20,55 ) a2 = A( ' Jane ' ,18,55 ) print (a1 == a2) # True
6.__hash__
控制對象中的哈希值和另外一個對象的哈希值是否相等
class A: def __init__ (self,name,age,height): self.name = name self.age = age self.height = height def __hash__ (self): return hash(self.age + self.height) + hash(self.name) a1 = A( ' Jane ' ,20,55 ) a2 = A( ' Jane ' ,18,55 ) print (hash(a1)) # -1393240518857837779 print (hash(a2)) # -1393240518857837781
7.__new__
創(chuàng)建一個對象
class A: height = 18 def __init__ (self): self.name = ' Aane ' self.price = 300 self.types = ' aaa ' def __new__ (cls, *args, ** kwargs): print ( ' 實(shí)例化一個對象... ' ) return object. __new__ (cls, *args, ** kwargs) a = A() # 實(shí)例化一個對象... print (a. __dict__ ) # {'name': 'Aane', 'price': 300, 'types': 'aaa'}
單例模式:限制一個類始終只有一個實(shí)例,因?yàn)橐话銇碇v一個類可以產(chǎn)生無數(shù)個對象
在這里我們創(chuàng)建三個對象并打印它們的內(nèi)存地址可以發(fā)現(xiàn)它們是不同的
class A: def __init__ (self): self.name = ' aaa ' a1 = A() a2 = A() a3 = A() print (a1) # <__main__.A object at 0x00000000025B1D68> print (a2) # <__main__.A object at 0x00000000025CD0F0> print (a3) # <__main__.A object at 0x00000000025CD128>
所以在我們第一次實(shí)例化這個類的時候就創(chuàng)建一個實(shí)例化的對象,那么我們再一次實(shí)例化一個對象的話該如何再去使用之前的實(shí)例化對象呢?
class A: __instance = False def __init__ (self,name,age): self.name = name self.age = age def __new__ (cls,*args,** kwargs): if cls. __instance : return cls. __instance cls. __instance = object. __new__ (A) return cls. __instance a1 = A( ' Jogn ' ,33 ) a2 = A( ' Jane ' ,35 ) a3 = A( ' KKK ' ,55 ) print (a1) # <__main__.A object at 0x000000000217D198> print (a1. __dict__ ) # {'name': 'KKK', 'age': 55} print (a2) # <__main__.A object at 0x000000000217D198> print (a2. __dict__ ) # {'name': 'KKK', 'age': 55} print (a3) # <__main__.A object at 0x000000000217D198> print (a3. __dict__ ) # {'name': 'KKK', 'age': 55} print (id(a1),id(a2),id(a3)) # 41734552 41734552 41734552
8.__del__
析構(gòu)函數(shù):當(dāng)對象結(jié)束其生命周期,如對象所在的函數(shù)已調(diào)用完畢時,系統(tǒng)自動執(zhí)行析構(gòu)函數(shù),它往往用來做"清理善后"的工作。當(dāng)我們直接刪除一個實(shí)例化的對象再去打印它,就會報(bào)錯告訴我們這個對象已經(jīng)不存在了
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types a = A( ' AAA ' ,200, ' A ' ) del a print (a) # NameError: name 'a' is not defined
我們再在A中添加一個__del__方法
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __del__ (self): print ( ' 這個對象%s已被刪除! ' % self.name) del self a = A( ' AAA ' ,200, ' A ' ) del a # 這個對象AAA已被刪除! 這里相當(dāng)于調(diào)用了a.__dict__ print (a) # NameError: name 'a' is not defined
8.__getitem__
模擬字典的方式來拿值
class A: gender = ' male ' def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __getitem__ (self, item): if hasattr(self,item): return getattr(self,item) return ' 沒有找到這個值! ' a = A( ' AAA ' ,200, ' A ' ) print (a[ ' name ' ]) # AAA print (a[ ' price ' ]) # 200 print (a[ ' types ' ]) # A print (a[ ' gender ' ]) # male print (a[ ' sex ' ]) # 沒有找到這個值!
9.__setitem__
模擬字典的方式來設(shè)值
class A: def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __setitem__ (self,key,value): # 重新設(shè)定一個新的值 self. __dict__ [ ' key ' ] = value a = A( ' AAA ' ,200, ' A ' ) print (a. __dict__ ) # {'name': 'AAA', 'price': 200, 'types': 'A'} a. __dict__ [ ' name ' ] = ' BBB ' a. __dict__ [ ' price ' ] = 300 a. __dict__ [ ' types ' ] = ' C ' a. __dict__ [ ' gender ' ] = ' male ' # 增加了一個新的屬性gender print (a. __dict__ ) # {'name': 'BBB', 'price': 300, 'types': 'C', 'gender': 'male'}
10.__delitem__
模擬字典的方式來刪除
class A: gender = ' male ' def __init__ (self,name,price,types): self.name = name self.price = price self.types = types def __delitem__ (self, key): print ( ' %s已刪除! ' % key) del self. __dict__ [key] a = A( ' AAA ' ,200, ' A ' ) del a[ ' name ' ] # name已刪除! del a[ ' price ' ] # price已刪除! print (a. __dict__ ) # {'types': 'A'}
?
問題總結(jié)
1.有很多對象,它們的姓名和性別相同但是年齡不同,如何這種情況的對象去重?
class A: def __init__ (self,name,sex,age): self.name = name self.sex = sex self.age = age def __eq__ (self, other): if self.name == other.name and self.sex == other.sex: return True return False def __hash__ (self): return hash(self.name+ self.sex) a = A( ' Json ' , ' male ' ,26 ) b = A( ' Json ' , ' male ' ,30 ) print (set((a,b))) # set()依賴對象的 __eq__和__hash__ {<__main__.A object at 0x0000000002761DD8>}
2.撲克牌問題
import json from collections import namedtuple Card = namedtuple( ' Card ' ,[ ' rank ' , ' suit ' ]) # rank牌面的大小 suit牌面的花色 class FrenchDeck: ranks = [str(n) for n in range(2,11)] + list( ' JQKA ' ) suits = [ ' 紅心 ' , ' 方塊 ' , ' 梅花 ' , ' 黑桃 ' ] def __init__ (self): self._cards = [Card(rank,suit) for rank in FrenchDeck.ranks for suit in FrenchDeck.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 def __str__ (self): return json.dumps(self._cards,ensure_ascii= False) deck = FrenchDeck() print (deck[10]) # Card(rank='4', suit='梅花') from random import choice print (choice(deck)) # Card(rank='3', suit='方塊') print (choice(deck)) # Card(rank='9', suit='方塊') from random import shuffle shuffle(deck) print (deck[10]) # Card(rank='2', suit='方塊') print (deck) # 打印所有牌色 print (deck[:5]) # [Card(rank='6', suit='梅花'), Card(rank='3', suit='方塊'), Card(rank='10', suit='紅心'),
#Card(rank='9', suit='紅心'), Card(rank='4', suit='方塊')]
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

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