内容梗概:
    1. isinstance, type, issubclass
    2. 区分函数和方法
    3. 反射(重点)
    4. md5加密

1. isinstance, type, issubclass
1.1 issubclass() 这个内置函数可以帮我们判断xxx类是否是yyy类型的子类.
class Base:
    pass
class Foo(Base):
    pass
class Bar(Foo):
    pass
print(issubclass(Bar,Foo))      #True
print(issubclass(Bar,Base))     #True 可以隔代判断
print(issubclass(Foo,Bar))      #False

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

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

1.2 type
定义:type(obj) 表⽰查看obj是由哪个类创建的
class Foo:
    pass
obj = Foo()
print(obj, type(obj)) # 查看obj的类  可以精准的返回数据类型

实例二:判断男女并统计
class Boy:
    pass
class Girl:
    pass
统计传进来的男生和女生分别有多少
def func(*args):
    b = 0
    g = 0
    for obj in args:
        if type(obj) == Boy:
            b += 1
        elif type(obj) == Girl:
            g += 1
    return b, g
ret = func(Boy(), Girl(), Girl(), Girl(), Boy(), Boy(), Girl())
print(ret)

1.3 isinstance
作用:isinstance也可以判断xxx是yyy类型的数据. 但是isinstance没有type那么精准.
class Animal:
    pass
class Cat(Animal): # x是一种y. x继承y
    pass
class BosiCat(Cat):
    pass
kitty = Cat()
kate = BosiCat()
print(isinstance(kitty, BosiCat))  # False  kitty是cat,但不一定是BosiCat
print(isinstance(kate,Cat))         # True kate是BosiCat,所以一定是Cat

tips:type的精确性更高,实例如下
print(type(kitty) == Animal)      # False
print(isinstance(kitty, Animal))  # True


2. 区分函数和方法
2.1 区分方法一(野路子) 直接print()打印看结果
class Car:
    def run(self): # 实例方法
        print("我是车, 我会跑")
    @staticmethod
    def cul():
        print("我会计算")
    @classmethod
    def jump(cls):
        print("我会jump")

c = Car()
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.2 用MethodType,FunctionType判断是函数还是方法(官方版)
from types import MethodType,FunctionType
实例方法:
print(isinstance(c.run,MethodType))    #True
print(isinstance(Car.run,MethodType))  #False
print(isinstance(c.run,FunctionType))    #False
print(isinstance(Car.run,FunctionType)) #True

静态方法:
print(isinstance(c.cul,MethodType))    #False
print(isinstance(Car.cul,MethodType))  #False
print(isinstance(c.cul,FunctionType))    #True
print(isinstance(Car.cul,FunctionType)) #True

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

总结:
    1. 类方法. 不论任何情况, 都是方法.
    2. 静态方法, 不论任何情况. 都是函数
    3. 实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数.


3 反射.
关于反射, 其实一共有4个函数:
1. hasattr(obj, str)判断obj中是否包含str成员
2. getattr(obj,str)从obj中获取str成员
3. setattr(obj, str, value)把obj中的str成员设置成value.注意.这里的value可以是值,也可以是函数或方法
4. delattr(obj, str)把obj中的str成员删除掉
注意,以上操作都是在内存中进行的.并不会影响你的源代码

import master
def hei()
    print("大牛不行,吃得少")
print(getattr(master,"name"))   #获取master中的属性
setattr(master,"chi",hei)         #更改master中chi的内容
setattr(master,"haha",hei)       #若master无此内容,则会创建一个新内容
setattr(master,"name","张全蛋")    #更改master中name的内容
setattr(master,"hehe","张全蛋")   #若master无此内容,则会创建一个新属性
print(master.name)
print(master.haha)

while 1:
    s = input("请输入你要测试的功能名字:")
    if hasattr(master,s):   #判断master中是否含有该内容
        fn = getattr(master,s)
        fn()
    else:
        print("滚犊子")

实例二
class Car:
    def __init__(self, color, pai, price):
        self.color = color
        self.pai = pai
        self.price = price

    def fly(self):
        print("我的车会飞")

c = Car("黄色", "兰博基尼", 188888)
删除属性和方法
delattr(Car, "fly")  # 可以操纵我们的类或者对象
c.fly()    # 会报错,因为已经被删掉了 'Car' object has no attribute 'fly'

更该方法:
setattr(Car, "fly", lambda self:print("我的天啊. 我的车居然会飞"))
c.fly()

更改属性
print(c.color)
setattr(c, 'color', "黑色")
print(c.color)

print(getattr(c, "pai"))
print(c.pai)


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

大致流程如下:
import hashlib
SALT = b"abcdefghijklmnjklsfdafjklsdjfklsjdak" #盐 变相二次加密,防止库匹配
创建md5的对象
obj = hashlib.md5(SALT) # 加盐
给obj设置铭文
obj.update("alex".encode("utf-8"))
获取到密文
miwen = obj.hexdigest()
             f4c17d1de5723a61286172fd4df5cb83(加盐后)
print(miwen) # 534b44a19bf18d20b71ecc4eb77c572f (未加盐前)

实例:
uname = "alex"
upwd = "3b74435096910f0ca102a3bde0b7b963"

import hashlib
SALT = b"abcdefghijklmnjklsfdafjklsdjfklsjdak"

def jiami(content):
    obj = hashlib.md5(SALT)
    obj.update(content.encode("utf-8"))
    return obj.hexdigest()

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

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

if uname == username and upwd == jiami(password):
    print("登录成功")
else:
    print("失败")