一.類中的裝飾器的使用:property,classmethod,staticmethod,python
property的使用:property 的做用是講一個類的函數屬性裝飾成對象的一個數據屬性,可以直接被對象.方法名 調用,不用去經過加()的方式調用。面試
當property去裝飾一個類的函數方法時,與setattr,delattr 共用時,@name.setattr @name.delattr 前面的前綴必須相同json
property的本質就實現了 get,set,del 三個方法dom
class Foo: @property def AAA(self): print('get的時候運行我啊') @AAA.setter def AAA(self,value): print('set的時候運行我啊') @AAA.deleter def AAA(self): print('delete的時候運行我啊') #只有在屬性AAA定義property後才能定義AAA.setter,AAA.deleter f1=Foo() f1.AAA f1.AAA='aaa' del f1.AAA
class Goods: def __init__(self): # 原價 self.original_price = 100 # 折扣 self.discount = 0.8 @property def price(self): # 實際價格 = 原價 * 折扣 new_price = self.original_price * self.discount return new_price @price.setter def price(self, value): self.original_price = value @price.deleter def price(self): del self.original_price obj = Goods() obj.price # 獲取商品價格 obj.price = 200 # 修改商品原價 print(obj.price) del obj.price # 刪除商品原價
#實現類型檢測功能 #第一關: class People: def __init__(self,name): self.name=name @property def name(self): return self.name # p1=People('alex') #property自動實現了set和get方法屬於數據描述符,比實例屬性優先級高,因此你這面寫會觸發property內置的set,拋出異常 #第二關:修訂版 class People: def __init__(self,name): self.name=name #實例化就觸發property @property def name(self): # return self.name #無限遞歸 print('get------>') return self.DouNiWan @name.setter def name(self,value): print('set------>') self.DouNiWan=value @name.deleter def name(self): print('delete------>') del self.DouNiWan p1=People('alex') #self.name實際是存放到self.DouNiWan裏 print(p1.name) print(p1.name) print(p1.name) print(p1.__dict__) p1.name='egon' print(p1.__dict__) del p1.name print(p1.__dict__) #第三關:加上類型檢查 class People: def __init__(self,name): self.name=name #實例化就觸發property @property #當property將一個類的函數屬性定義與__init__中的名字同樣時, # 因爲property的優先級更高會優先執行property,而property必須經過setter方法去設置對象的新的屬性 def name(self): # return self.name #無限遞歸 print('get------>') return self.DouNiWan @name.setter def name(self,value): print('set------>') if not isinstance(value,str): raise TypeError('必須是字符串類型') self.DouNiWan=value @name.deleter def name(self): print('delete------>') del self.DouNiWan p1=People('alex') #self.name實際是存放到self.DouNiWan裏 p1.name=1 案例二
2.classmethod:ide
class Classmethod_Demo(): role = 'dog' @classmethod #做用及時統一了對象和類調用方法的方式,都是經過同一種方式去調用 def func(cls): print(cls.role) def func1(self): print(self.role) Classmethod_Demo.func() Classmethod_Demo.func1() #必須傳一個參數才能實現類調用去下的函數屬性。
3.staticmethod:函數
class Staticmethod_Demo(): role = 'dog' @staticmethod #做用就是當成普通的函數方法使用,類與對象都不用傳參數 def func():#注意不自動傳self值了 print("當普通方法用") Staticmethod_Demo.func() s =Staticmethod_Demo() s.func()
#1...__new__方法的使用:就是構造方法,建立一個對象 #單例模式:一個類從始至終只實例化一個對象,單例模式的模擬 """ class A: __issingle = False def __init__(self,name,age): print('執行的init方法') self.name = name self.age = age def __new__(cls, *args, **kwargs): print('執行的new方法') if cls.__issingle: return cls.__issingle cls.__issingle = object.__new__(cls) return cls.__issingle a1 = A('yuan',18) a2 = A('rong',18) a1.id = '001' print(id(a1),id(a2)) #在內存中的id都是相同的,實際上操做的是同一個對象 print(a1.name,a2.name) print(a1.age,a2.age) print(a1.id,a2.id)# a2對象而言並無id屬性,用的就是a1.id,實際上就是操做同一個實例化對象 """
#.2.item系列的方法: 字典類型的數據就是經過item的內置方法去建立和操做的。 """ class A: def __init__(self,name): self.name = name def __getitem__(self, item): print('執行的getitem方法') return self.__dict__[item] def __setitem__(self, key, value): print('執行的setitem方法') self.__dict__[key] = value return self.__dict__ def __delitem__(self, key): print('執行的delitem方法') del self.__dict__[key] def __delattr__(self, item): print('執行的delattr方法') del self.__dict__[item] pass a = A('yuan') # print(a.name) # print(a['name']) # a.age = 18 a['age'] = 19 print(a.age) del a['age'] #若是執行del 語句,會執行__delitem__方法, del a.age # 若是執行del 語句,會執行__delattr__方法,就是兩種刪除的方法不同執行調用類的方法就不同, #若是即沒有delitem和delattr方法就會去執行父類中的方法,都沒有就執行object中的delattr方法 print(a.age) """
#__str__:能夠控制對象的屬性詳細的說明的方法,當類中沒有__str__方法時候,會調用__repr__ """ class A: def __str__(self): print('這是A類本身的__str__方法') return 'A' #能夠在這裏面定義本身想要定義返回的信息 a = A() print(a)#當類中沒有定義本身的__str__方法時,會去object中找__str__方法,會返回這個對象的內存地址 #而當類中有本身定義的__str__方法時會優先執行執行的__str__方法,print一個對象的時候會自動執行該對象下的 #__str__方法,該對象的類中沒有,找父類,父類沒有,找object中。 print(str(a)) %s,str() 就是調用類下的__str__方法 """
# __repr__:將對象的原始數據格式打印到終端,當類中沒有__repr__時候,不能調用__str__方法。 #%r repr() 就是調用了類下的__repr__方法 """ class A: def __init__(self,name,age): self.name = name self.age = age def __repr__(self): print('這是本身的repr方法') return str(self.__dict__) #跟str的返回值同樣,必須返回一個字符串 a = A('yuan',18) print('%r'% a)#至關於調用_repr__方法 print(repr(a)) """
#__del__:析構函數 # 做用通常是在文件打開後作的收尾工做,與內置的垃圾回收裝置相關 """ import time class A: def __del__(self): print('執行本身的del方法') a = A() #若是一個程序代碼都執行完以後,會自動執行對象中的__del__方法,即沒有手動 # del 對象也會執行__del__裏面的代碼,與python中的垃圾回收裝備有關聯關係。 time.sleep(3) """
#__call__:當一個對象被調用的時候會自動執行該對象下的__call__方法 """ class A: pass # def __call__(self, *args, **kwargs): # print('執行本身的call方法') a = A() #至關於執行了 a() ,就是自動執行該對象下的__call__方法 #若是沒有該對象下沒有__call__方法,及時提示報錯,只會從該對象的父類中查找是否有 #__call__方法,不會去object中找尋__call__方法, a() """
#__eq__:判斷兩個對象是否相等,默認的是比較兩個對象的內存地址,若是須要從新 #定製本身的判斷相等的方法,只須要在__eq__中定義本身的方法 """ class A: def __init__(self,name): self.name = name def __eq__(self, other): if self.name == other.name: return True a1 = A('yuan') a2 = A('yuan') print(a1 == a2) # 若是沒有定製本身的__eq__,就默認執行object中的__eq__,默認比較兩個對象的內存地址 """
#__hash__:得到對象的hash值 """ a = 10 a1 ='abc' l = [1,2,3] print(hash(a)) print(hash(a1)) print(hash(l)) #可變數據類型是不能夠被hash的 """
#內置方法的實例,使用內置方法會使代碼更加的優美 #1 實例一 模擬一副撲克牌 """ import random import json from collections import namedtuple from random import shuffle Card = namedtuple('Card',['rank','suits']) class Poke: ranks = [str(rank) for rank in range(1,11)] + list('JQKA') suits = ['紅心','黑桃','方塊','梅花'] def __init__(self): self.__cards = [Card(rank,suit) for rank in Poke.ranks for suit in Poke.suits] def __getitem__(self, item): #想要經過[]的形式去取值,就要設置本身的__len__方法, return self.__cards[item] def __len__(self): return len(self.__cards) def __setitem__(self, key, value): self.__cards[key] = value def __str__(self):#想要定義本身的__str__就必需要定義本身的__setitem__方法 return json.dumps(self.__cards,ensure_ascii=False)#__str__可視化要進行json序列化一下 c = Poke() print(c[0]) #取得是第一張牌 print(c[0][0])#取得是第一張牌的數字 print(c[0][1])#取得是第一張牌的花色 print(random.choice(c)) print(c) shuffle(c)#完成洗牌操做 print(c) print(c[:5])#直接去經過__getitem__方法去實現的,相似於用字典的關鍵字去取值同樣 """
#2.實例一 一道面試題 #1.有100的對象,名字和性別相同,但年齡不一樣 class A: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age def __eq__(self, other):#加了__eq__才能完成去重,內置判斷去重不是簡單的判斷hash,仍是與__eq__相關聯 if self.name == other.name and self.sex == other.sex: return True return False def __hash__(self): return hash(self.name + self.sex) a1 = A('yuan','male',18) a2 = A('yuan','male',18) print(set((a1,a2)))# 仍是沒有完成去重,加了__hash__和__eq__才能完成去重 """
a1 = A('yuan','male',18) a2 = A('yuan','male',19) print(a1) print(a2) print(a2.__dict__) res =set((a2,a1))# 仍是沒有完成去重,加了__hash__和__eq__才能完成去重 print(list(res)[0].__dict__) #完成了去重,獲得去重後的值