本节主要内容:
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("失败")