1,繼續上一小節,講解雙下內置方法,雙下getitem,setitem,delitem方法,是對象能夠像字典同樣的來訪問屬性程序員
# 普通的字典是像下面這樣操做的 dic = {'k' : 'v'} dic['k'] = 'v' class Foo: def __init__(self,name,age,sex): self.name = name self.age = age self.sex =sex def __getitem__(self, item): if hasattr(self,item): return self.__dict__[item] def __setitem__(self, key, value): self.__dict__[key] = value def __delitem__(self, key): del self.__dict__[key] def __delattr__(self, item): print('del obj.key時,我執行') self.__dict__.pop(item) # 只要想像字典同樣的來操做,就必須實現這幾個函數 f = Foo('lisa',100,'女') print(f['name']) f['name'] = 'lucy' f['hobby'] = 'running' print(f['name']) print(f.name,f['name']) del f.hobby # object原生支持 __delattr__ object 原生實現的 # del f['hobby'] # 經過本身來實現的 # print(f.hobby)
2,__new__雙下new方法面試
# __init__ 初始化方法 # __new__ 構造方法:建立一個對象 class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls, *args, **kwargs): # 運行new的時候,理論上來講來尚未self,因此第一個參數是cls, # 可是若是第一個參數修改成self也是能夠的,我還不曉得爲什麼 print('in new function') return object.__new__(A,*args,**kwargs) # 我本身定義的new方法是沒有辦法本身常見類的,須要藉助於父類的new方法來建立 a = A() # 運行結果: # in new function # in init function
3,設計模式一共有23種,單例模式,很著名的一種模式,他已經傳了好多年了,單例模式很適合在雙下New這個地方講,一個類始終只有一個實例,算法
a1 = A() a2 = A() a3 = A() print(a1) print(a2) print(a3) # <__main__.A object at 0x10514cf60> # <__main__.A object at 0x105211198> # <__main__.A object at 0x1052111d0> # 若是不是單例模式的話,每一個新建的對象都佔用新的地址空間
4,單例模式,限制你的類從始至終只能有一個實例,當你第一次實例化這個類的時候,就建立一個實例化的對象,當你以後再來實例化的時候,就用以前建立的對象編程
class A: __instanse = False # 我不但願別人來用 def __init__(self,name,age): self.name = name self.age = age def __new__(cls, *args, **kwargs): if cls.__instanse: return cls.__instanse cls.__instanse = object.__new__(A) return cls.__instanse egon = A('egg',38) nezha = A('nezha',25) print(egon) print(nezha) # <__main__.A object at 0x10d5b32b0> # <__main__.A object at 0x10d5b32b0> egon.cloth = '小花襖' print(nezha.name) print(egon.name) print(nezha.cloth) # nezha # nezha # 小花襖 # 全部人都在操做一個對象,這就是單例模式,提到單例,必定要提new
5,雙下new方法是須要記的,基本面試都會考,只要面試官稍微難纏一點,必定會考的json
6,雙下eq方法,設計模式
class A: def __init__(self,name): self.name = name def __eq__(self, other): # 這個地方能夠定製須要比較的內容,這兒不寫返回值的話,就不返回的 if self.name ==other.name: return True ob1 = A('egg') ob2 = A('egg') print(ob1 == ob2) # 實現了雙下eq就是真,沒有實現就是假 print(ob1 is ob2) print(ob1) print(ob2) # <__main__.A object at 0x10eda9198> # <__main__.A object at 0x10eda91d0> # 這兒不同,因此is是false
7,雙下hash 方法服務器
# hash() __hash__ class A: def __init__(self,name): self.name = name a = A('egon') b = A('egon') print(hash(a)) print(hash(b)) # 默認根據對象的內存地址去進行hash # 273542713 # -9223372036581188387
8,定製hash 方法網絡
# 假如但願屬性值相同的時候,哈希值也相同,那麼就須要定製__hash__函數 class B: def __init__(self,name,gender): self.name = name self.gender = gender def __hash__(self): return hash(self.name+self.gender) a = B('lisa','female') b = B('lisa','female') c = B('mike','male') print(hash(a)) print(hash(b)) print(hash(c)) # -2954662424006399276 # -2954662424006399276 # -5502858135697491787
9,面向對象的進階,雙下內置方法的實例app
from collections import namedtuple Card = namedtuple('card',['rank','suit']) # rank牌面的大小,suit是花色,藉助於nametuple建立了一個只有屬性的類 c1 = Card(2,'紅心') # 實例化 print(c1) print(c1.suit)
10,上接第九步,choice 依賴內置的len,shuffle依賴內置的setitem方法dom
import json from collections import namedtuple Card = namedtuple('Card',['rank','suit']) 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 def __str__(self): # 由於返回的必須是字符串,因此須要序列化 return json.dumps(self._cards,ensure_ascii=False) deck = FranchDeck() print(deck[3]) from random import choice print(choice(deck)) # choice依賴內置的len方法 print(choice(deck)) from random import shuffle # shuffle方法依賴內置的setitem方法 shuffle(deck) print(deck[10]) print(deck) print(deck._cards[:5]) # 也實現了切片
11,內置函數 內置模塊,內置的基礎數據類型 < --- >類的內置方法
== eq
len __len__
12, set函數依賴於hash 和len方法
# 根據名字和性別去重,年齡不在意 class A: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age def __hash__(self): # 只有hash 函數能夠用set了,可是結果仍是不對 return hash(self.name + self.sex) def __eq__(self, other): if self.name == other.name and self.sex == other.sex: return True else:return False a = A('egg','男', 38) b = A('egg','男', 37) print(set((a,b))) # 依賴對象的hash 和 eq方法,這種狀況就是遇到一個解決一個 # {<__main__.A object at 0x10d099588>, <__main__.A object at 0x10d0995c0>} # 很明顯沒有去重,可是老師當時跑的時候,說報了一個錯,就是unhashbale ,因此總是想到這個set 函數是依賴與雙下哈市
13,一道面試題
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 self.sex == other.sex:return True p_lst = [] for i in range(84): p_lst.append(Person('lisa',i,'male')) print(p_lst) print(set(p_lst)) # 這個地方他判斷相等的時候,不會去考慮中間的年領,因此後面的都會被認爲是相等的 # set函數依賴對象的hash eq 方法
14,hashlib,這個模塊,只要你是一個程序員,就會一直伴着你,如今學習用,之後登錄用,將來學習socket的時候還會用的,網絡編程也會用,揭開hashlib的什麼面紗。
# 寫登錄認證的時候,會有一個文件保存用戶名密碼,萬一文件丟了,怎麼辦?比方說你是支付寶 # 加密 確定對應一個解密功能,可是咱們如今這個算法他解不了,只能加密。因此咱們給了他一個新名字,叫作摘要算法 # hashlib 能幹的事 # 兩個字符串,500萬個字,即便有一個字符不同,結果也不同,計算過程咱們先不關係,分別進行摘要,結果就是不同的 import hashlib # 提供摘要算法的模塊 md5 = hashlib.md5() md5.update(b'alex3714') # 必須是bytes類型的 print(md5.hexdigest()) # aee949757a2e698417463d47acac93df,若是我文件裏面存的是這一串數字,就不怕丟了 # 摘要算法對同一個字符串進行摘要,結果永遠不會變化的,不僅是同一次運行,屢次結果也是固定的
15,總結:無論算法多麼不一樣,摘要的功能始終不變;對於相同的字符串使用同一個算法進行摘要,獲得的值老是不變的;使用不一樣的算法,對相同的字符串進行摘要,獲得的值應該不一樣;無論使用什麼算法,hashlib的方式永遠不變。
16,sha 算法
# 調用方法和md5方法是同樣的,sha 算法隨着算法複雜成都的增長,我摘要的時間成本空間成本都有所增長 sha = hashlib.sha1() sha.update(b'alex3714') print(sha.hexdigest()) sha = hashlib.sha3_224() sha.update(b'alex3714') print(sha.hexdigest()) sha = hashlib.sha3_512() sha.update(b'alex3714') print(sha.hexdigest())
17,從此全部的密碼,都應該是密文存儲的,不能明文顯示,hashlib裏面的摘要算法有不少種,md5是最核心,用的最多的。
18,摘要算法的用處:密碼的密文存儲,文件的一致性檢查,不少網站下載的時候也會有那種須要檢查,他怕你下載時不完整,在最右邊,下載的時候咱們會檢查咱們下載的文件和遠程服務器的文件是否一致;兩臺機器上的兩個文件,想檢查這兩個文件是否相等。好比500臺服務器要求資料是同樣的,這時候會用到一致性校驗
19,