反射 后边有关字符串的
# class Management:
# role = '管理员'
# def __init__(self,name,sex,phone,mail):
# self.name = name
# self.sex = sex
# self.phone = phone
# self.mail = mail
# def creat_class(self):
# print('创建了一个班级')
# def creat_teacher(self):
# print('新建了一条讲师信息')
# def creat_student(self):
# print('新建了一条学生信息')
# manager = Management('小雨','女',1233211234567,'xiaoyu@qq.com')
# print(hasattr(manager,'小华')) # D对象和属性 判断是否有 返回 布尔值 False
# print(hasattr(manager,'creat_student')) # 返回 True
# ---------
# 属性的 hasattr()和 getattr组合用法
# if hasattr(Management,'role'): #类名 和属性
# print(getattr(Management, 'role'))
# else:
# logging.warning('没有输入的属性')
# 管理员
# 获取方法 getattr
# func = getattr(manager,'creat_student') #只是个函数名字 需要后边调用
# func()
# 新建了一条学生信息
# -------
# hasatt 和 getattr 组合用法
# import logging
# if hasattr(manager, 'hobby'): # 类名 和属性
# print(getattr(manager, 'hobby'))
# else:
# logging.warning('没有输入的属性')

# manager = Management('小雨','女',111252,'1111@qq.com')
# if hasattr(manager,'sex1'): # True
# sex = getattr(manager,'sex1')# False
# print(sex)
# else:
# print('没有你输入的属性')
# 没有你输入
# ------------
# 设置属性 也就是修改 setattr
# setattr(Management,'role','小孩子') #先改变在打印
# print(getattr(Management,'role'))
# 小孩子

# -----
# 删除 delattr()
# print(getattr(manager,'name'))
# print(delattr(manager,'name'))
# manager.creat_class()
# delattr(Management,'creat_class') #删除方法 后边加括号
# manager.creat_class()

# -------
# 对象的反射
# 类的反射
# 模块的反射
# 本模块的反射:找到本模块sys.modules[__name__]
# python面向对象中的反射:通过字符串的形式操作对象相关的属性。
# python中的一切事物都是对象(都可以使用反射)

# hasattr() 函数用于判断对象是否包含对应的属性。
# getattr() 函数用于返回一个对象属性值。
# setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在。
# delattr 函数用于删除属性。
# delattr(x, 'foobar') 相等于 del x.foobar。

# import mkfs
# mkfs 作为另一个被引用的模块的py文件
# m= 'wangyan'
# def qqxing(arg):
# print('qqxing','arg')
    return ‘调用成功’
# --
# print(mkfs.m) # 第一种 调用模块
# print(getattr(mkfs,'m')) #反射调用
# ret = getattr(mkfs,'qqxing') # 反射函数名ret 因为是方法 后边在调用
# ret('arg') #调用函数已经有上传参数了 必须和参数保持一致
# qq = getattr(mkfs,'qqxing') # 函数名字
# ret=qq('www') # 返回值 和调用
# print(ret)
# qqxing arg
# 调用成功
# ------------------------
# 其他内置函数的
# __str__方法
# class A:pass
# a = A()
# print(a) # <__main__.A object at 0x014BA450 内存地址 自己找不到到父类找 再找不到就是object
# l = list()
# print(l) # [] 为什么打出来长上面的不一样,因为list里面有内置方法
# print(a.__str__()) #<__main__.A object at 0x014BA450
# ****打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值
# 返回值必须是字符串

# print('%s'%a) #<__main__.A object at 0x014BA450
# %s 就是__str__方法的返回值
# --------------------------
# # 类的双下划线方法 比较
# # __str__ 和 __repr__
# 自己定制str方法 都有的话 各用各的
# class A:
# def __str__(self):
# return 'a的对象' # str必须return一个字符串
# def __repr__(self):
# return 'repr:A的对象'
# a = A()
# print(a.__str__()) # a的对象
# print(a.__repr__()) #
# print('%s'%a)
# print('%r'%a)
# a的对象
# repr:A的对象
# a的对象
# repr:A的对象

# # #------------------# repr是str的备胎,没有str就用repr没有__str__ 使用备胎的__repr__
# class A:
# def __repr__(self):
# return 'repr:A的对象'
# a = A()
# print(a.__str__()) # a的对象
# print(a.__repr__())
# print('%s'%a)
# print('%r'%a)
# repr:A的对象
# repr:A的对象
# repr:A的对象
# repr:A的对象
# ---------------
# # repr是str的备胎,没有str就用repr (repr比较随和)
# # str 却不能给repr做备胎 (str高冷 )
# ----------没有repr 不能用str
# class A:
# def __str__(self):
# return 'repr:A的对象'
# a = A()
# print(a.__str__()) # a的对象
# print(a.__repr__())
# print('%s'%a)
# print('%r'%a)
# repr:A的对象
# <__main__.A object at 0x02AE3110>
# repr:A的对象
# <__main__.A object at 0x02AE3110>
# -----------------------------------------------------
# 自定制格式化字符串__format__

# format_dict={
# 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
# 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
# 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
# }
# class School:
# def __init__(self,name,addr,type):
# self.name=name
# self.addr=addr
# self.type=type
# def __repr__(self):
# return 'School(%s,%s)' %(self.name,self.addr)
# def __str__(self):
# return '(%s,%s)' %(self.name,self.addr)
# def __format__(self, format_spec):
# # if format_spec
# if not format_spec or format_spec not in format_dict:
# format_spec='nat'
# fmt=format_dict[format_spec]
# return fmt.format(obj=self)
# s1=School('oldboy1','北京','私立')
# print('from repr: ',repr(s1))
# print('from str: ',str(s1))
# print(s1)
# ----------
# __del__析构方法,当对象在内存中被释放时,自动触发执行。
# 这个方法只有在执行del A类的对象时候才会被触发 且执行代码中的内容,在删除对象
# 如果为删除了这个对象,他跟着还有些其他的附属的内容也没有了 我们就可以在这个方法中回收掉
# 注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放
# 因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

# class Foo:
# def __del__(self):
# print('执行我啦')
# f1=Foo()
# import time
# time.sleep(2)
# del f1 #要删除f1 在此时才会被触发
# print('删除成功')
# # 先执行 __del__(self): 在删除
# 执行我啦
# 删除成功
# --------------------------------
# __item__ 这个方法类似字典的操作
# 对象访问如果是对象名[],是因为内部实现了item的方法
# class Foo:
# def __init__(self,name):
# self.name=name
# def __getitem__(self, item):
# print(self.__dict__[item])
# def __setitem__(self, key, value):
# self.__dict__[key]=value
# def __delitem__(self, key):
# print('del obj[key]时,我执行')
# self.__dict__.pop(key)
# def __delattr__(self, item):
# print('del obj.key时,我执行')
# self.__dict__.pop(item)
# f1=Foo('sb')
# f1['age']=18 #f1.age = 18 增加一个属性
# # #print(f1.__dict__)
# # {'name': 'sb', 'age': 18}
# f1['age1']=19 #f1.age = 19
# del f1.age1 #方式 一删除
# del f1['age'] #方式 一删除
# f1['name']='alex' # f1.name = 'alex'
# print(f1.__dict__)
# ------------------
# ****__new__方法
# 一般是objct 在创造的, __new__方法和 __init__方法 一定是new先执行
# 对象的实例化
#创造一个裸地对象 —— __new__ ****
# 单例模式 —— 设计模式
# 一个类 从头到尾 只创建 一个对象
# class Singleton:
# def __new__(cls, *args):
# if not hasattr(cls, '_instance'):
# cls._instance = object.__new__(cls) #_instance 静态属性 因为前面是类 所有对象共用
# return cls._instance
# def __init__(self,name):
# self.name = name
# one = Singleton('alex')
# print(one.name)
#
# two = Singleton('egon')
# print(two.name)
# print(one.name)
# print(id(one),id(two))
# alex
# egon
# egon
# 46805584 46805584
# two = one
# two.name = 'egon'
# 原因是单例模式 因为重写new 模式实现的
# ---------
# 单例模式 面试必问 , 从头到尾一个类只有一个对象,可以多次实例化
# 但是只能是一个对象,
# 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)
# a = A()
# print(a.x)
# in new function 打印出对象必须是先是new 然后是init
# in init function
# 1
# ----------------------------------------
# __call__
# 对象后面加括号,触发执行。
# 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;
# 而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
# class Foo:
# def __init__(self):
# pass
#
# def __call__(self, *args, **kwargs):
# print('__call__')
# a = Foo()
# Foo()() #类名()()
# a() #对象名()
# __call__
# __call__
# 固定的用法 类名()() 和__call__是一对

# ----------------------------------------
# __len()__ 长度
# class A:
# def __init__(self):
# self.a = 1
# self.b = 2
# self.c = 3
#
# def __len__(self):
# return len(self.__dict__)
# a = A()
# print(len(a))
# 3 表示对象的长度 init 的属性多长就是多长
# ——————————————————
# hash 哈希调用 不可变的数据类型 针对不可变的类型
# class A:
# def __init__(self):
# self.a = 1
# self.b = 2
#
# def __hash__(self):
# return hash(str(self.a)+str(self.b))
# a = A()
# print(hash(a))
# 1657541466 每次数值是不一样的额
# ---------------------------------
# equal 相等的 如没有条件 肯定不相等 是两个objec的 出来的
# class A:
# def __eq__(self,obj): #equal : 相等
# # if self.a == obj.a and self.b == obj.b:
# return True
# a = A()
# b = A()
# # a.name = 'alex'
# # b.name = 'egon'
# print(a == b)
# -----------
# class A:pass
#
# a = A()
# b = A()
#
# print(a == b)
# False inint属性有两个 根据__new__ 有两个内存的值
#