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,