day27-面向对象进阶

时间:2022-12-15 13:26:37
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# ------------------------------------------------------------
#
# 参考资料:(未有转载)
# 面向对象进阶 - linhaifeng - 博客园
# https://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12
# 
# python常用模块(模块和包的解释,time模块,sys模块,random模块,os模块,json和pickle序列化模块) - 心大一点 - 博客园
# http://www.cnblogs.com/yangjian1/p/6172174.html
#
# python基础之迭代器协议和生成器(一) - devops1992 - 博客园
# https://www.cnblogs.com/bingabcd/p/6691730.html
#
# ------------------------------------------------------------
# ******************** day27-面向对象进阶 *******************
# ******************** day27-面向对象进阶 *******************
# =====>>>>>>内容概览
# =====>>>>>>内容概览
# day27_MianXiangDuiXiangJinJie


# ------------------------------------------------------------
# # 1、argv
# # # 在命令行参数是一个空列表,在其他中第一个列表元素中程序本身的路径
# # # 通过命令终端来运行下面的程序,在pycharm中,编译器会自动处理,因此会报错
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 2、sys.path
# # # 返回模块的搜索路径,初始化时使用python PATH环境变量的值
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 3、getcwd、chdir、r字符串
# # # getcwd     获取当前的文件路径
# # # chdir      更改文件路径
# # # r字符串    正则表达式r的作用,让"D:\Program Files (x86)"的“\”不再具备有特殊意义
# # # 即“\\”  == r“\”
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 4、路径拼接,os.path.join
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 4.1、路径拼接2, os.path.join
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 5、判断该运行文件中是否有该属性x
# # # day27_MianXiangDuiXiangJinJie 是当前的文件运行名称
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 5.1、判断该运行文件中是否有该属性2
# # # 解决序列5的问题
# # # __name__        当前的运行文件
# # # sys.modules     储存挡墙的运行文件的模块名称列表
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 6、__setattr__,__delattr__,__getattr__的应用对象
# # # 这三者的应用对象是类的“实例”;类本身并不会被影响到
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 7、isinstance
# # # isinstance(obj,cls)检查是否obj是否是类 cls 的对象
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 8、issubclass
# # # issubclass(sub, super)检查sub类是否是 super 类的派生类
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 9、getattribute
# # # 只要与实例相关的都会触发该操作
# # # getattribute的优先级别高于getattr
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 9.1、getattribute被屏蔽时,getattr的情况
# # # 只要与实例相关的都会触发该操作
# # # getattribute的优先级别高于 getattr
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 10、AttributeError
# # # 自定义的抛出异常
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 11.1、 __getattr__的作用
# # # 属性不存在的时候会触发  __getattr__
# # # 类是不会触发  __getattr__
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 11.2、 只有__getattribute__存在的情况,没有写入raise AttributeError
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 11.3、 __getattribute__与__getattr__ ,没有raise
# # # 没有raise是不会触发__getattr__;
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 11.4、 __getattribute__与__getattr__与raise
# # # 有了raise之后,无论属性有没有都会执行,raise AttributeError,
# # # 之后,就会直接触发__getattr__;
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 12、 __getattribute__与__getattr__总结
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 13、__setitem__设置属性,
# # # f1["age"]  = 18 这种方式才回触发__setitem__
# # # __setitem__操作的是[], 注意与前面的__setattr__区别
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 14、__delitem__
# # # del f1['age'] 这种方式才会触发 __delitem__
# # # __setitem__操作的是[], 注意与前面的__delattr__区别
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 15、__getitem__
# # # f1["age"]这种方式才会触发 __getitem__
# # # __getitem__[], 注意与前面的__getattr__区别
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 16、__str__
# # # 改变的是输出到窗口的信息, 与print(f2)   ,print(file) 对比
# # # str函数或者print函数--->obj.__str__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 17、str(f1), f1.__str__()
# # # str(f1)--->f1.__str__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 17.1、str(f1), f1.__str__()
# # # str(f1)--->f1.__str__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 18、repr
# # # repr 或者交互式解释器--->obj.__repr__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 19、__str__ 与 __repr__
# # # 两者同时出现时,输出打印选择的是__str__
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 20、__str__与__repr__总结
# # # str函数或者print函数--->obj.__str__()
# # # repr或者交互式解释器--->obj.__repr__()
# # # 如果__str__没有被定义,那么就会使用__repr__来代替输出
# # # 两者同时出现时,输出打印选择的是__str__
# # # 注意:这俩方法的返回值必须是字符串,否则抛出异常
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 21、字符串.format
# # #
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 22、字符串.format的应用1
# # #
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 22.1、format 与类中 __format__ 的关系
# # # 运行时,format 实际上就去调用“对应类”中的 __format__, __format__要有返回值
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 23、format的应用 之 自定义格式
# # # 自定义输出日期的格式, 与前面 序号21 对比;
# # # 运行时,format 实际上就去调用“对应类”中的 __format__, __format__要有返回值
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 24、__slots__介绍
# # # 对于 __slots__ 我们关注的是,1、它的存在是为了节约内存; 2、它存在的类中,所有的
# # # 属性“全部”都取消了实例字典,只有类字典;   3、__slots__ 定以后的变量,不可以在添加新的值,
# # # 但是可以修改
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 24.1、__slots__ 属性值添加
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 24.2、__slots__ 属性值添加
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 24.3、__slots__
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 24.4、 __doc__
# # # 该属性无法继承给子类;   如果没有对该属性进行赋值的话,那么默认是None
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 25、 __module__ 与 __class__
# # #
# # # __module__     表示当前操作的对象在那个模块
# # # __class__     表示当前操作的对象的类是什么
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 26、__del__析构方法介绍
# # #
# # # 析构方法,当对象在内存中被释放时,自动触发执行。
# # # 注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,
# # # 如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,
# # # 比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就
# # # 用到了__del__
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 27、__del__ 实例
# # # 运行结束之后,就会触发 __del__
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 27.1、__del__ 实例1
# # # 情况一:程序运行结束之后,就会触发 __del__
# # # 情况2 :删除实例,就会触发 __del__
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 28、__call__ 的引入
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 28.1、__call__ 演示
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 29、迭代器的协议的引入
# # # (字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,
# # # 调用了他们内部的__iter__方法,把他们变成了可迭代对象;  而下面的类中,是一个对象,但是
# # # 并不是一个可迭代对象
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 30、迭代器的协议
# # # (字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,
# # # 调用了他们内部的__iter__方法,把他们变成了可迭代对象;
# # # 而下面的类中,是一个对象,在类中引入iter与next使它变成一个选代器
# ------------------------------------------------------------


# ------------------------------------------------------------
# # 30.1、迭代器协议实现斐波那契数列
# # # 斐波那契数列: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233...
# # #
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 31、描述符的介绍
# # # 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
# # #__get__():调用一个属性时,触发
# # #__set__():为一个属性赋值时,触发
# # #__delete__():采用del删除属性时,触发
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 31.1、定义一个描述符
# # #  在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 32、描述符与实例的关系
# # # 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这
# # # 个类的类属性,不能定义到构造函数中
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 33、描述符的的使用
# # # 注意到,下面的实例是的数值数属是  类级别的
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 33.1、含有描述符的实例与类的关系
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 34、描述符之一,数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 一 数据描述符:至少实现了__get__()和__set__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 35、描述符之二,非数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 35.1、描述符之二,非数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 36、描述符之优先级别,类属性>数据描述
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 36.1、描述符之优先级别,类属性>数据描述
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 36.2、描述符之优先级别,实例属性>非数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 36.3、描述符之优先级别,实例属性>非数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 36.4、描述符之优先级别,实例属性>非数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 37、非数据描述符>找不到
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 38、不同目录级别下的文件路径处理1
# # # 注:下面的这种方式的文件路径是没有处理的主,不建  讠义 使用;
# ------------------------------------------------------------

# ------------------------------------------------------------
# # 38.1、不同目录级别下的文件路径处理2
# # # 注:下面的这种方式的文件路径是进行了处理,建  讠义  使用;这样,当工程文件的拷贝到了不同的止录下,
# # #   都是可以使用的
# ------------------------------------------------------------




# ------------------------------------------------分割线------------------------------------------------- # ------------------------------------------------分割线------------------------------------------------- # ------------------------------------------------分割线-------------------------------------------------

 
# 01 os模块复习
# 01 os模块复习
'''
# ------------------------------------------------------------
# # 1、argv
# # # 在命令行参数是一个空列表,在其他中第一个列表元素中程序本身的路径
# # # 通过命令终端来运行下面的程序,在pycharm中,编译器会自动处理,因此会报错
# ------------------------------------------------------------
'''
#
# import sys,os
# li = sys.argv
#
# if li[1] == "post":
#     print("post")
#
# elif li[1] == 'down':
#     print("1111111")
#
#
# # 命令终端运行结果如下
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie>python file.py post
# # post
# #
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie>python file.py down
# # 1111111
# #




'''
# ------------------------------------------------------------
# # 2、sys.path
# # # 返回模块的搜索路径,初始化时使用python PATH环境变量的值
# ------------------------------------------------------------
'''
#
# import sys
# print("sys.path:        ", sys.path)
# for i in sys.path:
#     print(i)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # sys.path:         ['D:\\C_cache\\py\\day27_MianXiangDuiXiangJinJie', 'D:\\C_cache\\py\\day27_MianXiangDuiXiangJinJie', 'D:\\Anaconda3\\python36.zip', 'D:\\Anaconda3\\DLLs', 'D:\\Anaconda3\\lib', 'D:\\Anaconda3', 'D:\\Anaconda3\\lib\\site-packages', 'D:\\Anaconda3\\lib\\site-packages\\win32', 'D:\\Anaconda3\\lib\\site-packages\\win32\\lib', 'D:\\Anaconda3\\lib\\site-packages\\Pythonwin', 'D:\\Program Files (x86)\\PyCharm 2018.1.3\\helpers\\pycharm_matplotlib_backend']
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie
# # D:\Anaconda3\python36.zip
# # D:\Anaconda3\DLLs
# # D:\Anaconda3\lib
# # D:\Anaconda3
# # D:\Anaconda3\lib\site-packages
# # D:\Anaconda3\lib\site-packages\win32
# # D:\Anaconda3\lib\site-packages\win32\lib
# # D:\Anaconda3\lib\site-packages\Pythonwin
# # D:\Program Files (x86)\PyCharm 2018.1.3\helpers\pycharm_matplotlib_backend
# #
# # Process finished with exit code 0






'''
# ------------------------------------------------------------
# # 3、getcwd、chdir、r字符串
# # # getcwd     获取当前的文件路径
# # # chdir      更改文件路径
# # # r字符串    正则表达式r的作用,让"D:\Program Files (x86)"的“\”不再具备有特殊意义
# # # 即“\\”  == r“\”
# ------------------------------------------------------------
'''
#
# import os
# print(os.getcwd())                   # 尽量少用这个,用sys.path
# # 正则表达式r的作用,让"D:\Program Files (x86)"的“\”不再具备有特殊意义
# # 即“\\”  == r“\”
# os.chdir(r"D:\Program Files (x86)")
# print(os.getcwd())
#
# # 使用\\
# os.chdir("C:\\Windows\\Boot")
# print(os.getcwd())
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie
# # D:\Program Files (x86)
# # C:\Windows\Boot
# #
# # Process finished with exit code 0













'''
# ------------------------------------------------------------
# # 4、路径拼接,os.path.join 
# ------------------------------------------------------------
'''
#
# import os
# print(os.path.join("D:\\C_cache\\py"))
# print(os.path.join(r"D:\C_cache\py") )
# print(os.path.join("D:\\C_cache\\py", 'www', 'baidu'))
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # D:\C_cache\py
# # D:\C_cache\py
# # D:\C_cache\py\www\baidu
# #
# # Process finished with exit code 0









'''
# ------------------------------------------------------------
# # 4.1、路径拼接2, os.path.join
# ------------------------------------------------------------
'''
#
# import os
# print(os.getcwd())                   # 尽量少用这个,用sys.path
# # __file__是pycharm内置的方法,获取的运行的文件名,在编译器处理的时候,会自动加上前面的文件路径
# print( os.path.dirname(os.path.abspath(__file__)))
# print(os.path.join(os.path.dirname(os.path.abspath(__file__)),"bb","123.txt"))
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie\bb\123.txt
# # D:\C_cache\py\day27_MianXiangDuiXiangJinJie\bb\123.txt
# #
# # Process finished with exit code 0





'''
# ------------------------------------------------------------
# # 5、判断该运行文件中是否有该属性x
# # # day27_MianXiangDuiXiangJinJie 是当前的文件运行名称
# ------------------------------------------------------------
'''
#
# import day27_MianXiangDuiXiangJinJie as obj
# x = 1
# y = 9
# print('x===>>', hasattr(obj,'x'))        # 直接运行,每一个都运行了两遍
# print('y===>>', hasattr(obj,'y'))        # 直接运行,每一个都运行了两遍
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/file.py
# # x===>> True
# # y===>> True
# # x===>> True
# # y===>> True
# #
# # Process finished with exit code 0








'''
# ------------------------------------------------------------
# # 5.1、判断该运行文件中是否有该属性2
# # # 解决序列5的问题
# # # __name__        当前的运行文件
# # # sys.modules     储存挡墙的运行文件的模块名称列表
# ------------------------------------------------------------
'''
#
# import sys
# x = 1
# y = 9
# print("__name__:   ", __name__)
# obj = sys.modules[__name__]     # 获取到当前文件的运行名称
#
# print('x===>>', hasattr(obj,'x'))        # 直接运行,每一个都运行了两遍
# print('y===>>', hasattr(obj,'y'))        # 直接运行,每一个都运行了两遍
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/file.py
# # __name__):    __main__
# # x===>> True
# # y===>> True
# #
# # Process finished with exit code 0



'''
# ------------------------------------------------------------
# # 6、__setattr__,__delattr__,__getattr__的应用对象
# # # 这三者的应用对象是类的“实例”;类本身并不会被影响到
# ------------------------------------------------------------
'''
#
# class Foo:
#     x=1
#     def __init__(self,y):
#         self.y=y
#
#     def __getattr__(self, item):
#         print('----> from getattr:你找的属性不存在')
#
#     def __setattr__(self, key, value):
#         print('----> from setattr')
#         # self.key=value #这就无限递归了,你好好想想
#         # self.__dict__[key]=value #应该使用它
#
#     def __delattr__(self, item):
#         print('----> from delattr')
#         # del self.item #无限递归了
#         self.__dict__.pop(item)
#
# f1 = Foo("zhang")
# f1.x = 10
# f1.z = "z"
#
# # 并不会触发属性
# Foo.A = "A"
# Foo.B = "B"
# #
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # ----> from setattr
# # ----> from setattr
# # ----> from setattr
# #
# # Process finished with exit code 0










# 03 内置函数补充及getattribute
# 03 内置函数补充及getattribute

'''
# ------------------------------------------------------------
# # 7、isinstance
# # # isinstance(obj,cls)检查是否obj是否是类 cls 的对象
# ------------------------------------------------------------
'''
#
# class Foo:
#     pass
#
# class Bar(Foo):
#     pass
#
# b1 = Bar()
# print(isinstance(b1, Bar))
# print(isinstance(b1, Foo))
#
# print(type(b1))
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # True
# # True
# # <class '__main__.Bar'>
# # <class 'list'>
# #
# # Process finished with exit code 0












'''
# ------------------------------------------------------------
# # 8、issubclass
# # # issubclass(sub, super)检查sub类是否是 super 类的派生类
# ------------------------------------------------------------
'''
#
# class Foo:
#     pass
#
# class Bar(Foo):
#     pass
#
# class cls:
#     pass
#
# print(issubclass(Bar, Foo))
# print(issubclass(cls, Foo))
# print(issubclass(Bar, object))
# print(issubclass(Foo, object))
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # True
# # False
# # True
# # True
# #
# # Process finished with exit code 0












'''
# ------------------------------------------------------------
# # 9、getattribute 
# # # 只要与实例相关的都会触发该操作
# # # getattribute的优先级别高于getattr
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name):
#         self.name = name
#
#     def __getattr__(self, item):
#         print("执行的是getattr!触发的内容是【%s】"%item)
#
#     # def __getattribute__(self, item):
#     #     print("执行的是getattribute!触发的内容是【%s】"%item)
#
#     def func(self):
#         pass
#
# f1 = Foo("我是哈")
# print("Foo.__dict__: ", Foo.__dict__)
# Foo.func("随便写")
#
# print("f1.__dict__: ", f1.__dict__)         # __getattribute__会触发
#
# print("f1.name:     ", f1.name)
# print("f1.name:     ", f1.name99999999999)  # 不存在的函数属性
#
# print("f1.__dict__: ", f1.__dict__)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Foo.__dict__:  {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x0000000001D41EA0>, '__getattr__': <function Foo.__getattr__ at 0x00000000029A4620>, '__getattribute__': <function Foo.__getattribute__ at 0x00000000039EE7B8>, 'func': <function Foo.func at 0x00000000039EE840>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # 执行的是getattribute!触发的内容是【__dict__】
# # f1.__dict__:  None
# # # 执行的是getattribute!触发的内容是【name】
# # # f1.name:      None
# # 执行的是getattribute!触发的内容是【__dict__】
# # f1.__dict__:  None
# #
# # Process finished with exit code 0
# #
# #
# #









'''
# ------------------------------------------------------------
# # 9.1、getattribute被屏蔽时,getattr的情况
# # # 只要与实例相关的都会触发该操作
# # # getattribute的优先级别高于 getattr
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name):
#         self.name = name
#
#     def __getattr__(self, item):
#         print("执行的是getattr!触发的内容是【%s】"%item)
#
#     # def __getattribute__(self, item):
#     #     print("执行的是getattribute!触发的内容是【%s】"%item)
#
#     def func(self):
#         pass
#
# f1 = Foo("我是哈")
# print("Foo.__dict__: ", Foo.__dict__)
# Foo.func("随便写")
#
# print("f1.__dict__: ", f1.__dict__)         # __getattribute__会触发
#
# print("f1.name:     ", f1.name)
# print("f1.name:     ", f1.name99999999999)  # 不存在的函数属性
#
# print("f1.__dict__: ", f1.__dict__)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Foo.__dict__:  {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x0000000001D41EA0>, '__getattr__': <function Foo.__getattr__ at 0x00000000029A4620>, '__getattribute__': <function Foo.__getattribute__ at 0x00000000039EE7B8>, 'func': <function Foo.func at 0x00000000039EE840>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # 执行的是getattribute!触发的内容是【__dict__】
# # f1.__dict__:  None
# # # 执行的是getattribute!触发的内容是【name】
# # # f1.name:      None
# # 执行的是getattribute!触发的内容是【__dict__】
# # f1.__dict__:  None
# #
# # Process finished with exit code 0
# #









'''
# ------------------------------------------------------------
# # 10、AttributeError
# # # 自定义的抛出异常
# ------------------------------------------------------------
'''
#
# raise AttributeError("这个是我自定义的抛出异常")
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Traceback (most recent call last):
# #   File "D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py", line 458, in <module>
# #     raise AttributeError("这个是我自定义的抛出异常")
# # AttributeError: 这个是我自定义的抛出异常
# #
# # Process finished with exit code 1














'''
# ------------------------------------------------------------
# # 11.1、 __getattr__的作用
# # # 属性不存在的时候会触发  __getattr__
# # # 类是不会触发  __getattr__
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name):
#         self.name = name
#
#     def __getattr__(self, item):
#         print("执行的是getattr!触发的内容是【%s】"%item)
#
#     def func(self):
#         pass
#
# f1 = Foo("我是哈")
#
# print("分割线111".center(100,"-"))
# print("f1.__dict__: ", f1.__dict__)
#
# print("分割线222".center(100,"-"))
# print("f1.name:     ", f1.name)             # 属性有的内容
# print("f1.name:     ", f1.name99999999999)  # 不存在的属性内容
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Foo.__dict__:  {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000020A1EA0>, '__getattr__': <function Foo.__getattr__ at 0x00000000029A4620>, 'func': <function Foo.func at 0x0000000003A2E7B8>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # -----------------------------------------------分割线111-----------------------------------------------
# # f1.__dict__:  {'name': '我是哈'}
# # -----------------------------------------------分割线222-----------------------------------------------
# # f1.name:      我是哈
# # 执行的是getattr!触发的内容是【name99999999999】
# # f1.name:      None
# # -----------------------------------------------分割线333-----------------------------------------------
# # f1.__dict__:  {'name': '我是哈'}
# #
# # Process finished with exit code 0
#













'''
# ------------------------------------------------------------
# # 11.2、 只有__getattribute__存在的情况,没有写入raise AttributeError
# # # 情况一:没有写入raise AttributeError;
# # #         不管属性的内容有,还是没有,都会正常运行,程序不会报错
# # # 情况二:写入raise AttributeError;
# # #         报错,即使是属性有的内容们也会报错,因为运行后,直接触发raise AttributeError
# # #         触发后,没有__getattr__来处理
# # #
# # # 总的来说,如果__getattribute__有的内容,就不会触发 raise AttributeError;
# # # 如果没有,就是触发raise AttributeError;
# # # 下面演示中 __getattr__被注释掉了,因此触发的AttributeError无法让__getattr__来处理,才回报错
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name):
#         self.name = name
#
#     # def __getattr__(self, item):
#     #     print("执行的是getattr!触发的内容是【%s】"%item)
#
#     def __getattribute__(self, item):
#         print("执行的是getattribute!触发的内容是【%s】"%item)
#         # 有了raise之后,如果有,就会直接触发__getattr__;
#         # 如果没有,就是会触发raise AttributeError
#         raise AttributeError("《《抛出异常》》")
#
#     def func(self):
#         pass
#
# f1 = Foo("我是哈")
#
# print("分割线111".center(100,"-"))
# print("f1.__dict__: ", f1.__dict__)
#
# print("分割线222".center(100,"-"))
# print("f1.name:     ", f1.name)             # 属性有的内容
# print("f1.name:     ", f1.name99999999999)  # 不存在的属性内容
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # -----------------------------------------------分割线111-----------------------------------------------
# # 执行的是getattribute!触发的内容是【__dict__】
# # Traceback (most recent call last):
# #   File "D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py", line 582, in <module>
# #     print("f1.__dict__: ", f1.__dict__)
# #   File "D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py", line 574, in __getattribute__
# #     raise AttributeError("《《抛出异常》》")
# # AttributeError: 《《抛出异常》》
# #
# # Process finished with exit code 1




'''
# ------------------------------------------------------------
# # 11.3、 __getattribute__与__getattr__ ,没有raise
# # # 没有raise是不会触发__getattr__;
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name):
#         self.name = name
#
#     def __getattr__(self, item):
#         print("执行的是getattr!触发的内容是【%s】"%item)
#
#     def __getattribute__(self, item):
#         print("执行的是getattribute!触发的内容是【%s】"%item)
#         # 有了raise之后,如果有,就会直接触发__getattr__;
#         # 如果没有,就是会触发raise AttributeError
#         # raise AttributeError("《《抛出异常》》")
#
#
#
#     def func(self):
#         pass
#
# f1 = Foo("我是哈")
# print("Foo.__dict__: ", Foo.__dict__)
# # 类是不会触发__getattribute__
# Foo.func("随便写")
#
# print("分割线111".center(100,"-"))
# # __getattribute__会触发;__getattribute__触发后,没有将属性设置进f1实例里面,因此f1为空
# print("f1.__dict__: ", f1.__dict__)
#
# print("分割线222".center(100,"-"))
# print("f1.name:     ", f1.name)             # 属性有的内容
# print("f1.name:     ", f1.name99999999999)  # 不存在的属性有的内容
#
# print("分割线333".center(100,"-"))
# print("f1.__dict__: ", f1.__dict__)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Foo.__dict__:  {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000003C1EA0>, '__getattr__': <function Foo.__getattr__ at 0x0000000002994620>, '__getattribute__': <function Foo.__getattribute__ at 0x00000000039EE7B8>, 'func': <function Foo.func at 0x00000000039EE840>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # -----------------------------------------------分割线111-----------------------------------------------
# # 执行的是getattribute!触发的内容是【__dict__】
# # f1.__dict__:  None
# # -----------------------------------------------分割线222-----------------------------------------------
# # 执行的是getattribute!触发的内容是【name】
# # f1.name:      None
# # 执行的是getattribute!触发的内容是【name99999999999】
# # f1.name:      None
# # -----------------------------------------------分割线333-----------------------------------------------
# # 执行的是getattribute!触发的内容是【__dict__】
# # f1.__dict__:  None
# #
# # Process finished with exit code 0
#



















'''
# ------------------------------------------------------------
# # 11.4、 __getattribute__与__getattr__与raise
# # # 有了raise之后,无论属性有没有都会执行,raise AttributeError,
# # # 之后,就会直接触发__getattr__;
# ------------------------------------------------------------
'''

# class Foo:
#     def __init__(self, name):
#         self.name = name
#
#     def __getattr__(self, item):
#         print("执行的是getattr!触发的内容是【%s】"%item)
#
#     def __getattribute__(self, item):
#         print("执行的是getattribute!触发的内容是【%s】"%item)
#         # 有了raise之后,如果有,就会直接触发__getattr__;
#         # 如果没有,就是会触发raise AttributeError
#         raise AttributeError("《《抛出异常》》")
#
#
#
#     def func(self):
#         pass
#
# f1 = Foo("我是哈")
# print("Foo.__dict__: ", Foo.__dict__)
# # 类是不会触发__getattribute__
# Foo.func("随便写")
#
# print("分割线111".center(100,"-"))
# # __getattribute__会触发;__getattribute__触发后,没有将属性设置进f1实例里面,因此f1为空
# print("f1.__dict__: ", f1.__dict__)
#
# print("分割线222".center(100,"-"))
# print("f1.name:     ", f1.name)             # 属性有的内容
# print("f1.name:     ", f1.name99999999999)  # 不存在的属性有的内容
#
# print("分割线333".center(100,"-"))
# print("f1.__dict__: ", f1.__dict__)
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Foo.__dict__:  {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x0000000001D41EA0>, '__getattr__': <function Foo.__getattr__ at 0x00000000029A4620>, '__getattribute__': <function Foo.__getattribute__ at 0x00000000039EE7B8>, 'func': <function Foo.func at 0x00000000039EE840>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # -----------------------------------------------分割线111-----------------------------------------------
# # 执行的是getattribute!触发的内容是【__dict__】
# # 执行的是getattr!触发的内容是【__dict__】
# # f1.__dict__:  None
# # -----------------------------------------------分割线222-----------------------------------------------
# # 执行的是getattribute!触发的内容是【name】
# # 执行的是getattr!触发的内容是【name】
# # f1.name:      None
# # 执行的是getattribute!触发的内容是【name99999999999】
# # 执行的是getattr!触发的内容是【name99999999999】
# # f1.name:      None
# # -----------------------------------------------分割线333-----------------------------------------------
# # 执行的是getattribute!触发的内容是【__dict__】
# # 执行的是getattr!触发的内容是【__dict__】
# # f1.__dict__:  None
# #
# # Process finished with exit code 0













'''
# ------------------------------------------------------------
# # 12、 __getattribute__与__getattr__总结
(采用系统默认的方式)自己定义的类中没有 __getattribute__与__getattr__:
__getattr__       __getattr__触发的前提是属性调用不存在的情况
__getattribute__  不会触发

(自定义)方式一,自己定义的类中没有 __getattribute__,但是有__getattr__:
__getattr__       __getattr__触发的前提是属性调用不存在的情况,触发的内容根据自己所定义的
__getattribute__  不会触发

(自定义)方式二,自己定义的类中有 __getattribute__,但是没有__getattr__:
__getattribute__  情况一:没有raise AttributeError,不论调用的属性内容是否存在,都会触发该内容
                  情况二:有raise AttributeError,  不论调用的属性内容是否存在,都会触发该内容,
                        在运行到AttributeError时,会都会执行,这个时候,报错

(自定义)方式三,自己定义的类中有 __getattribute__,有__getattr__:
__getattribute__  情况一:没有raise AttributeError,不论调用的属性内容是否存在,都会触发__getattribute__,但是不会__getattr__
                            __getattribute__,__getattr__中只有__getattribute__会执行      
                  情况二:raise AttributeError,  不论调用的属性内容是否存在,都会触发__getattribute__,
                          在运行到AttributeError时,会都会执行,这个时候,会将AttributeError报错的内容触发__getattr__
                          此时,  __getattribute__,__getattr__都会执行           

# ------------------------------------------------------------
'''

# ------------------------------------------------分割线-------------------------------------------------
# 05 item系列
# 05 item系列
#

'''
# ------------------------------------------------------------
# # 13、__setitem__设置属性,
# # # f1["age"]  = 18 这种方式才回触发__setitem__
# # # __setitem__操作的是[], 注意与前面的__setattr__区别
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __setitem__(self, key, value):
#         print("【__setitem__】 ")
#         self.__dict__[key] = value
#
# f1 = Foo()
# print("f1.__dict__: ", f1.__dict__)
#
# # “.”的方式进行添加
# f1.name = 'egon'
# print("f1.__dict__: ", f1.__dict__)
#
# # 类似于字典的方式添加
# f1["age"]  = 18                     # 这种方式才会触发setitem
# print("f1.__dict__: ", f1.__dict__)
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # f1.__dict__:  {}
# # f1.__dict__:  {'name': 'egon'}
# # 【__setitem__】
# # f1.__dict__:  {'name': 'egon', 'age': 18}
# #
# # Process finished with exit code 0







'''
# ------------------------------------------------------------
# # 14、__delitem__
# # # del f1['age'] 这种方式才会触发 __delitem__
# # # __setitem__操作的是[], 注意与前面的__delattr__区别
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name, age, domicile):
#         self.name = name
#         self.age = age
#         self.domicile = domicile
#
#     def __setitem__(self, key, value):
#         self.__dict__[key] = value
#         print("【__setitem__】,属性添加成功!!")
#
#     def __delitem__(self, key):
#         print("【__delitem__】 ")
#         self.__dict__.pop(key)          # 汪意, 这里是花括号
#
# f1 = Foo("张哈", 22, "北京")
# f1["sex"] = "male"
# print("f1.__dict__: ", f1.__dict__)
#
# print("==>>del f1.domicile")
# del f1.domicile
# print("==>>del f1['age']")
# del f1['age']
#
# print("f1.__dict__: ", f1.__dict__)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 【__setitem__】,属性添加成功!!
# # f1.__dict__:  {'name': '张哈', 'age': 22, 'domicile': '北京', 'sex': 'male'}
# # ==>>del f1.domicile
# # ==>>del f1['age']
# # 【__delitem__】
# # f1.__dict__:  {'name': '张哈', 'sex': 'male'}
# #
# # Process finished with exit code 0









'''
# ------------------------------------------------------------
# # 15、__getitem__
# # # f1["age"]这种方式才会触发 __getitem__
# # # __getitem__[], 注意与前面的__getattr__区别
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name, age, domicile):
#         self.name = name
#         self.age = age
#         self.domicile = domicile
#     def __getitem__(self, item):
#         print("【getitem】 ", item)
#         return self.__dict__[item]
#
#     def __setitem__(self, key, value):
#         self.__dict__[key] = value
#         print("【__setitem__】,属性添加成功!!")
#
#     def __delitem__(self, key):
#         print("【__delitem__】己经删除%s =  %s" % (key, self.__dict__[key]))
#         self.__dict__.pop(key)          # 汪意, 这里是花括号
#
#
# f1 = Foo("张哈", 22, "北京")
# f1["sex"] = "male"
# print("f1.__dict__: ", f1.__dict__)
# f1["age"]
# del f1["domicile"]
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 【__setitem__】,属性添加成功!!
# # f1.__dict__:  {'name': '张哈', 'age': 22, 'domicile': '北京', 'sex': 'male'}
# # 【getitem】  age
# # 【__delitem__】己经删除domicile =  北京
# #
# # Process finished with exit code 0













'''
# ------------------------------------------------------------
# # 16、__str__
# # # 改变的是输出到窗口的信息, 与print(f2)   ,print(file) 对比
# # # str函数或者print函数--->obj.__str__()
# ------------------------------------------------------------
'''
#
# l = list('hello')
#
# print(l)
# file = open('test.txt', 'w')
# print(file)         # 输出的信息是默认的
#
# class Foo:
#     def __init__(self, name, age, domicile):
#         self.name = name
#         self.age = age
#         self.domicile = domicile
#
#     def __str__(self):
#         return "这是自定义的显示方式"
# class func:
#     pass
#
# f1 = Foo("tom", 22, "魔都")
# f2 = func()
#
# print(f1)           # 输出的信息是修改的
# print(f1.name)
#
# print(f2)           # 输出的信息是修改的
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # ['h', 'e', 'l', 'l', 'o']
# # <_io.TextIOWrapper name='test.txt' mode='w' encoding='cp936'>
# # 这是自定义的显示方式
# # tom
# # <__main__.func object at 0x0000000002975BA8>
# #
# # Process finished with exit code 0











'''
# ------------------------------------------------------------
# # 17、str(f1), f1.__str__()
# # # str(f1)--->f1.__str__()
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name, age, domicile):
#         self.name = name
#         self.age = age
#         self.domicile = domicile
#
#     def __str__(self):
#         return "这是自定义的显示方式"
#
# f1 = Foo("tom", 22, "魔都")
# print(f1)       # str(f1)--->f1.__str__()
#
# x = str(f1)     # str(f1)--->f1.__str__()
# print(x)
#
# y = f1.__str__()
# print(y)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 这是自定义的显示方式
# # 这是自定义的显示方式
# # 这是自定义的显示方式
# #
# # Process finished with exit code 0











'''
# ------------------------------------------------------------
# # 17.1、str(f1), f1.__str__()
# # # str(f1)--->f1.__str__()
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name, age, domicile):
#         self.name = name
#         self.age = age
#         self.domicile = domicile
#
#     def __str__(self):
#         return '名字是 %s  年龄是%s' %(self.name, self.age)
#
# f1 = Foo("tom", 22, "魔都")
# print(f1)       # str(f1)--->f1.__str__()
#
# x = str(f1)     # str(f1)--->f1.__str__()
# print(x)
#
# y = f1.__str__()
# print(y)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 名字是 tom  年龄是22
# # 名字是 tom  年龄是22
# # 名字是 tom  年龄是22
# #
# # Process finished with exit code 0







'''
# ------------------------------------------------------------
# # 18、repr
# # # repr 或者交互式解释器--->obj.__repr__()
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name, age, domicile):
#         self.name = name
#         self.age = age
#         self.domicile = domicile
#
#     def __repr__(self):
#         return '__repr__==>名字是 %s  年龄是%s' %(self.name, self.age)
#
# f1 = Foo("tom", 22, "魔都")
# print(f1)       # str(f1)--->f1.__str__()
#
# x = str(f1)     # str(f1)--->f1.__str__()
# print(x)
#
# y = f1.__str__()
# print(y)
# #
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # __repr__==>名字是 tom  年龄是22
# # __repr__==>名字是 tom  年龄是22
# # __repr__==>名字是 tom  年龄是22
# #
# # Process finished with exit code 0




'''
# ------------------------------------------------------------
# # 19、__str__ 与 __repr__
# # # 两者同时出现时,输出打印选择的是__str__
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, name, age, domicile):
#         self.name = name
#         self.age = age
#         self.domicile = domicile
#
#     def __str__(self):
#         return '__str__名字是 %s  年龄是%s' %(self.name, self.age)
#
#     def __repr__(self):
#         return '__repr__==>名字是 %s  年龄是%s' %(self.name, self.age)
#
# f1 = Foo("tom", 22, "魔都")
# print(f1)       # str(f1)--->f1.__str__()
#
# x = str(f1)     # str(f1)--->f1.__str__()
# print(x)
#
# y = f1.__str__()
# print(y)
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # __str__名字是 tom  年龄是22
# # __str__名字是 tom  年龄是22
# # __str__名字是 tom  年龄是22
# #
# # Process finished with exit code 0




'''
# ------------------------------------------------------------
# # 20、__str__与__repr__总结
# # # str函数或者print函数--->obj.__str__()
# # # repr或者交互式解释器--->obj.__repr__()
# # # 如果__str__没有被定义,那么就会使用__repr__来代替输出
# # # 两者同时出现时,输出打印选择的是__str__
# # # 注意:这俩方法的返回值必须是字符串,否则抛出异常
# ------------------------------------------------------------
'''






# ------------------------------------------------分割线-------------------------------------------------
# 07 自定制format
# 07 自定制format

'''
# ------------------------------------------------------------
# # 21、字符串.format
# # # 
# ------------------------------------------------------------
'''
#
# x = '{0}{0}{0}'.format("dog")
#
# y1 = "{} {}".format("hello", "world")           # 不设置指定位置,按默认顺序
# y2 = "{0} {1}".format("hello", "world")         # 设置指定位置
# y3 = "{1} {0} {1}".format("hello", "world")     # 设置指定位置
#
#
# print(" x ",  x)
# print("y1 ", y1)
# print("y2 ", y2)
# print("y3 ", y3)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# #  x  dogdogdog
# # y1  hello world
# # y2  hello world
# # y3  world hello world
# #
# # Process finished with exit code 0






'''
# ------------------------------------------------------------
# # 22、字符串.format的应用1
# # # 
# ------------------------------------------------------------
'''
#
# class Date:
#     def __init__(self, year, mon, day):
#         self.year = year
#         self.mon = mon
#         self.day = day
#
#
# d1 = Date(2018, 8, 1)
# x = '{0.year}{0.mon}{0.day}'.format(d1)
# y = '{0.year}:{0.mon}:{0.day}'.format(d1)
# z = '{0.year}-{0.mon}-{0.day}'.format(d1)
#
# print(x)
# print(y)
# print(z)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 201881
# # 2018:8:1
# # 2018-8-1
# #
# # Process finished with exit code 0










'''
# ------------------------------------------------------------
# # 22.1、format 与类中 __format__ 的关系
# # # 运行时,format 实际上就去调用“对应类”中的 __format__, __format__要有返回值
# ------------------------------------------------------------
'''

#
# class Date:
#     def __init__(self, year, mon, day):
#         self.year = year
#         self.mon = mon
#         self.day = day
#     def __format__(self, format_spec):
#         print("我执行啦!!")
#         print("format_spec: ", format_spec)
#
#         return "我才只要需要返回值这个事"
#
# class person:
#     def __init__(self, name,age):
#         self.name = name
#         self.age = age
#
#     def __format__(self, format_spec):
#         print("person类调用我,我执行啦!!")
#         print("person类调用我   format_spec: ", format_spec)
#
#         return "person类调用我, 我给个返回值"
#
# #
# d1 = Date(2018, 8, 1)
# print(format(d1,"这是什么鬼"))
#
# print("分割线".center(100,"-"))
# p1 = person("li",22)
# print(format(p1,"这是什么鬼"))
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 我执行啦!!
# # format_spec:  这是什么鬼
# # 我才只要需要返回值这个事
# # ------------------------------------------------分割线-------------------------------------------------
# # person类调用我,我执行啦!!
# # person类调用我   format_spec:  这是什么鬼
# # person类调用我, 我给个返回值
# #
# # Process finished with exit code 0









'''
# ------------------------------------------------------------
# # 23、format的应用 之 自定义格式
# # # 自定义输出日期的格式, 与前面 序号21 对比; 
# # # 运行时,format 实际上就去调用“对应类”中的 __format__, __format__要有返回值
# ------------------------------------------------------------
'''
#
# format_dic = {
#     'ymd':'{0.year}{0.mon}{0.day}',
#     'y:m:d': '{0.year}:{0.mon}:{0.day}',
#     'y-m-d':'{0.year}-{0.mon}-{0.day}'
# }
#
# class Date:
#     def __init__(self, year, mon, day):
#         self.year = year
#         self.mon = mon
#         self.day = day
#
#     def __format__(self, format_spec):
#         # format_spec给定的格式不存在,那么,我们给它一个默认的格式方式
#         if format_spec not in format_dic:
#             format_spec = "ymd"
#
#         # 取 format_spec == ymd ,则 'ymd':'{0.year}{0.mon}{0.day}'
#         tmp = format_dic[format_spec]
#         # '{0.year}{0.mon}{0.day}'.format(d1),这里实例化d1,d1 == self, 则 format会调用python默认的方式处理
#         print("__format__执行完成!")
#         return tmp.format(self)
# #
# d1 = Date(2018, 8, 1)
# print(format(d1,"ymd"))
# print(format(d1,"y-m-d"))
#
# print("分割线".center(100,"-"))
# print(format(d1,""))
# print(format(d1,"不存在"))
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # __format__执行完成!
# # 201881
# # __format__执行完成!
# # 2018-8-1
# # ------------------------------------------------分割线-------------------------------------------------
# # __format__执行完成!
# # 201881
# # __format__执行完成!
# # 201881
# #
# # Process finished with exit code 0








# 08 slots属性
# 08 slots属性



'''
# ------------------------------------------------------------
# # 24、__slots__介绍
# # # 1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
# # # 2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
# # # 3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__
# # # 当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个
# # # 字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给
# # # 实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
# # # 4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该
# # # 只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。
# # # 关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。           更多的是用来作为一个内存优化工具。
# # # ==>>
# # # 对于 __slots__ 我们关注的是,1、它的存在是为了节约内存; 2、它存在的类中,所有的
# # # 属性“全部”都取消了实例字典,只有类字典;   3、__slots__ 定以后的变量,不可以在添加新的值,
# # # 但是可以修改
# ------------------------------------------------------------
'''






'''
# ------------------------------------------------------------
# # 24.1、__slots__ 属性值添加
# ------------------------------------------------------------
'''
#
# class Foo:
#     __slots__ = 'name'        # 等价于 {'name':None}
#
# f1 = Foo()
# # 定义好的属性,进行值添加
# f1.name = 'egon'
# print(f1.name)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # egon
# #
# # Process finished with exit code 0








'''
# ------------------------------------------------------------
# # 24.2、__slots__ 属性值添加
# ------------------------------------------------------------
'''
#
# class Foo:
#     __slots__ = 'name'        # 等价于 {'name':None}
#
# f1 = Foo()
#
# # 添加新的属性
# f1.age = 33         # 报错, 不允许添加;    --->setattr----->f1.__dict__['age']=18  但是这里取消了实例的字典
# print(f1.age)
# print(f1.__dict__)  # 报错,没有该字典
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Traceback (most recent call last):
# #   File "D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py", line 1410, in <module>
# #     f1.age = 33
# # AttributeError: 'Foo' object has no attribute 'age'





'''
# ------------------------------------------------------------
# # 24.3、__slots__ 
# ------------------------------------------------------------
'''
#
# class Foo:
#     __slots__ = ['name', 'age']  # {'name':None,'age':None}
#
# f1 = Foo()
#
# f1.name ="cheng"
# f1.age = 33         # 不允许添加
#
# print(f1.name)
# print(f1.age)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # cheng
# # 33
# #
# # Process finished with exit code 0




#
# ------------------------------------------------分割线-------------------------------------------------
# 09 doc属性
# 09 doc属性

'''
# ------------------------------------------------------------
# # 24.4、 __doc__
# # # 该属性无法继承给子类;   如果没有对该属性进行赋值的话,那么默认是None
# ------------------------------------------------------------
'''
#
# class Foo:
#     '这个是Foo的描述作息'             # 这个应就是__doc__, 该属性无不法被子类所继承
#     pass
#
#
# class Bar(Foo):                       # 继承Foo类
#     pass
#
# print(Foo.__doc__)
# print(Bar.__doc__)
#
# print(Foo.__dict__)
# print(Bar.__dict__)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 这个是Foo的描述作息
# # None
# # {'__module__': '__main__', '__doc__': '这个是Foo的描述作息', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>}
# # {'__module__': '__main__', '__doc__': None}
# #
# # Process finished with exit code 0







#
# ------------------------------------------------分割线-------------------------------------------------
# 10 module和class
# 10 module和class

'''
# ------------------------------------------------------------
# # 25、 __module__ 与 __class__
# # # 
# # # __module__     表示当前操作的对象在那个模块
# # # __class__     表示当前操作的对象的类是什么

【类C的具体信息】:
当前文件路径:D:\C_cache\py\day27_MianXiangDuiXiangJinJie
类C 文件路径:D:\C_cache\py\day27_MianXiangDuiXiangJinJie\lib\aa.py

【aa.py文件内容】:
class C:
    def __init__(self):
        self.name = "啥呀"
# ------------------------------------------------------------
'''
#
# from lib.aa import C            # 导入类
#
# c1 = C()
# print(c1.name)
#
# print(c1.__module__)
# print(c1.__class__)
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 啥呀
# # lib.aa
# # <class 'lib.aa.C'>
# #
# # Process finished with exit code 0



# 11 析构方法
# 11 析构方法

'''
# ------------------------------------------------------------
# # 26、__del__析构方法介绍
# # # 
# # # 析构方法,当对象在内存中被释放时,自动触发执行。
# # # 注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,
# # # 如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,
# # # 比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就
# # # 用到了__del__
# ------------------------------------------------------------
'''





'''
# ------------------------------------------------------------
# # 27、__del__ 实例
# # # 运行结束之后,就会触发 __del__
# ------------------------------------------------------------
'''
#
#
# class Foo:
#     def __init__(self, name):
#         self.name = name
#
#     def __del__(self):
#         print("我是__del__,我执行结束了!!")
#
# f1 = Foo("什么鬼")
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 我是__del__,我执行结束了!!
# #
# # Process finished with exit code 0



'''
# ------------------------------------------------------------
# # 27.1、__del__ 实例1
# # # 情况一:程序运行结束之后,就会触发 __del__
# # # 情况2 :删除实例,就会触发 __del__
# ------------------------------------------------------------
'''
#
#
# class Foo:
#     def __init__(self, name):
#         self.name = name
#
#     def __del__(self):
#         print("我是__del__,我执行结束了!!")
#
# f1 = Foo("什么鬼")
# f2 = Foo("吃瓜")
# print("接下来执行,del f1.name  ")
# del f1.name         # 删除实例的属性不会触发__del__
# print("接下来执行,del f2  ")
# del f2              # 删除实例会触发__del__
#
# print("============》》》》》》》》》》》》》")
# # 程序运行完毕会自动回收内存,触发__del__
#
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 接下来执行,del f1.name
# # 接下来执行,del f2
# # 我是__del__,我执行结束了!!
# # ============》》》》》》》》》》》》》
# # 我是__del__,我执行结束了!!
# #
# # Process finished with exit code 0





#  12 call 方法
#  12 call 方法

'''
# ------------------------------------------------------------
# # 28、__call__ 的引入
# ------------------------------------------------------------
'''
#
# class Foo:
#     pass
#
# f1 = Foo()
#
# f1()            # 报错,TypeError: 'Foo' object is not callable;   说明f1()是可以被执行的
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Traceback (most recent call last):
# #   File "D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py", line 1630, in <module>
# #     f1()            # 报错,TypeError: 'Foo' object is not callable;   说明f1()是可以被执行的
# # TypeError: 'Foo' object is not callable
# #
# # Process finished with exit code 1










'''
# ------------------------------------------------------------
# # 28.1、__call__ 演示
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __call__(self, *args, **kwargs):
#         print("我是__call__,我执行了!!")
#
# f1 = Foo()
#
# f1()            # f1的类Foo 下的__call__
#
# Foo()           # Foo的类 xxx下的__call__
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 我是__call__,我执行了!!
# #
# # Process finished with exit code 0






# ------------------------------------------------分割线-------------------------------------------------
# 13 迭代器协议
# 13 迭代器协议

'''
# ------------------------------------------------------------
# # 29、迭代器的协议的引入
# # # (字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,
# # # 调用了他们内部的__iter__方法,把他们变成了可迭代对象;  而下面的类中,是一个对象,但是
# # # 并不是一个可迭代对象
# ------------------------------------------------------------
'''
#
# class Foo:
#     pass
#
# l = list("hello")
# for i in l:
#     print(i)
#
# f1 = Foo()
#
# for i in f1:         # TypeError: 'Foo' object is not iterable
#     print(i)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Traceback (most recent call last):
# #   File "D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py", line 1700, in <module>
# # h
# # e
# # l
# # l
# # o
# #     for i in f1:
# # TypeError: 'Foo' object is not iterable
# #
# # Process finished with exit code 1










'''
# ------------------------------------------------------------
# # 30、迭代器的协议
# # # (字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,
# # # 调用了他们内部的__iter__方法,把他们变成了可迭代对象;  
# # # 而下面的类中,是一个对象,在类中引入iter与next使它变成一个选代器
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __init__(self, n ):
#         self.n = n
#
#     def __iter__(self):
#         return self
#
#     def __next__(self):
#         if self.n == 13:
#             raise StopIteration("运行终止")
#         self.n +=1
#         return self.n
#
# l = list("hello")
# for i in l:
#     print(i)
#
# print("分割线".center(100,"-"))
# f1 = Foo(10)
# for i in f1:
#     print(i)
#
# print("分割线".center(100,"-"))
# f2 = Foo(8)
# print(f2.__next__(), next(f2))
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # h
# # e
# # l
# # l
# # o
# # ------------------------------------------------分割线-------------------------------------------------
# # 11
# # 12
# # 13
# # ------------------------------------------------分割线-------------------------------------------------
# # 9 10
# #
# # Process finished with exit code 0









# ------------------------------------------------分割线-------------------------------------------------
# 30 迭代器协议实现斐波那契数列
# 30 迭代器协议实现斐波那契数列

'''
# ------------------------------------------------------------
# # 30.1、迭代器协议实现斐波那契数列
# # # 斐波那契数列: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233...
# # # 
# ------------------------------------------------------------
'''
#
# class Fib:
#     def  __init__(self):
#         self._a = 1
#         self._b = 1
#
#     def __iter__(self):
#         return self
#
#     def __next__(self):
#         if self._a > 10:
#             raise StopIteration("终止了!")
#         '''
#         tmp = self._a
#         self._a = self._b
#         self._b = tmp + self._b
#         使用python的等价简洁表达方式如下
#
#         '''
#         self._a, self._b = self._b, self._a + self._b
#         return self._a
#
# f1 = Fib()
# f2 = Fib()
#
# for i in f1:
#     print(i,end=' ')
#
# print("\n")
# print(f2.__next__(), next(f2), next(f2), next(f2), next(f2), next(f2))
# next(f2)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 1 2 3 5 8 13
# #
# # 1 2 3 5 8 13
# # Traceback (most recent call last):
# #   File "D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py", line 1823, in <module>
# #     next(f2)
# #   File "D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py", line 1804, in __next__
# #     raise StopIteration("终止了!")
# # StopIteration: 终止了!
# #
# # Process finished with exit code 1




# ------------------------------------------------分割线-------------------------------------------------
# day27 描述符
# day27 描述符

'''
# ------------------------------------------------------------
# # 31、描述符的介绍
# # # 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
# # #__get__():调用一个属性时,触发
# # #__set__():为一个属性赋值时,触发
# # #__delete__():采用del删除属性时,触发
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# ------------------------------------------------------------
'''






'''
# ------------------------------------------------------------
# # 31.1、定义一个描述符
# # #  在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
# ------------------------------------------------------------
'''
#
# class Foo :
#     def __get__(self, instance, owner):
#         pass
#
#     def __set__(self, instance, value):
#         pass
#
#     def __delete__(self, instance):
#         pass








'''
# ------------------------------------------------------------
# # 32、描述符与实例的关系
# # # 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这
# # # 个类的类属性,不能定义到构造函数中
# ------------------------------------------------------------
'''
#
# class Foo :
#     ''' 这是一个描述符类 '''
#     def __get__(self, instance, owner):
#         print("触发get")
#
#     def __set__(self, instance, value):
#         print("触发set")
#
#     def __delete__(self, instance):
#         print("触发delete")
#
#
# # 包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,
# # 并不会触发这三个方法
# f1 = Foo()
# print(f1.__dict__
# )
# f1.name = 'egon'
# f1.age = 22
# f1.name
# del f1.name
#
# print(f1.__dict__)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # {}
# # {'age': 22}
# #
# # Process finished with exit code 0









'''
# ------------------------------------------------------------
# # 33、描述符的的使用
# # # 注意到,下面的实例的数值数属是  类级别的
# ------------------------------------------------------------
'''
#
# # 描述符Str
# class Str:
#     def __get__(self, instance, owner):
#         print("Str调用了get")
#
#     def __set__(self, instance, value):
#         print("Str调用了set")
#
#     def __delete__(self, instance):
#         print("Str调用了delete")
#
# # 描述符 Int
# class Int:
#     def __get__(self, instance, owner):
#         print("Int调用了get")
#
#     def __set__(self, instance, value):
#         print("Int调用了set")
#
#     def __delete__(self, instance):
#         print("Int调用了delete")
#
# class People:
#     name = Str()
#     age  = Int()
#     def __init__(self, name, age ):
#         self.name = name
#         self.age = age
#
# p1 = People("alex", 22)
# print("p1.__dict__:     ", p1.__dict__)
# print("People.__dict__: ", People.__dict__)
#
# print("分割线111".center(100,"-"))
# # 描述符Str的分割线使用
# p1.name
# p1.name = 'egon'
#
# # 描述符Int的使用
# print("分割线222".center(100,"-"))
# p1.age
# p1.age = 11
#
# print("分割线333".center(100,"-"))
# print("p1.__dict__:     ", p1.__dict__)
# print("People.__dict__: ", People.__dict__)
# print("p1.age:      ", p1.age)
# print("p1.name:     ", p1.name)
#
# del p1.name
# del p1.age
#
# print("分割线444".center(100,"-"))
# print("p1.__dict__:     ", p1.__dict__)
# print("People.__dict__: ", People.__dict__)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Str调用了set
# # Int调用了set
# # p1.__dict__:      {}
# # People.__dict__:  {'__module__': '__main__', 'name': <__main__.Str object at 0x0000000002955EF0>, 'age': <__main__.Int object at 0x0000000002965C88>, '__init__': <function People.__init__ at 0x00000000039EF9D8>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
# # -----------------------------------------------分割线111-----------------------------------------------
# # Str调用了get
# # Str调用了set
# # -----------------------------------------------分割线222-----------------------------------------------
# # Int调用了get
# # Int调用了set
# # -----------------------------------------------分割线333-----------------------------------------------
# # p1.__dict__:      {}
# # People.__dict__:  {'__module__': '__main__', 'name': <__main__.Str object at 0x0000000002955EF0>, 'age': <__main__.Int object at 0x0000000002965C88>, '__init__': <function People.__init__ at 0x00000000039EF9D8>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
# # Int调用了get
# # p1.age:       None
# # Str调用了get
# # p1.name:      None
# # Str调用了delete
# # Int调用了delete
# # -----------------------------------------------分割线444-----------------------------------------------
# # p1.__dict__:      {}
# # People.__dict__:  {'__module__': '__main__', 'name': <__main__.Str object at 0x0000000002955EF0>, 'age': <__main__.Int object at 0x0000000002965C88>, '__init__': <function People.__init__ at 0x00000000039EF9D8>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
# #
# # Process finished with exit code 0








'''
# ------------------------------------------------------------
# # 33.1、含有描述符的实例与类的关系
# ------------------------------------------------------------
'''
#
# # 描述符Str
# class Str:
#     def __get__(self, instance, owner):
#         print("Str调用了get")
#
#     def __set__(self, instance, value):
#         print("Str调用了set")
#
#     def __delete__(self, instance):
#         print("Str调用了delete")
#
# # 描述符 Int
# class Int:
#     def __get__(self, instance, owner):
#         print("Int调用了get")
#
#     def __set__(self, instance, value):
#         print("Int调用了set")
#
#     def __delete__(self, instance):
#         print("Int调用了delete")
#
# class People:
#     name = Str()
#     age  = Int()
#     def __init__(self, name, age ):
#         self.name = name
#         self.age = age
#
#
# p1 = People("alex", 22)
#
# print("分割线11".center(100,"-"))
# print("p1.__dict__:     ", p1.__dict__)
# print("People.__dict__: ", People.__dict__)
#
# print("分割线22".center(100,"-"))
# print("type(p1):    ", type(p1))       # type(obj)其实是查看obj是由哪个类实例化来的
# print(type(p1) == People)
# print(type(p1).__dict__ == People.__dict__)         # 被修饰后,p1的字典是等价于类的
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Str调用了set
# # Int调用了set
# # -----------------------------------------------分割线11------------------------------------------------
# # p1.__dict__:      {}
# # People.__dict__:  {'__module__': '__main__', 'name': <__main__.Str object at 0x000000000295A438>, 'age': <__main__.Int object at 0x0000000002965BE0>, '__init__': <function People.__init__ at 0x00000000039EF9D8>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
# # -----------------------------------------------分割线22------------------------------------------------
# # type(p1):     <class '__main__.People'>
# # True
# # True
# #
# # Process finished with exit code 0











'''
# ------------------------------------------------------------
# # 34、描述符之一,数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 一 数据描述符:至少实现了__get__()和__set__()
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __set__(self, instance, value):
#         print("set")
#
#     def __get__(self, instance, owner):
#         print("get")
#






'''
# ------------------------------------------------------------
# # 35、描述符之二,非数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------
'''
#
# class Foo:
#     def __get__(self, instance, owner):
#         print("get")
#







'''
# ------------------------------------------------------------
# # 36、描述符之优先级别,类属性>数据描述
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------
'''
#
# #描述符Str
# class Str:
#     def __get__(self, instance, owner):
#         print('Str调用')
#     def __set__(self, instance, value):
#         print('Str设置...')
#     def __delete__(self, instance):
#         print('Str删除...')
#
# # 描述符 Int
# class Int:
#     def __get__(self, instance, owner):
#         print("Int调用了get")
#
#     def __set__(self, instance, value):
#         print("Int调用了set")
#
#     def __delete__(self, instance):
#         print("Int调用了delete")
#
# class People:
#     name=Str()
#     age = Int()
#     def __init__(self,name,age): #name被Str类代理,age被Int类代理,
#         self.name=name
#         self.age=age
#
#
# #基于上面的演示,我们已经知道,在一个类中定义描述符它就是一个类属性,存在于类的属性字典中,而不是实例的属性字典
#
# #那既然描述符被定义成了一个类属性,直接通过类名也一定可以调用吧,没错
# People.name # 恩,调用类属性name,本质就是在调用描述符Str,触发了__get__()
#
# People.name='egon' #那赋值呢,我去,并没有触发__set__()
# del People.name #赶紧试试del,我去,也没有触发__delete__()
# # 结论:描述符对类没有作用-------->傻逼到家的结论
#
'''
原因:描述符在使用时被定义成另外一个类的类属性,因而类属性比二次加工的描述符伪装而来的类属性有更高的优先级
People.name #恩,调用类属性name,找不到就去找描述符伪装的类属性name,触发了__get__()

People.name='egon' #那赋值呢,直接赋值了一个类属性,它拥有更高的优先级,相当于覆盖了描述符,肯定不会触发描述符的__set__()
del People.name #同上
'''
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Str调用
# #
# # Process finished with exit code 0









'''
# ------------------------------------------------------------
# # 36.1、描述符之优先级别,类属性>数据描述
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------
'''
#
# # 描述符Str
# class Str:
#     def __get__(self, instance, owner):
#         print('Str调用')
#
#     def __set__(self, instance, value):
#         print('Str设置...')
#
#     def __delete__(self, instance):
#         print('Str删除...')
#
#
# class People:
#     name=Str()
#
#     def __init__(self,name,age):    # name被Str类代理
#         self.name=name
#         self.age=age
#
#
# p1=People('egon',18)
#
# print("分割线11".center(100,"-"))
# # 如果描述符是一个数据描述符(即有__get__又有__set__),那么p1.name的调用与赋值都是触发
# # 描述符的操作,于p1本身无关了,相当于覆盖了实例的属性
# p1.name='egonnnnnn'
#
# print("分割线22".center(100,"-"))
# p1.name
#
# print("分割线33".center(100,"-"))
# # 实例的属性字典中没有name,因为name是一个数据描述符,优先级高于实例属性,查看/赋值/删除都是
# # 跟描述符有关,与实例无关了
# print(p1.__dict__)
# del p1.name
#
# # D:\Anaconda3\python.exe D:/C_cache/py/cache.py
# # Str设置...
# # -----------------------------------------------分割线11------------------------------------------------
# # Str设置...
# # -----------------------------------------------分割线22------------------------------------------------
# # Str调用
# # -----------------------------------------------分割线33------------------------------------------------
# # {'age': 18}
# # Str删除...
# #
# # Process finished with exit code 0








'''
# ------------------------------------------------------------
# # 36.1.1、描述符之优先级别,类属性>数据描述
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------
'''
#
# # 描述符Str
# class Str:
#     def __get__(self, instance, owner):
#         print('Str调用')
#
#     # def __set__(self, instance, value):
#     #     print('Str设置...')
#     #
#     # def __delete__(self, instance):
#     #     print('Str删除...')
#
#
# class People:
#     name = Str()
#
#     def __init__(self, name, age):  # name被Str类代理,
#         self.name = name
#         self.age = age
#
#
# p1 = People('egon', 18)
#
# # 如果描述符是一个数据描述符(即有__get__又有__set__),那么p1.name的调用与赋值都是触发
# # 描述符的操作,于p1本身无关了,相当于覆盖了实例的属性;
# # 如果只有__get__的话,那么就是不会触发描述符, 进行的赋值操作会对实例的字典进行操作
# p1.name = 'egonnnnnn'
# p1.name
# print(p1.__dict__)  # 实例的属性字典中没有name,因为name是一个数据描述符,优先级高于实例属性,查看/赋值/删除都是跟描述符有关,与实例无关了
# del p1.name
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # Str设置...
# # Str设置...
# # Str调用
# # {'age': 18}
# # Str删除...
# #
# # Process finished with exit code 0
#








'''
# ------------------------------------------------------------
# # 36.2、描述符之优先级别,实例属性>非数据描述符
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------
'''
#
# class Foo:
#     def func(self):
#         print('我胡汉三又回来了')
#
#
# f1 = Foo()
# f1.func()  # 调用类的方法,也可以说是调用非数据描述符
# # 函数是一个非数据描述符对象(一切皆对象么)
#
# print("分割线11".center(100,"-"))
# print(dir(Foo.func))
# print(hasattr(Foo.func, '__set__'))
# print(hasattr(Foo.func, '__get__'))
# print(hasattr(Foo.func, '__delete__'))
# # 有人可能会问,描述符不都是类么,函数怎么算也应该是一个对象啊,怎么就是描述符了
# # 笨蛋哥,描述符是类没问题,描述符在应用的时候不都是实例化成一个类属性么
# # 函数就是一个由非描述符类实例化得到的对象
# # 没错,字符串也一样
#
# print("分割线22".center(100,"-"))
# print("Foo.__dict__:    ", Foo.__dict__)
# print("f1.__dict__:     ", f1.__dict__)
#
# print("分割线33".center(100,"-"))
# # 对实例 f1 生成数据数性 func; 注意,类中有一个己已经定义好的函数属属性 def func()
# f1.func = '这是实例属性啊'
# # =========>>>>>>这里,类的属性与实例中,都是func;
# # =========>>>>>>不过类中的是非数据属性,实例中的是数据属性
# print(f1.func)
#
# print("分割线44".center(100,"-"))
# print("Foo.__dict__:    ", Foo.__dict__)    # 'func': <function Foo.func at 0x0000000001CF1EA0>,
# print("f1.__dict__:     ", f1.__dict__)     # {'func': '这是实例属性啊'}
#
# print("分割线55".center(100,"-"))
# del f1.func  # 删掉了非数据
# f1.func()
#
# print("分割线66".center(100,"-"))
# print("Foo.__dict__:    ", Foo.__dict__)
# print("f1.__dict__:     ", f1.__dict__)
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 我胡汉三又回来了
# # -----------------------------------------------分割线11------------------------------------------------
# # ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
# # False
# # True
# # False
# # -----------------------------------------------分割线22------------------------------------------------
# # Foo.__dict__:     {'__module__': '__main__', 'func': <function Foo.func at 0x0000000001D11EA0>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # f1.__dict__:      {}
# # -----------------------------------------------分割线33------------------------------------------------
# # 这是实例属性啊
# # -----------------------------------------------分割线44------------------------------------------------
# # Foo.__dict__:     {'__module__': '__main__', 'func': <function Foo.func at 0x0000000001D11EA0>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # f1.__dict__:      {'func': '这是实例属性啊'}
# # -----------------------------------------------分割线55------------------------------------------------
# # 我胡汉三又回来了
# # -----------------------------------------------分割线66------------------------------------------------
# # Foo.__dict__:     {'__module__': '__main__', 'func': <function Foo.func at 0x0000000001D11EA0>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # f1.__dict__:      {}
# #
# # Process finished with exit code 0
#









'''
# ------------------------------------------------------------
# # 36.3、描述符之优先级别,实例属性>非数据描述符( 再次验证1 )
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------
'''
#
# class Foo:
#
#     def __set__(self, instance, value):
#         '''
#
#         :param instance:    r1,所修饰的对象中所产生的寮例  <__main__.Room object at 0x00000000029A5F28>
#         :param value:       '厕所'
#         :return:
#         '''
#         print('【set】')
#         print('==>>self', self)          # <__main__.Foo object at 0x000000000210C278>
#         print('==>>instance', instance)  # r1,<__main__.Room object at 0x00000000029A5F28>
#         print('==>>value', value)        # '厕所'
#
#     def __get__(self, instance, owner):
#         print('【get】')
#
#
# class Room:
#     name = Foo()            # 相当于对Foo过行了实例化,Foo的括号默认传入 self.name
#
#     def __init__(self, name, width, length):
#         self.name = name
#         self.width = width
#         self.length = length
#
#
# # name是一个数据描述符,因为name=Foo()而Foo实现了get和set方法,因而比实例属性有更高的优先级
# # 对实例的属性操作,触发的都是描述符的
#
# r1 = Room('厕所', 1, 1)
#
# print("分割线111".center(100,"-"))
# print("Room.__dict__:    ", Room.__dict__)
# print("r1.__dict__:     ", r1.__dict__)
# print("r1", r1)             # r1 <__main__.Room object at 0x0000000002975C50>
#
# print("分割线222".center(100,"-"))
# print("==>>r1.name", r1.name)
# r1.name
# r1.name = '厨房'
# print("=======>>>r1.name", r1.name)
#
# print("分割线333".center(100,"-"))
# print("Room.__dict__:    ", Room.__dict__)
# print("r1.__dict__:     ", r1.__dict__)
#
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 【set】
# # ==>>self <__main__.Foo object at 0x00000000020CC278>
# # ==>>instance <__main__.Room object at 0x0000000002975C88>
# # ==>>value 厕所
# # -----------------------------------------------分割线111-----------------------------------------------
# # Room.__dict__:     {'__module__': '__main__', 'name': <__main__.Foo object at 0x00000000020CC278>, '__init__': <function Room.__init__ at 0x00000000039EF7B8>, '__dict__': <attribute '__dict__' of 'Room' objects>, '__weakref__': <attribute '__weakref__' of 'Room' objects>, '__doc__': None}
# # r1.__dict__:      {'width': 1, 'length': 1}
# # r1 <__main__.Room object at 0x0000000002975C88>
# # -----------------------------------------------分割线222-----------------------------------------------
# # 【get】
# # ==>>r1.name None
# # 【get】
# # 【set】
# # ==>>self <__main__.Foo object at 0x00000000020CC278>
# # ==>>instance <__main__.Room object at 0x0000000002975C88>
# # ==>>value 厨房
# # 【get】
# # =======>>>r1.name None
# # -----------------------------------------------分割线333-----------------------------------------------
# # Room.__dict__:     {'__module__': '__main__', 'name': <__main__.Foo object at 0x00000000020CC278>, '__init__': <function Room.__init__ at 0x00000000039EF7B8>, '__dict__': <attribute '__dict__' of 'Room' objects>, '__weakref__': <attribute '__weakref__' of 'Room' objects>, '__doc__': None}
# # r1.__dict__:      {'width': 1, 'length': 1}
# #
# # Process finished with exit code 0






'''
# ------------------------------------------------------------
# # 36.4、描述符之优先级别,实例属性>非数据描述符( 再次验证2 )
# # # 描述符分两种,一:数据描述符; 二:非数据描述符
# # # 二 非数据描述符:没有实现__set__()
# ------------------------------------------------------------
'''

#
# class Foo:
#     def __get__(self, instance, owner):
#         print('get')
#
#
# class Room:
#     name = Foo()
#
#     def __init__(self, name, width, length):
#         self.name = name
#         self.width = width
#         self.length = length
#
#
# # name是一个非数据描述符,因为name=Foo()而Foo没有实现set方法,因而比实例属性有更低的优先级
# # 对实例的属性操作,触发的都是实例自己的
# r1 = Room('厕所', 1, 1)
#
# print("分割线".center(100,"-"))
# print("Foo.__dict__:    ", Foo.__dict__)
# print("r1.__dict__:     ", r1.__dict__)
#
# print("分割线".center(100,"-"))
# r1.name
# r1.name = '厨房'
#
# print("Foo.__dict__:    ", Foo.__dict__)
# print("r1.__dict__:     ", r1.__dict__)
#
# # D:\Anaconda3\python.exe D:/C_cache/py/cache.py
# # ------------------------------------------------分割线-------------------------------------------------
# # Foo.__dict__:     {'__module__': '__main__', '__get__': <function Foo.__get__ at 0x00000000023A3620>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # r1.__dict__:      {'name': '厕所', 'width': 1, 'length': 1}
# # ------------------------------------------------分割线-------------------------------------------------
# # Foo.__dict__:     {'__module__': '__main__', '__get__': <function Foo.__get__ at 0x00000000023A3620>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
# # r1.__dict__:      {'name': '厨房', 'width': 1, 'length': 1}
# #
# # Process finished with exit code 0
#






'''
# ------------------------------------------------------------
# # 37、非数据描述符>找不到
# ------------------------------------------------------------
'''
#
# class Foo:
#     def func(self):
#         print("我回来了")
#
#     def __getattr__(self, item):
#         print("找不到了当然就来找我啦", item)
#
# f1 = Foo()
# f1.func()
# f1.xxxxxxx
# #
# # D:\Anaconda3\python.exe D:/C_cache/py/cache.py
# # 我回来了
# # 找不到了当然就来找我啦 xxxxxxx
# #
# # Process finished with exit code 0









'''
# ------------------------------------------------------------
# # 38、不同目录级别下的文件路径处理1
# # # 注:下面的这种方式的文件路径是没有处理的主,不建  讠义 使用;
运行的路径如下:
 D:\C_cache\py\day27_MianXiangDuiXiangJinJie\bin\bin.py
 
 lib.aa.py的路径如下:
 D:\C_cache\py\day27_MianXiangDuiXiangJinJie\lib\aa.py
 
 aa.py的内容如下:
def info():
    print("我是aa.py文件,欢迎来到到这里呀")
# ------------------------------------------------------------
'''
#
# # 在 pycharm编译器 中,它会自动帮你把文件路径进行处理,因为在建立工程项目文件的时候,pycharm
# # 会自动帮你把工程的文件路径加入运行的环境变量(sys.path)中,因此下面的运行时不会有
# # 任何的问题,但是到了  命令终端 之后,就会报错!因为运行的环境变量没有改变,找不到aa.py文件
# # 在命令终端的查找的过程如下:
# #     bin 目录下找lib 目录下的 aa.py —> 没有 -->报错
# # 在pycharm编译器中查找的过程如下:
# #     bin 目录下找lib 目录下的 aa.py —> 没有 --> sys.path查找 --> 找到lib下的aa.py(建立工程的时候pychar自动把工程下的文件路径加入运行的环境变量中)
#
# from lib import aa
# aa.info()
#
#
# D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# 我是aa.py文件,欢迎来到到这里呀
#
# Process finished with exit code 0







'''
# ------------------------------------------------------------
# # 38.1、不同目录级别下的文件路径处理2
# # # 注:下面的这种方式的文件路径是进行了处理,建  讠义  使用;这样,当工程文件的拷贝到了不同的止录下,
# # #   都是可以使用的

运行的路径如下:
 D:\C_cache\py\day27_MianXiangDuiXiangJinJie\bin\bin.py

 lib.aa.py的路径如下:
 D:\C_cache\py\day27_MianXiangDuiXiangJinJie\lib\aa.py

 aa.py的内容如下:
def info():
    print("我是aa.py文件,欢迎来到到这里呀")
# ------------------------------------------------------------
'''
#
# # 在pycharm编译器中,它会自动帮你把文件路径进行处理因此下面的运行时不会有任何的问题,但是到了
# # 命令终端之后,就会报错!因为运行的环境变量没有改变,找不到aa.py文件
# import os, sys
# BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# # print(BASE_DIR)
# sys.path.append(BASE_DIR)
# from lib import aa
# aa.info()
#
# # D:\Anaconda3\python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
# # 我是aa.py文件,欢迎来到到这里呀
# #
# # Process finished with exit code 0