第二十八天:内置函数的讲解:
1.在我们学的数据类型中字典可以通过[]来进行获取value的值,那么对象是否可以通过[]来获取属性和方法吗?
2可以通过getitem获得:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __getitem__(self, item): pass if hasattr(self,item): return self.__dict__[item] f=A('alex','男',10) print(f['name']) #遇到这种格式会直接执行__getitemz函数如果不存在就报错 结果为 alex
3.也可以通过此方法进行对象属性的添加:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __getitem__(self, item): pass if hasattr(self,item): return self.__dict__[item] def __setitem__(self, key, value): self.__dict__[key]=value f=A('alex','男',10) print(f['name']) #遇到这种格式会直接执行__getitemz函数如果不存在就报错 f['hobby']='basktball' #进行属性的添加需要执行setitem函数 print(f.__dict__) 结果为 alex {'name': 'alex', 'sex': '男', 'age': 10, 'hobby': 'basktball'}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __getitem__(self, item): pass if hasattr(self,item): return self.__dict__[item] def __setitem__(self, key, value): self.key=value f=A('alex','男',10) print(f['name']) #遇到这种格式会直接执行__getitemz函数如果不存在就报错 f['hobby']='basktball' #进行属性的添加需要执行setitem函数 print(f.__dict__)
4.删除一个对象中属性的方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __getitem__(self, item): pass if hasattr(self,item): return self.__dict__[item] def __setitem__(self, key, value): self.key=value f=A('alex','男',10) print(f['name']) #遇到这种格式会直接执行__getitemz函数如果不存在就报错 f['hobby']='basktball' #进行属性的添加需要执行setitem函数 print(f.__dict__) del f.name print(f.__dict__) 结果为 alex {'name': 'alex', 'sex': '男', 'age': 10, 'key': 'basktball'} {'sex': '男', 'age': 10, 'key': 'basktball'}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __getitem__(self, item): pass if hasattr(self,item): return self.__dict__[item] def __setitem__(self, key, value): self.key=value def __delitem__(self, key): del self.key f=A('alex','男',10) print(f['name']) #遇到这种格式会直接执行__getitemz函数如果不存在就报错 f['hobby']='basktball' #进行属性的添加需要执行setitem函数 print(f.__dict__) del f['name'] print(f.__dict__) 结果为 alex {'name': 'alex', 'sex': '男', 'age': 10, 'key': 'basktball'} {'name': 'alex', 'sex': '男', 'age': 10}
5.__new__就是构造方法,创建类中的对象,我们每次创建类时自带的self就是通过此方法进行创建的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,x): self.x=x def __new__(cls, *args, **kwargs): print('调用即打印') return object.__new__(cls) a=A('alex') #实例化之后就会执行__new__里面的语句 结果为 调用即打印
6.在对类进行实例化时每一个对象所占用的内存都不同:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self): self.x=1 def __new__(cls, *args, **kwargs): return object.__new__(cls) a=A() #实例化之后就会执行__new__里面的语句 a1=A() a2=A() print(a) print(a1) print(a2) 结果为<__main__.A object at 0x00000280CFCB90F0> <__main__.A object at 0x00000280CFE56A90> <__main__.A object at 0x00000280CFE56AC8>
7.在编程过程中有一种;单例模式:就是说一个类只能实例化一次,当你第一次实力化之后使用这个对象,进行第二次实例化后不在进行创建对象,而是把上一次创建的对象给他,属性也存在,但是可以进行修改,在等第一个值调用时,属性已经变成第二个对象修改的属性了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: __key=False def __init__(self,name,sex): self.name=name self.sex=sex def __new__(cls, *args, **kwargs): if cls.__key: return cls.__key cls.__key=object.__new__(cls) return cls.__key a=A('alex','男') b=A('bin','不想') print(a.name) print(b.name) print(a) print(b) 结果为 bin bin <__main__.A object at 0x0000016E4F4C5F28> <__main__.A object at 0x0000016E4F4C5F28>
8.如果创建两个对象,两个对象中的传入值相同,那么这两个对象相等吗?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name): self.name=name a=A('alex') b=A('alex') print(a==b) 结果为 False
既然他们传入的值都一样结果时false,那么有什么方法能让他们相等吗?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name): self.name=name a=A('alex') b=A('alex') print(hash(a)) print(hash(b)) 结果为 -9223371933925107417 -9223371933925107445
通过hash值我们不难发现他们的内存地址不同,计算机判断是否相等就是看内存地址是否相同,如果相同就为True,通过下面方法就可以让上述结果为True
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name): self.name=name def __hash__(self): return hash(self.name) #会跟据自己的定义来判断某个对象的hash值 a=A('alex') b=A('alex') print(hash(a)) print(hash(b)) print(a==b) 结果为 7807086709747762995 7807086709747762995 False
通过这一步可以让其hash值相等,再通过下面程序就可以让他们相等:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name): self.name=name def __hash__(self): return hash(self.name) #会跟据自己的定义来判断某个对象的hash值 def __eq__(self, other): # if self.name==other.name:#让hash值相等的对象返回True return True return False a=A('alex') b=A('alex') print(hash(a)) print(hash(b)) print(a==b) 结果为 1822651601806597939 1822651601806597939 True
9.蜘蛛纸牌游戏:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from collections import namedtuple import json Card=namedtuple('Card',['rank','suit']) class FrancDeck: ranks=[str(n) for n in range(2,11)]+list('JQKA') suits=['红心','方片','梅花','黑桃'] def __init__(self): self.card=[Card(rank,suit) for rank in FrancDeck.ranks for suit in FrancDeck.suits] def __len__(self): return len(self.card) def __getitem__(self, item): return self.card[item] #需要返回值 def __setitem__(self, key, value): self.card[key]=value #不需要返回值 def __str__(self): return json.dumps(self.card,ensure_ascii=False) deck=FrancDeck() print(deck[0]) from random import choice print(choice(deck)) from random import shuffle shuffle (deck) print(deck) 结果为 Card(rank='2', suit='红心') Card(rank='A', suit='黑桃') [["10", "方片"], ["8", "红心"], ["8", "黑桃"], ["K", "红心"], ["4", "红心"], ["4", "黑桃"], ["9", "黑桃"], ["6", "红心"], ["10", "梅花"], ["10", "红心"], ["2", "黑桃"], ["3", "方片"], ["7", "梅花"], ["3", "红心"], ["9", "方片"], ["7", "红心"], ["7", "黑桃"], ["J", "方片"], ["7", "方片"], ["K", "方片"], ["Q", "红心"], ["9", "梅花"], ["J", "梅花"], ["K", "梅花"], ["2", "方片"], ["3", "梅花"], ["J", "红心"], ["A", "方片"], ["J", "黑桃"], ["2", "红心"], ["3", "黑桃"], ["5", "黑桃"], ["10", "黑桃"], ["6", "梅花"], ["8", "方片"], ["6", "方片"], ["6", "黑桃"], ["5", "红心"], ["5", "梅花"], ["A", "梅花"], ["Q", "方片"], ["9", "红心"], ["2", "梅花"], ["4", "梅花"], ["A", "黑桃"], ["Q", "梅花"], ["5", "方片"], ["4", "方片"], ["8", "梅花"], ["Q", "黑桃"], ["A", "红心"], ["K", "黑桃"]]
10.怎么让姓名性别相同,年龄不同的两个对象合并成一个:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __hash__(self): return hash(self.name+self.sex) def __eq__(self, other): if self.name==other.name and self.name==other.name: return True return False a=A('alex','男',14) b=A('alex','男',55) c=set((a,b)) print(c) 结果为 {<__main__.A object at 0x00000205E34790F0>}
11.进行登陆密码的加密可以使用算法:hashlib
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib passwd='alex123' md5=hashlib.md5() md5.update(bytes(passwd,encoding='utf-8'))#没有返回值,而且传入的数据必须时bytes类型 ret=md5.hexdigest() #有返回值 #进行16进制的转换和消化工作 print(ret) 结果为 b75bd008d5fecb1f50cf026532e8ae67
12.算法的介绍:
13.对于算法的一些总结:
不管算法有多么的不同,摘要的功能始终不变
对于相同的字符串使用同一个算法进行摘要时,得到地值使用是不变的
使用不同地算法对相同地字符进行摘要时,得到的值应该不同
14.使用sha3算法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib passwd='alex123' sha=hashlib.sha3_512() sha.update(bytes(passwd,encoding='utf-8'))#没有返回值,而且传入的数据必须时bytes类型 ret=sha.hexdigest() #有返回值 #进行16进制的转换和消化工作 print(ret) 结果为 2975f0b0c557a9fd52742bde0df89227e05119293f2319bd6ff2b1f3fc1236e5a2f93360c857b057f12d3e7da58233817957f5e598a43bb234545a71f4a94679
15.sha中有多种算法,随着算法复杂程度的增加,算法的空间成本(内存)和时间成本都会增加
16.写一个用户登陆程序:包括:1.用户的注册,2.用户输入用户名,用户输入 密码。明文的密码进行摘要 拿到一个密文密码 写入文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib def func1(): print('欢迎进入创建用户界面') with open('studentinfo','a',encoding='utf-8') as f: user=input('请输入用户名') pass_wd=input('请输入用户的密码:') md5=hashlib.md5() md5.update(bytes(pass_wd,encoding='utf-8')) ret=md5.hexdigest() f.write(user+'|'+ret+'\n') print('创建成功') def func2(): print('欢迎进入登陆界面') with open('studentinfo',encoding='utf-8')as f: user=input('请输入用户名') pass_wd=input('请输入用户的密码:') md5=hashlib.md5() md5.update(bytes(pass_wd,encoding='utf-8')) ret=md5.hexdigest() for i in f: i=i.strip('\n') username,pass_wd1=i.split('|') if username==user and pass_wd1==ret: print('等录成功') return True print('登陆失败') num=int(input('''欢迎进入此界面: 选择2进入登陆界面 选择1进入创建账号界面''')) if num==1: func1() elif num==2: func2() else: print('你输入错误') 结果为 欢迎进入此界面: 选择2进入登陆界面 选择1进入创建账号界面2 欢迎进入登陆界面 请输入用户名1234 请输入用户的密码:1234 等录成功
19.md5如果进行简单加密有时候是可以通过网上进行破解的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib md5=hashlib.md5() md5.update(b'1234') ret=md5.hexdigest() print(ret) 结果为 81dc9bdb52d04dc20036dbd8313ed055
使用md5破解的结果为
20.针对这种现象我们采用的第一种方法为静态加盐法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib md5=hashlib.md5(bytes('salt',encoding='utf-8')) #进行md5加盐操作 md5.update(b'1234') ret=md5.hexdigest() print(ret) 结果为 a6d4f0a9c109cd24eacb88e75e5be690
使用这种方法破解是增加了苦难但是如果有人破解一次之后就可以进行测试得到正确与否
为了解决此问题,我们可以采用动态加盐的方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import random import hashlib salt=input('请输入加密的内容:') salt=random.sample(salt,len(salt)-2) salt=''.join(salt) md5=hashlib.md5(bytes(salt,encoding='utf-8')) #进行md5加盐操作 md5.update(b'1234') ret=md5.hexdigest() print(ret) 结果为 请输入加密的内容:dfjkljkfdj 621370e3cb535492381e4d0506361e59
21.文件的一致性校验,在进行文件的一致性校验是不需要加盐,文件的更新可以进行多次:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib md5=hashlib.md5() md5.update(b'qwertyuiop123456') ret=md5.hexdigest() print(ret) md4=hashlib.md5() md4.update(b'qwert') md4.update(b'yuiop') md4.update(b'123456') ret1=md4.hexdigest() print(ret1) 结果为 8e523cd5ef475ab6834f0598f4a502f8 8e523cd5ef475ab6834f0598f4a502f8