day018反射及区分函数和方法,md5加密

本节主要内容:

1. isinstance, type, issubclass 三个面向对象的内置函数
2. 区分函数和方法
3. 反射(重点)
4. md5加密(数字签名、电子签章的原理)

一、三个关于面向对象的内置函数

1、issubclass()

作用:判断xxx是否是yyy类型的子类
object是所有类的根,是面向对象的祖宗

fe:

class Foo(object):
    pass

class Bar(Foo):
    pass

class FooBar(Bar):
    pass

print(issubclass(Bar, Foo)) # True
print(issubclass(Foo, Bar)) # False
print(issubclass(FooBar, Foo)) # True 可以隔代判断


print(issubclass(Foo, object))
print(issubclass(Bar, object))
print(issubclass(FooBar, object))

object是所有类的根. 面向对象的祖宗

2、type

作用: 精准的返回该对象的类型

fe1:判断数据类型

print(type("你好")) # <class 'str'> 返回该对象的数据类型

class Animal:
    pass

class Cat(Animal):
    pass

c = Cat()

print(type(c)) # 可以精准的返回数据类型

fe2: 计算a+b的结果 数学运算

def cul(a, b):
    if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float):
        return a + b
    else:
        print("不行. 不能帮你计算")

print(cul(10, "胡辣汤"))

3、isinstance()

作用:判断xxx是否是yyy类型的数据,包括父类
只能向上

fe1:

class Animal:
    pass

class cat(Animal):
    pass

class BoSiCat(cat):
    pass

c = cat()

print(isinstance(c, Animal))  # 判断这个对象是否是 xxx的一种,包括父类

print(isinstance(c, BoSiCat))  # 报错,只能向上判断,不能向下

print(type(c, Animal))  # 只能精准判断属于cat, 不能找到父类

fe2: 判断是否是迭代器类型的数据

from collections import Iterator # 引入
lst = []
it = lst.__iter__() # list_iterator
print(isinstance(it, Iterator)) # True

二、区分函数和方法(面向对象中)

1、野路子判断

通过打印

fe1:

查看类中的方法和函数
class Car:
    def run(self): # 实例方法
        print("我是车, 我会跑")

    @staticmethod
    def cul():
        print("我会计算")

    @classmethod
    def jump(cls):
        print("我会jump")

# 实例方法 <bound method Car.run of <__main__.Car object at 0x000001E9166B73C8>>
c = Car()
1
"str"
print(c.run) # <bound method Car.run of <__main__.Car object at 0x000001E9166B73C8>>
Car.run(c) #  通过类名也可以访问实例方法. 不要这么干
print(Car.run) # <function Car.run at 0x000002454C748AE8>
# 实例方法:
#     1. 用对象.方法   方法
#     2. 类名.方法     函数
#
# 静态方法
#    都是函数
print(c.cul) # <function Car.cul at 0x0000024BA2658BF8>
print(Car.cul) # <function Car.cul at 0x0000024BA2658BF8>

# 类方法都是方法
print(c.jump) # <bound method Car.jump of <class '__main__.Car'>>
print(Car.jump) # <bound method Car.jump of <class '__main__.Car'>>
# 对象.方法
# 万事万物皆为对象
# 我们写的类. 也是对象.  可以创建对象

2、官方的办法

用程序来分辨
from types import FunctionType, MethodType
print(isinstance(xx, FunctionType)))
print(isinstance(xx, MethodType)))
所有的方法都是MethodType
所有的函数都是FunctionType

fe:

from types import FunctionType, MethodType

class Car:
    def run(self): # 实例方法
        print("我是车, 我会跑")

    @staticmethod
    def cul():
        print("我会计算")

    @classmethod
    def jump(cls):
        print("我会jump")

# 实例方法:
#     1. 用对象.方法   方法
#     2. 类名.方法     函数
c = Car()
# print(isinstance(c.run, FunctionType)) # False
# print(isinstance(Car.run, FunctionType)) # True
# print(isinstance(c.run, MethodType)) # True
# print(isinstance(Car.run, MethodType)) # False

# 静态方法 都是函数
# print(isinstance(c.cul, FunctionType)) # True
# print(isinstance(Car.cul, FunctionType)) # True
# print(isinstance(c.cul, MethodType)) # False
# print(isinstance(Car.cul, MethodType)) # False

# 类方法都是方法
print(isinstance(c.jump, FunctionType)) # False
print(isinstance(Car.jump, FunctionType)) # False
print(isinstance(c.jump, MethodType)) # True
print(isinstance(Car.jump, MethodType)) # True

# FunctionType:所有的函数
# MethodType: 所有的方法

3、区分函数和方法的结论

1. 实例方法:

用类名访问. 函数
用对象访问. 方法

2. 静态方法

都是函数

3. 类方法

都是方法

三、反射

常用(掌握):
hasattr(对象, 属性(字符串))  判断是否有这个属性,返回True或者False, # 判断 xxx中是否有 xxx
getattr(对象, 属性(字符串))  从对象中获取到xxx属性
不太常用:
setattr(对象, 属性, 值)     设置,原来有就修改,没有就修改
delattr(对象, 属性)         从对象中删除xxx属性

fe1:

反射
import master  # 引入模块,在自己这边开辟内存,存放master模块(一个写好的py文件)

def chi():
    print("大牛说的不对,我要换")

setattr(master, "chi", chi) # 给xxx模块的chi替换成我的chi,跟字典一样,在自己这边的内存,修改函数
setattr(master, "haha", chi) # 没有就新增,新增haha函数

delattr(master, "name") # 删除"name"这个变量
print(master.name)

setattr(master, "wife", "皮蛋")  # 有就是修改,没有就新增
print(master.wife)  # 模块名.变量名 或 函数名 或其他,就是调用


while 1:
    s = input("请输入你要测试的功能:")  # 输入函数名

    if hasattr(master, s):  # 判断 xxx中是否有 xxx
        fn = getattr(master, s)  # 在 xxx中获取到 xxx
        fn()
    else:
        print("没有这个功能喔")


普通的获取方法

lst = ["chi", "he", "shui"]

for k, item in enumerate(lst):  # 枚举,enumerate(枚举的对象)
    print(k, item)

fe2: 属性存储在对象里,方法存储在类里

class Car:
    def __init__(self, cloro, pai, price):
        self.cloro =cloro
        self.pai = pai
        self.price = price

    def fly(self):
        print("车在飞")

c = Car("大红色", "宝马", 1000000)

setattr(Car, "fly", lambda self: print("我让他飞的,不是他自己飞") ) # 方法存在类里,所以用类来操作
c.fly()

setattr(c, "cloro", "黑色")  # 属性存在对象里,所以用对象来进行操作修改
print(c.cloro)

# print(getattr(c, "cloro"))  # 属性存在对象里,所以要用对象去拿
# print(getattr(Car, "cloro"))  # 报错   类中不存属性
# print(c.cloro)

# delattr(Car, "fly")
# delattr(c,"cloro")  # 可以操作我们的类或者对象

四、md5加密

md5特点: 不可逆的一种加密方式
最多用在密码加密上

1、步骤

import hashlib  # 引入
obj = hashlib.md5(加盐)  # 加盐=二次加密,md5出来太久,可以被查询,二次加密后就无法查询到了
obj.update(铭文的bytes)
obj.hexdigest() 获取密文

2、md5的使用

import hashlib
def jiami(content):
    obj = hashlib.md5(SALT)  # 创建md5对象,并进行加密
    obj.update(content.encode("utf-8"))  # 给obj设置铭文
    return obj.hexdigest()  # 获取到密文

fe1: 使用实例,注册和登录的实例

import hashlib

SALT = b"abcdefghijklmnjklsfdafjklsdjfklsjdak"

# 创建md5的对象
obj = hashlib.md5(SALT) # 加盐
# 给obj设置铭文
obj.update("alex".encode("utf-8"))
# 获取到密文
miwen = obj.hexdigest()
             # f4c17d1de5723a61286172fd4df5cb83
             # 534b44a19bf18d20b71ecc4eb77c572f
print(miwen) # 534b44a19bf18d20b71ecc4eb77c572f

fe2: 注册和登录的实例

import hashlib

SALT = b"abcdefghijklmnjklsfdafjklsdjfklsjdak" # 一定要byte类型的加盐

# 注册
# username = input("请输入你的用户名:")   # alex
# password = input("请输入你的密码:")
# password = jiami(password) # c3d4fe3dce88533a8b50cf2e9387c66d
# print(password)

# 登录
uname = "alex"
upwd = "c3d4fe3dce88533a8b50cf2e9387c66d"

username = input("请输入你的用户名:")
password = input("请输入你的密码:")

if uname == username and upwd == jiami(password):
    print("登录成功")
else:
    print("失败")
posted @ 2018-11-09 18:57  一片疏影  阅读(241)  评论(0编辑  收藏  举报