Python全栈(第一期)Day28

今日主要内容:
面向对象进阶
item系列
__new__方法
__eq__方法
__hash__方法

一,面向对象进阶

1,item系列

# item 系列:
# 从此操作对象就和操作字典一样
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]

f = Foo('egon', 38, '男')
print(f['name'])
f['hobby'] = '男'
print(f.hobby, f['hobby'])
# del f.hobby      # 删除方法一:object 原生支持: ---> __delattr__
del f['hobby']     # 删除方法二: 通过自己实现的,需要自己写: ----> __delitem__
print(f.__dict__)

输出结果:
egon
男 男
{‘name’: ‘egon’, ‘age’: 38, ‘sex’: ‘男’}

2,__new__方法

# new 就是构建self的那个机制!

# 可以看到下面这个例子中a1 and a2 and a3 不是一个地址!
class A:
    def __init__(self):
        self.x = 1
        print('in init function')
    def __new__(cls, *args, **kwargs):
        print('in new function')
        return object.__new__(A, *args, **kwargs)

a1 = A()
a2 = A()
a3 = A()
print(a1)
print(a2)
print(a3)


print('下一个例子!')


# 设计模式(算法导论 + 设计模式)
# 23种
# 著名的设计模式:单例模式
    # 含义:一个类始终只有一个实例。
    # 当你第一次实例化这个类的时候 就创建一个实例化的对象
    # 当你之后再来实例化的时候 就用之前创建的对象


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__(cls)
        return cls.__instance

egon = A('egg', 38)
egon.cloth = '小花袄'

nezha = A('nazha', 25)
print(nezha)
print(egon)
print(nezha.name)
print(egon.name)
print(nezha.cloth)

输出结果:
in new function
in init function
in new function
in init function
in new function
in init function
<main.A object at 0x0000025DC7410710>
<main.A object at 0x0000025DC74102E8>
<main.A object at 0x0000025DC844CD30>
下一个例子!
<main.A object at 0x0000025DC815F240>
<main.A object at 0x0000025DC815F240>
nazha
nazha
小花袄

2,eq 方法

# __eq__ 方法
class A:
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        if self.__dict__ == other.__dict__:
            return True
        else:
            return False

ob1 = A('faker')
ob2 = A('egg')
ob3 = A('egg')
print(ob1 == ob2)
print(ob2 == ob3)
# 如果没有__eq__方法:比较内存地址;如果有这个方法,那么就会按照我们设定的比较方法。

输出结果:
False
True

3,__hash__方法

# hash()   #__hash__
# 可以通过自己写函数,控制输出的哈希值

class A:
    def __init__(self, name, sex):
        self.name = name
        self.sex = sex
    def __hash__(self):
        return hash(self.name+self.sex)

a = A('egon', '男')
b = A('egon', '女')
print(hash(a))
print(hash(b))

输出结果:
-2320217479882720496
-3197586383191713367

4,实战一

import json
from collections import namedtuple
Card = namedtuple('Card', ['rank', 'suit'])   # rank 牌面的大小 suit牌面的花色
# c1 = Card(2, '红心')  # 其实这相当于这是一个只有属性没有方法的类
# print(c1)


class FranchDeck:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')   # 2-A
    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[10])   # 通过索引取出self._cards 中的牌
from random import choice
print(choice(deck))  # 抽排

from random import shuffle  # 洗牌
shuffle(deck)
print(deck[10])
print(deck[:2])

输出结果:
Card(rank=‘4’, suit=‘梅花’)
Card(rank=‘J’, suit=‘黑桃’)
Card(rank=‘2’, suit=‘梅花’)
[Card(rank=‘4’, suit=‘方板’), Card(rank=‘K’, suit=‘黑桃’)]

5,实战二

# 内置函数 内置的模块 内置的基础类型 < --- >类的内置方法
# ==    __eq__
# len() __len__

# 100 名字 和 性别 年龄不同,只根据其中一个或者多个特征是否相同 实现去重
# 我们一般会想到:set
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):  # 本例中选取名字 and 性别
        return hash(self.name + self.sex)

a = A('egg', '男', 38)
b = A('egg', '男', 37)
print(set((a, b)))   # unhashable


# 得到结论:set 依赖对象的 hash and eq  两个内置方法

输出结果:
{<main.A object at 0x00000258671A9EF0>}

二,摘要算法

1,初始摘要算法

# 登录认证
# 加密 --> 解密
# 摘要算法: 可以实现密文存储
# 两个字符串 :


import hashlib   # 提供摘要算法的模块
md5 = hashlib.md5()  # md5 只是摘要算法 中的一个,md5是用的最多的一个。
md5.update(b'nanshan')
print(md5.hexdigest())  # 拿到摘要算法的结果
#e5df6237985ca15085e86f70073415cc:对同一个字符串的摘要算法结果,永远都不会变。


# 不管算法多么不同,摘要的功能始终不变
# 对于相同的字符串使用同一个算法进行摘要,得到的值总是不变的
# 使用不同算法对相同的字符串进行摘要,得到的值应该不同
# 不管使用什么算法,hashlib的方式永远不变

输出结果:
e5df6237985ca15085e86f70073415cc

2,应用

# sha算法(另一种):随着 算法复杂程度的增加 我摘要的时间成本空间成本都会增加
# 摘要算法功能:
# 1.密码的密文存储
# 2.文件的一致性验证
        # 在下载的时候 检查我们下载的文件和远程服务器上的文件是否一致
        # 两台机器上的两个文件 你想检查这两个文件是否相等




# 第一步:用户注册
#   用户输入用户名
#   用户输入密码
#   明文的密码进行摘要 拿到一个密文的密码
#   写入文件

# 第二步:用户的登录
import hashlib
usr = input('username :')
pwd = input('password : ')
with open('userinfo') as f:
    for line in f:
        user, passwd, role = line.split('|')
        md5 = hashlib.md5()
        md5.update(bytes(pwd, encoding='utf-8'))
        md5_pwd = md5.hexdigest()
        if usr == user and md5_pwd == passwd:
            print('登录成功')

3,加盐

# 加盐:解决md5的被破解问题
import hashlib   # 提供摘要算法的模块
md5 = hashlib.md5(bytes('盐', encoding='utf-8'))
# md5 = hashlib.md5()
md5.update(b'123456')
print(md5.hexdigest())

输出结果;
970d52d48082f3fb0c59d5611d25ec1e

4,动态加盐

# 动态加盐
# 用户名;密码
# 使用用户名的一部分或者直接使用整个用户名作为盐
import hashlib
md5 = hashlib.md5(bytes('盐', encoding='utf-8') + b'520')
# md5 = hashlib.md5()
md5.update(b'123456')
print(md5.hexdigest())

输出结果:
8eafddd9e6fad5cb74a87d981eb27a04

5,知识点补充

# 补充:可以进行多次进行摘要算法。
# 同时,和对'alex3714' 一次性进行摘要得到的结果是相同的。
import hashlib
md5 = hashlib.md5()
md5.update(b'alex')
md5.update(b'3714')
print(md5.hexdigest())

输出结果:
aee949757a2e698417463d47acac93df

猜你喜欢

转载自blog.csdn.net/qq_42615032/article/details/86574163