zoukankan      html  css  js  c++  java
  • day28-描述符应用与类的装饰器

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # ------------------------------------------------------------
    #
    # 参考资料:
    # 面向对象进阶 - linhaifeng - 博客园
    # https://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12
    #
    # python之函数介绍及使用 - 病毒尖er - 博客园
    # http://www.cnblogs.com/leguan1314/articles/6116928.html
    #
    # 元类metaclass - linhaifeng - 博客园
    # http://www.cnblogs.com/linhaifeng/articles/8029564.html
    #
    # ------------------------------------------------------------
    # ******************** day28-描述符应用与类的装饰器 *******************
    # ******************** day28-描述符应用与类的装饰器 *******************
    # =====>>>>>>内容概览
    # =====>>>>>>内容概览
    # Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi

    '''
    # ------------------------------------------------------------
    # # 1、总结:
    # # # hasattr, getattr, setattr;;  getitem, setitem, delitem;; set, get, delete;; __del__
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 2、 __enter__ 与 __exit__
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3、 __enter__ 与 __exit__ 之文件异常引入
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3.1、 __enter__ 与 __exit__ 之文件异常引入1
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3.2、 __exit__ 中 exc_type, exc_val, exc_tb 之文件异常引入1
    # # # __exit__ 中的 exc_type, exc_val, exc_tb 就是文件异常的信息内容
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3.3、 __exit__ 中 exc_type, exc_val, exc_tb 之文件异常
    # # # __exit__ 中的 exc_type, exc_val, exc_tb 就是文件异常的信息内容
    # # # __exit__ 中的返回值设置为True时,文件的异常会结束该文件内容的操作,但是对于
    # # # 该操作外的操作信息不会有所影响,仍能够正常运行 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3.4、总结 __enter__ 与 __exit__ 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 4、描述符的应用的引入
    # # # test给定的参数中,如果是字符串或者整形数字就输出,否则留报错!显然,
    # # # 下面的例子中,是不能够满足该要求的;  下面关于描述符的应用就是为了解决该问题
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 5、描述符中 __set__ 中的各个参数
    # # # __set__中的各个参数:
    # # # instance : 修饰的实例本身(下例中,就是实例p1)
    # # # value    :实例中修饰的那个值(下例中,就是 alex)
    # # # self     :描述符所在的类本身
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 6、描述符中 __get__ 中的各个参数
    # # # __get__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # # # owner    :修饰的实例所属的类(下例中,是类People)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 6.1、描述符中 __get__ 中的各个参数
    # # # __get__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # # # owner    :修饰的实例所属的类(下例中,是类People)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 6.2、描述符中 __delete__ 中的各个参数
    # # # __delete__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 7、__set__  使用描述符给给定的实例中传入值  
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 8、__set__  使用描述符对给定的实例 获取对应的值  
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 9、使用描述符对给定的实例 的值的设定进行限制1
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 9.1、使用描述符对给定的实例 的值的设定进行限制2
    # # # 对类进行修饰的时候,直接指定数值属性的  类型 ,如name 是str类型
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 10、装饰器的引入,修饰函数
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 11、装饰器修饰 类
    # # # 类中的装饰器的运行的情况,是跟上面的函数的装饰器是有所区别的; 类中的是下运行类,之后再运行装饰器的运行
    # # # 而函数中的,是先运行装饰器中的内容,之后再运行函数的内容
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 12、函数也是有字典的
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 12.1、给函数的字典添加属性
    # # # 函数也可以像类一像添加属性,因为函数的本质就是类;python中的一切都是对像
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 13、使用装饰器给类中的字典添加属性
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 14、使用装饰器给类中的字典添加属性
    # # # 只能在装饰器中内部给定值的情况
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 14.1、使用装饰器给类中的字典添加属性1
    # # # 解决只能在装饰器中内部给定值的情况
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 15、装饰器的应用(与前面的序号10对比)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 16、property 的使用
    # # # property() 函数的作用是在新式类中返回属性值。
    # # # 下面例子中,(原)r1.area()-->>(现)r1.area 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 17、property引入 , 类的装饰器
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18、property装饰器初步 , 类的装饰器
    # # # print(r1.area.func(r1))   实现了基本的装饰器功能
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18.1、property装饰器初步之 __get__ , 类的装饰器
    # # # 目标: print(r1.area.func(r1)) ==>> 等价于执行   print(r1.area) 
    # # # __get__ 接受被修饰对象中的实例, 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18.2、property装饰器“实现”之 __get__ 返回运行的内容, 类的装饰器
    # # # 目标(实现): print(r1.area.func(r1)) ==>> 等价于执行   print(r1.area) 
    # # # __get__ 接受被修饰对象中的实例, 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18.3、property装饰器“实现” (简洁版)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18.4、property装饰器“实现” (简洁版) 与 内置的property装饰器对比1
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 19、property装饰器,之类调用静态属性 对比
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 19.1、property装饰器,之类调用静态属性,实现property的完整功能( 类无法调用静态属性)
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 20、__name__获取函数的名字
    # # # 用来获取运行的模块的名字,  或者对应的对象的名字(类是获取不到名字的)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 21、property装饰器,之类调用静态属性,实现property的完整功能
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 21.1、元类的引入
    # # # python中一切皆为对象。类的本身也是一个对象,由 type 产生
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 22、type 元类来产生 类

    # # # FFo = type("FFo", (object,), {'x': 1})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3:{'x': 1},    类的属性字典
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 22.1、type 元类来产生 类
    # # # 给类中添加类的初始化属数,类的数值属性, 类的函数属性

    # # # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3: {'x':1, '__init__':__init__, 'test':test},    类的属性字典
    # # # 'x':1  相当于在类中定义数值属性   x = 1
    # # # '__init__':__init__  相当于在类中定义类初化始的函数属性   def __init__(self)
    # # # 'test':test          相当于在类中定义类的函数属性   def test(self)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 22.2、type 元类产生的类进行  实例化
    # # # 给类中添加类的初始化属数,类的数值属性, 类的函数属性

    # # # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3: {'x':1, '__init__':__init__, 'test':test},    类的属性字典
    # # # 'x':1  相当于在类中定义数值属性   x = 1
    # # # '__init__':__init__  相当于在类中定义类初化始的函数属性   def __init__(self)
    # # # 'test':test          相当于在类中定义类的函数属性   def test(self)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 22.3、类的产生总结
    # # # 类的产生有两种方式,1、通过 class来定义类;       2、通过type来产生类
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 23、自定义元类引入,元类定义自己的元类type
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 24、自定义元类引入,__call__ 方法介绍
    # # # 实例运加括号的时候,即实例 f1() 时候,会触发所属的类中的 __call__方法
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 24.1、自定义元类引入,__call__ 方法介绍
    # # # 实例运加括号的时候,即实例 f1() 时候,会触发所属的类中的 __call__方法
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.1、自定义元类引入1,元类定义自己的元类type
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.2、自定义元类引入2,元类定义自己的元类type
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.3、自定义元类引入2( 实例传入的内容信息),自定义元类中的 __call__ 方法
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    # # # __call__ 接收着,我们使用 Foo类 进行实例化时候的信息
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.3、自定义元类实现,自定义元类中的 __call__ 方法
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):

    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.4、自定义元类实现(简洁版)
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    # ------------------------------------------------------------

    '''

     

    # ------------------------------------------------分割线-------------------------------------------------
    # ------------------------------------------------分割线-------------------------------------------------
    # ------------------------------------------------分割线-------------------------------------------------
    # ------------------------------------------------------------
    # # 1、总结:
    # # # hasattr, getattr, setattr;;  getitem, setitem, delitem;; set, get, delete;; __del__
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 2、 __enter__ 与 __exit__
    # # # 这个使用的方法是类似于 with open() as 文件名;
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 3、 __enter__ 与 __exit__ 之文件异常引入
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # # # 这个使用的方法是类似于 with open() as 文件名;
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 3.1、 __enter__ 与 __exit__ 之文件异常引入1
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # # # 这个使用的方法是类似于 with open() as 文件名;
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 3.2、 __exit__ 中 exc_type, exc_val, exc_tb 之文件异常引入1
    # # # __exit__ 中的 exc_type, exc_val, exc_tb 就是文件异常的信息内容
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 3.3、 __exit__ 中 exc_type, exc_val, exc_tb 之文件异常
    # # # __exit__ 中的 exc_type, exc_val, exc_tb 就是文件异常的信息内容
    # # # __exit__ 中的返回值设置为True时,文件的异常会结束该文件内容的操作,但是对于
    # # # 该操作外的操作信息不会有所影响,仍能够正常运行
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 3.4、总结 __enter__ 与 __exit__
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 4、描述符的应用的引入
    # # # test给定的参数中,如果是字符串或者整形数字就输出,否则留报错!显然,
    # # # 下面的例子中,是不能够满足该要求的;  下面关于描述符的应用就是为了解决该问题
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 5、描述符中 __set__ 中的各个参数
    # # # __set__中的各个参数:
    # # # instance : 修饰的实例本身(下例中,就是实例p1)
    # # # value    :实例中修饰的那个值(下例中,就是 alex)
    # # # self     :描述符所在的类本身
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 6、描述符中 __get__ 中的各个参数
    # # # __get__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # # # owner    :修饰的实例所属的类(下例中,是类People)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 6.1、描述符中 __get__ 中的各个参数
    # # # __get__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # # # owner    :修饰的实例所属的类(下例中,是类People)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 6.2、描述符中 __delete__ 中的各个参数
    # # # __delete__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 7、__set__  使用描述符给给定的实例中传入值
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 8、__set__  使用描述符对给定的实例 获取对应的值
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 9、使用描述符对给定的实例 的值的设定进行限制1
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 9.1、使用描述符对给定的实例 的值的设定进行限制2
    # # # 对类进行修饰的时候,直接指定数值属性的  类型 ,如name 是str类型
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 10、装饰器的引入,修饰函数
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 11、装饰器修饰 类
    # # # 类中的装饰器的运行的情况,是跟上面的函数的装饰器是有所区别的; 类中的是下运行类,之后再运行装饰器的运行
    # # # 而函数中的,是先运行装饰器中的内容,之后再运行函数的内容
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 12、函数也是有字典的
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 12.1、给函数的字典添加属性
    # # # 函数也可以像类一像添加属性,因为函数的本质就是类;python中的一切都是对像
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 13、使用装饰器给类中的字典添加属性
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 14、使用装饰器给类中的字典添加属性
    # # # 只能在装饰器中内部给定值的情况
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 14.1、使用装饰器给类中的字典添加属性1
    # # # 解决只能在装饰器中内部给定值的情况
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 15、装饰器的应用(与前面的序号10对比)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 16、property 的使用
    # # # property() 函数的作用是在新式类中返回属性值。
    # # # 下面例子中,(原)r1.area()-->>(现)r1.area
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 17、property引入 , 类的装饰器
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 18、property装饰器初步 , 类的装饰器
    # # # print(r1.area.func(r1))   实现了基本的装饰器功能
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 18.1、property装饰器初步之 __get__ , 类的装饰器
    # # # 目标: print(r1.area.func(r1)) ==>> 等价于执行   print(r1.area)
    # # # __get__ 接受被修饰对象中的实例,
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 18.2、property装饰器“实现”之 __get__ 返回运行的内容, 类的装饰器
    # # # 目标(实现): print(r1.area.func(r1)) ==>> 等价于执行   print(r1.area)
    # # # __get__ 接受被修饰对象中的实例,
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 18.3、property装饰器“实现” (简洁版)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 18.4、property装饰器“实现” (简洁版) 与 内置的property装饰器对比1
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 19、property装饰器,之类调用静态属性 对比
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 19.1、property装饰器,之类调用静态属性,实现property的完整功能( 类无法调用静态属性)
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 20、__name__获取函数的名字
    # # # 用来获取运行的模块的名字,  或者对应的对象的名字(类是获取不到名字的)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 21、property装饰器,之类调用静态属性,实现property的完整功能
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 21.1、元类的引入
    # # # python中一切皆为对象。类的本身也是一个对象,由 type 产生
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 22、type 元类来产生 类
    
    # # # FFo = type("FFo", (object,), {'x': 1})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3:{'x': 1},    类的属性字典
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 22.1、type 元类来产生 类
    # # # 给类中添加类的初始化属数,类的数值属性, 类的函数属性
    
    # # # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3: {'x':1, '__init__':__init__, 'test':test},    类的属性字典
    # # # 'x':1  相当于在类中定义数值属性   x = 1
    # # # '__init__':__init__  相当于在类中定义类初化始的函数属性   def __init__(self)
    # # # 'test':test          相当于在类中定义类的函数属性   def test(self)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 22.2、type 元类产生的类进行  实例化
    # # # 给类中添加类的初始化属数,类的数值属性, 类的函数属性
    
    # # # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3: {'x':1, '__init__':__init__, 'test':test},    类的属性字典
    # # # 'x':1  相当于在类中定义数值属性   x = 1
    # # # '__init__':__init__  相当于在类中定义类初化始的函数属性   def __init__(self)
    # # # 'test':test          相当于在类中定义类的函数属性   def test(self)
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 22.3、类的产生总结
    # # # 类的产生有两种方式,1、通过 class来定义类;       2、通过type来产生类
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 23、自定义元类引入,元类定义自己的元类type
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 24、自定义元类引入,__call__ 方法介绍
    # # # 实例运加括号的时候,即实例 f1() 时候,会触发所属的类中的 __call__方法
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 24.1、自定义元类引入,__call__ 方法介绍
    # # # 实例运加括号的时候,即实例 f1() 时候,会触发所属的类中的 __call__方法
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 25.1、自定义元类引入1,元类定义自己的元类type
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 25.2、自定义元类引入2,元类定义自己的元类type
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 25.3、自定义元类引入2( 实例传入的内容信息),自定义元类中的 __call__ 方法
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    # # # __call__ 接收着,我们使用 Foo类 进行实例化时候的信息
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 25.3、自定义元类实现,自定义元类中的 __call__ 方法
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    
    # ------------------------------------------------------------
    
    # ------------------------------------------------------------
    # # 25.4、自定义元类实现(简洁版)
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    # ------------------------------------------------------------
    
    '''
    
    # ------------------------------------------------分割线-------------------------------------------------
    # ------------------------------------------------分割线-------------------------------------------------
    # ------------------------------------------------分割线-------------------------------------------------
    #
    
    '''
    # ------------------------------------------------------------
    # # 1、总结:
    # # # hasattr, getattr, setattr;;  getitem, setitem, delitem;; set, get, delete;; __del__
    # ------------------------------------------------------------
    '''
    
    '''
    #自省
    hasattr(obj,'属性') #obj.属性  是否存在
    getattr(obj,'属性') #获取obj.属性   不存在则报错
    getattr(obj,'属性','默认值') #获取obj.属性   不存在不会报错,返回那个默认值
    setattr(obj,'属性','属性的值') #obj.属性=属性的值
    delattr(obj,'属性') #del obj.属性
    
    #__getattr__,__setattr__,__delattr__
    obj点的方式去操作属性时触发的方法
    
    __getattr__:obj.属性 不存在时触发
    __setattr__:obj.属性=属性的值 时触发
    __delattr__:del obj.属性 时触发
    
    #__getitem__,__setitem_,__delitem__
    obj[‘属性’]的方式去操作属性时触发的方法
    
    __getitem__:obj['属性'] 时触发
    __setitem__:obj['属性']=属性的值 时触发
    __delitem__:del obj['属性'] 时触发
    
    #__get__,__set__,__delete__
    描述就是一个新式类,这个类至少要实现上述三个方法的一个
    class 描述符:
    	def __get__():
    		pass
    	def __set__():
    		pass
    	def __delete__():
    		pass
    
    class 类:
    	name=描述符()
    
    obj=类()
    obj.name #get
    obj.name='egon' #set
    del obj.name #delete
    
    #__del__:析构方法
    垃圾回收时触发
    
    '''
    
    
    
    
    
    # 02 上下文管理协议
    # 02 上下文管理协议
    
    '''
    # ------------------------------------------------------------
    # # 2、 __enter__ 与 __exit__
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------
    '''
    #
    # class Foo:
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def __enter__(self):
    #         print("执行了enter")
    #         return self
    #
    #     def __exit__(self, exc_type, exc_val, exc_tb):
    #         print("执行了exit")
    #
    #
    #
    # with Foo('a.txt') as f:
    #     print(f)
    #     print("======1111======")
    #     print("======2222======")
    #     print("======3333======")
    #
    # print("000000000000")
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 执行了enter
    # # <__main__.Foo object at 0x000000000228C358>
    # # ======1111======
    # # ======2222======
    # # ======3333======
    # # 执行了exit
    # # 000000000000
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 3、 __enter__ 与 __exit__ 之文件异常引入
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------
    '''
    #
    # class Foo:
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def __enter__(self):
    #         print("执行了enter")
    #         return self
    #
    #     def __exit__(self, exc_type, exc_val, exc_tb):
    #         print("执行了exit")
    #
    #
    #
    # with Foo('a.txt') as f:
    #     print(f)
    #     print(ffffffffffff)
    #     print("======1111======")
    #
    # print("000000000000")
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 执行了enter
    # # <__main__.Foo object at 0x000000000297C358>
    # # 执行了exit
    # # Traceback (most recent call last):
    # #   File "D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py", line 149, in <module>
    # #     print(ffffffffffff)
    # # NameError: name 'ffffffffffff' is not defined
    # #
    # # Process finished with exit code 1
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 3.1、 __enter__ 与 __exit__ 之文件异常引入1
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------
    '''
    #
    # class Foo:
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def __enter__(self):
    #         print("执行了enter")
    #         return self
    #
    #     def __exit__(self, exc_type, exc_val, exc_tb):
    #         print("执行了exit")
    #         print(exc_type)
    #         print(exc_val)
    #         print(exc_tb)
    #
    #
    #
    # with Foo('a.txt') as f:
    #     print(f)
    #     print("======1111======")
    #
    # print("000000000000")
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 执行了enter
    # # <__main__.Foo object at 0x000000000295C358>
    # # ======1111======
    # # 执行了exit
    # # None
    # # None
    # # None
    # # 000000000000
    # #
    # # Process finished with exit code 0
    #
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 3.2、 __exit__ 中 exc_type, exc_val, exc_tb 之文件异常引入1
    # # # __exit__ 中的 exc_type, exc_val, exc_tb 就是文件异常的信息内容
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # ------------------------------------------------------------
    '''
    #
    # class Foo:
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def __enter__(self):
    #         print("执行了enter")
    #         return self
    #
    #     def __exit__(self, exc_type, exc_val, exc_tb):
    #         print("执行了exit")
    #         print(exc_type)
    #         print(exc_val)
    #         print(exc_tb)
    #
    #
    # with Foo('a.txt') as f:
    #     print(f)
    #     print(ffffffffffff)
    #     print("======1111======")
    #
    # print("000000000000")
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 执行了enter
    # # <__main__.Foo object at 0x000000000297C358>
    # # 执行了exit
    # # Traceback (most recent call last):
    # #   File "D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py", line 149, in <module>
    # #     print(ffffffffffff)
    # # NameError: name 'ffffffffffff' is not defined
    # #
    # # Process finished with exit code 1
    #
    
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 3.3、 __exit__ 中 exc_type, exc_val, exc_tb 之文件异常
    # # # __exit__ 中的 exc_type, exc_val, exc_tb 就是文件异常的信息内容
    # # # __exit__ 中的返回值设置为True时,文件的异常会结束该文件内容的操作,但是对于
    # # # 该操作外的操作信息不会有所影响,仍能够正常运行 
    # ------------------------------------------------------------
    '''
    #
    # class Foo:
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def __enter__(self):
    #         print("执行了enter")
    #         return self
    #
    #     def __exit__(self, exc_type, exc_val, exc_tb):
    #         print("执行了exit")
    #         print(exc_type)
    #         print(exc_val)
    #         print(exc_tb)
    #         return True
    #
    #
    # with Foo('a.txt') as f:
    #     print(f)
    #     print(ffffffffffff)
    #     print("======1111======")
    #
    # print("000000000000")
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 执行了enter
    # # <__main__.Foo object at 0x0000000002966DD8>
    # # 执行了exit
    # # <class 'NameError'>
    # # name 'ffffffffffff' is not defined
    # # <traceback object at 0x00000000039ED608>
    # # 000000000000
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 3.4、总结 __enter__ 与 __exit__ 
    # ------------------------------------------------------------
    '''
    
    '''
        # with obj as  f:
        #     '代码块'
        #     
        # 1.with obj ----》触发obj.__enter__(),拿到返回值
        # 
        # 2.as f----->f=返回值、
        # 
        # 3.with obj as f  等同于     f=obj.__enter__()
        # 
        # 4.执行代码块
        # 一:没有异常的情况下,整个代码块运行完毕后去触发__exit__,它的三个参数都为None
        # 二:有异常的情况下,从异常出现的位置直接触发__exit__
        #     a:如果__exit__的返回值为True,代表吞掉了异常
        #     b:如果__exit__的返回值不为True,代表吐出了异常
        #     c:__exit__的的运行完毕就代表了整个with语句的执行完毕
        
        # 在出现的异常中,
        # Trackback: 追踪信息
        # NameError: 错误类型; 后面跟的是异常值
        
        
    '''
    
    
    
    
    
    
    
    
    
    # ------------------------------------------------分割线-------------------------------------------------
    # day28 描述符应用part1
    # day28 描述符应用part1
    # day28 描述符应用part1
    
    '''
    # ------------------------------------------------------------
    # # 4、描述符的应用的引入
    # # # test给定的参数中,如果是字符串或者整形数字就输出,否则留报错!显然,
    # # # 下面的例子中,是不能够满足该要求的;  下面关于描述符的应用就是为了解决该问题
    # ------------------------------------------------------------
    '''
    #
    # def test(x):
    #     print("-->>",x)
    #
    #
    # test("alex")
    # test(1111)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # -->> alex
    # # -->> 1111
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 5、描述符中 __set__ 中的各个参数
    # # # __set__中的各个参数:
    # # # instance : 修饰的实例本身(下例中,就是实例p1)
    # # # value    :实例中修饰的那个值(下例中,就是 alex)
    # # # self     :描述符所在的类本身
    # ------------------------------------------------------------
    '''
    #
    # class Typed:
    #     def __set__(self, instance, value):
    #         print("【set】方法")
    #         print("instance参数 【%s】"%instance)        # instance 等价于 实例 p1
    #         print("value参数 【%s】" %value)             # 传入的alex
    #         print("__set__中的self====>>", self)         # <__main__.Typed object at 0x00000000022B6B00>
    #
    # class People:
    #     name = Typed()
    #     def __init__(self, name, age, salary):
    #         self.name = name
    #         self.age = age
    #         self.salary = salary
    #
    #
    # p1 = People("alex", "13", 6666)
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    #
    # print("p1.__dict__      ", p1.__dict__)
    #
    # print("分割线111".center(100, "-"))
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【set】方法
    # # instance参数 【<__main__.People object at 0x00000000022B6AC8>】
    # # value参数 【alex】
    # # __set__中的self====>> <__main__.Typed object at 0x00000000022B6B00>
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x00000000022B6AC8>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'age': '13', 'salary': 6666}
    # # -----------------------------------------------分割线111-----------------------------------------------
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 6、描述符中 __get__ 中的各个参数
    # # # __get__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # # # owner    :修饰的实例所属的类(下例中,是类People)
    # ------------------------------------------------------------
    '''
    #
    # class Typed:
    #     def __get__(self, instance, owner):
    #         print("【get】方法")
    #         print('instance参数 【%s】 ' %instance)         # instance 等价于 实例 p1
    #         print("owner参数 【%s】 "% owner)               # 类People
    #
    #     def __set__(self, instance, value):
    #         print("【set】方法")
    #         print("instance参数 【%s】"%instance)        # instance 等价于 实例 p1
    #         print("value参数 【%s】" %value)             # 传入的alex
    #         print("__set__中的self====>>", self)         # <__main__.Typed object at 0x00000000022B6B00>
    #
    #
    #
    # class People:
    #     name = Typed()
    #
    #     def __init__(self, name, age, salary):
    #         self.name = name
    #         self.age = age
    #         self.salary = salary
    #
    #
    # p1 = People("alex", "13", 6666)
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    # print("p1.__dict__      ", p1.__dict__)
    #
    # print("分割线222".center(100, "-"))
    # p1.name
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【set】方法
    # # instance参数 【<__main__.People object at 0x00000000029A6AC8>】
    # # value参数 【alex】
    # # __set__中的self====>> <__main__.Typed object at 0x00000000029A6B00>
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x00000000029A6AC8>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'age': '13', 'salary': 6666}
    # # -----------------------------------------------分割线222-----------------------------------------------
    # # 【get】方法
    # # instance参数 【<__main__.People object at 0x00000000029A6AC8>】
    # # owner参数 【<class '__main__.People'>】
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 6.1、描述符中 __get__ 中的各个参数
    # # # __get__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # # # owner    :修饰的实例所属的类(下例中,是类People)
    # ------------------------------------------------------------
    '''
    #
    # class Typed:
    #     def __get__(self, instance, owner):
    #         print("【get】方法")
    #         print('instance参数 【%s】 ' %instance)         # instance 等价于 实例 p1
    #         print("owner参数 【%s】 "% owner)               # 类People
    #
    #     def __set__(self, instance, value):
    #         print("【set】方法")
    #         print("instance参数 【%s】"%instance)        # instance 等价于 实例 p1
    #         print("value参数 【%s】" %value)             # 传入的alex
    #         print("__set__中的self====>>", self)         # <__main__.Typed object at 0x00000000022B6B00>
    #
    #
    #
    # class People:
    #     name = Typed()
    #
    #     def __init__(self, name, age, salary):
    #         self.name = name
    #         self.age = age
    #         self.salary = salary
    #
    #
    # p1 = People("alex", "13", 6666)
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    # print("p1.__dict__      ", p1.__dict__)
    #
    # print("分割线222".center(100, "-"))
    # p1.name
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【set】方法
    # # instance参数 【<__main__.People object at 0x00000000029A6AC8>】
    # # value参数 【alex】
    # # __set__中的self====>> <__main__.Typed object at 0x00000000029A6B00>
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x00000000029A6AC8>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'age': '13', 'salary': 6666}
    # # -----------------------------------------------分割线222-----------------------------------------------
    # # 【get】方法
    # # instance参数 【<__main__.People object at 0x00000000029A6AC8>】
    # # owner参数 【<class '__main__.People'>】
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 6.2、描述符中 __delete__ 中的各个参数
    # # # __delete__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    '''
    #
    # class Typed:
    #     def __get__(self, instance, owner):
    #         print("【get】方法")
    #         print('instance参数 【%s】 ' %instance)         # instance 等价于 实例 p1
    #         print("owner参数 【%s】 "% owner)               # 类People
    #
    #     def __set__(self, instance, value):
    #         print("【set】方法")
    #         print("instance参数 【%s】"%instance)        # instance 等价于 实例 p1
    #         print("value参数 【%s】" %value)             # 传入的alex
    #         print("__set__中的self====>>", self)         # <__main__.Typed object at 0x00000000022B6B00>
    #
    #     def __delete__(self, instance):
    #         print("delete 方法")
    #         print("instance参数 【%s】"%instance)         # instance 等价于 实例 p1
    #
    #
    # class People:
    #     name = Typed()
    #
    #     def __init__(self, name, age, salary):
    #         self.name = name
    #         self.age = age
    #         self.salary = salary
    #
    #
    # p1 = People("alex", "13", 6666)
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    # print("p1.__dict__      ", p1.__dict__)
    #
    # print("分割线222".center(100, "-"))
    # del p1.name
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【set】方法
    # # instance参数 【<__main__.People object at 0x00000000029A6AC8>】
    # # value参数 【alex】
    # # __set__中的self====>> <__main__.Typed object at 0x00000000029A6B00>
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x00000000029A6AC8>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'age': '13', 'salary': 6666}
    # # -----------------------------------------------分割线222-----------------------------------------------
    # # delete 方法
    # # instance参数 【<__main__.People object at 0x00000000029A6AC8>】
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 7、__set__  使用描述符给给定的实例中传入值  
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    '''
    #
    # class Typed:
    #     def __init__(self, key):            # key       = 'name '
    #         self.key = key                  # self.key  = 'name'
    #
    #     def __set__(self, instance, value):
    #         print("【set】方法")
    #         print("instance参数 【%s】"%instance)        # instance 等价于 实例 p1
    #         print("value参数 【%s】" %value)             # 传入的alex
    #         print("__set__中的self====>>", self)         # <__main__.Typed object at 0x00000000022B6B00>
    #         instance.__dict__[self.key] = value          # p1.__dict__[ 'name'] = alex
    #
    # class People:
    #     name=Typed('name')       # Typed.__set__()  ==  self.__set__()
    #
    #     def __init__(self, name, age, salary):
    #         self.name = name
    #         self.age = age
    #         self.salary = salary
    #
    #
    # p1 = People("alex", "13", 6666)
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    # print("p1.__dict__      ", p1.__dict__)
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【set】方法
    # # instance参数 【<__main__.People object at 0x0000000001F27AC8>】
    # # value参数 【alex】
    # # __set__中的self====>> <__main__.Typed object at 0x0000000001F36B00>
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x0000000001F27AC8>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'name': 'alex', 'age': '13', 'salary': 6666}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 8、__set__  使用描述符对给定的实例 获取对应的值  
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    '''
    #
    # class Typed:
    #     def __init__(self, key):            # key       = 'name '
    #         self.key = key                  # self.key  = 'name'
    #
    #     def __get__(self, instance, owner):
    #         print("【get】方法")
    #         print('instance参数 【%s】 ' %instance)         # instance 等价于 实例 p1
    #         print("owner参数 【%s】 "% owner)               # 类People
    #         return instance.__dict__[self.key]
    #
    #     def __set__(self, instance, value):
    #         print("【set】方法")
    #         print("instance参数 【%s】"%instance)        # instance 等价于 实例 p1
    #         print("value参数 【%s】" %value)             # 传入的alex
    #         # print("__set__中的self====>>", self)         # <__main__.Typed object at 0x00000000022B6B00>
    #         instance.__dict__[self.key] = value          # p1.__dict__[ 'name'] = alex
    #
    # class People:
    #     name=Typed('name')       # Typed.__set__()  ==  self.__set__()
    #     age =Typed('age')
    #
    #     def __init__(self, name, age, salary):
    #         self.name = name
    #         self.age = age
    #         self.salary = salary
    #
    #
    # p1 = People("alex", "13", 6666)
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    # print("p1.__dict__      ", p1.__dict__)
    #
    # print("分割线222".center(100, "-"))
    # print( "p1.age:     ", p1.age)
    # print( "p1.name:    ",p1.name)
    # print( "p1.salary:  ",p1.salary)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【set】方法
    # # instance参数 【<__main__.People object at 0x0000000002967E10>】
    # # value参数 【alex】
    # # 【set】方法
    # # instance参数 【<__main__.People object at 0x0000000002967E10>】
    # # value参数 【13】
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x0000000002967E10>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'name': 'alex', 'age': '13', 'salary': 6666}
    # # -----------------------------------------------分割线222-----------------------------------------------
    # # 【get】方法
    # # instance参数 【<__main__.People object at 0x0000000002967E10>】
    # # owner参数 【<class '__main__.People'>】
    # # p1.age:      13
    # # 【get】方法
    # # instance参数 【<__main__.People object at 0x0000000002967E10>】
    # # owner参数 【<class '__main__.People'>】
    # # p1.name:     alex
    # # p1.salary:   6666
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 9、使用描述符对给定的实例 的值的设定进行限制1
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    '''
    #
    # class Typed:
    #     def __init__(self, key):            # key       = 'name '   以name为例子
    #         self.key = key                                  # self.key  = 'name'
    #         # self.expected_typed = expected_typed            # self.expected_typed  = str
    #
    #     def __get__(self, instance, owner):
    #         print("【get】方法")
    #         return instance.__dict__[self.key]
    #
    #     def __set__(self, instance, value):
    #         if not isinstance(value, str ):
    #             print("你传入的类型不是字符串,错误!!")
    #             # return            # 用return的话,那么程序仍然可以正常运行
    #             raise TypeError("%s 传入的类型不是str " % (self.key))
    #         # 符合条件进行添加
    #         instance.__dict__[self.key] = value          # p1.__dict__[ 'name'] = alex
    #
    #
    # class People:
    #     name=Typed('name')       # Typed.__set__()  ==  self.__set__()
    #     age =Typed('age')
    #
    #     def __init__(self, name, age, salary):
    #         self.name = name
    #         self.age = age
    #         self.salary = salary
    #
    #
    # p1 = People("alex", "13", 6666)
    # # p2 = People("egon", 22, 5555)   # 会报错,因为这里实例age采用了Typed进行描述,而age要求的是字符串类型
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    # print("p1.__dict__      ", p1.__dict__)
    #
    # print("分割线222".center(100, "-"))
    # print( "p1.age:     ", p1.age)
    # print( "p1.name:    ",p1.name)
    # print( "p1.salary:  ",p1.salary)
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x0000000002297E48>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'name': 'alex', 'age': '13', 'salary': 6666}
    # # -----------------------------------------------分割线222-----------------------------------------------
    # # 【get】方法
    # # p1.age:      13
    # # 【get】方法
    # # p1.name:     alex
    # # p1.salary:   6666
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 9.1、使用描述符对给定的实例 的值的设定进行限制2
    # # # 对类进行修饰的时候,直接指定数值属性的  类型 ,如name 是str类型
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------
    '''
    #
    # class Typed:
    #     def __init__(self, key, expected_typed):                            # key       = 'name '   以name为例子
    #         self.key = key                                  # self.key  = 'name'
    #         self.expected_typed = expected_typed            # self.expected_typed  = str
    #
    #     def __get__(self, instance, owner):
    #         print("【get】方法")
    #         return instance.__dict__[self.key]
    #
    #     def __set__(self, instance, value,):
    #         if not isinstance(value, self.expected_typed ):
    #             print("传入的类型错误!!")
    #             # return            # 用return的话,那么程序仍然可以正常运行
    #             raise TypeError("%s 传入的类型不是 %s " % (self.key, self.expected_typed))
    #         # 符合条件进行添加
    #         instance.__dict__[self.key] = value          # p1.__dict__[ 'name'] = alex
    #
    #     def __delete__(self, instance):
    #         print('delete方法')
    #         # print('instance参数【%s】' % instance)
    #         instance.__dict__.pop(self.key)
    #
    # class People:
    #     name=Typed('name',str)       # Typed.__set__()  ==  self.__set__()
    #     age =Typed('age', int)
    #
    #     def __init__(self, name, age, salary):
    #         self.name = name
    #         self.age = age
    #         self.salary = salary
    #
    #
    # p1 = People("alex", 11, 6666)
    # # p2 = People("egon", "11", 5555)   # 会报错,因为这里实例age采用了Typed进行描述,而age要求的是整形,注意这里与上面区别
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    # print("p1.__dict__      ", p1.__dict__)
    #
    # print("分割线222".center(100, "-"))
    # print( "p1.age:     ", p1.age)
    # print( "p1.name:    ",p1.name)
    # print( "p1.salary:  ",p1.salary)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x0000000002997E48>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'name': 'alex', 'age': 11, 'salary': 6666}
    # # -----------------------------------------------分割线222-----------------------------------------------
    # # 【get】方法
    # # p1.age:      11
    # # 【get】方法
    # # p1.name:     alex
    # # p1.salary:   6666
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    
    # 08 类的装饰器的基本原理
    # 08 类的装饰器的基本原理
    
    '''
    # ------------------------------------------------------------
    # # 10、装饰器的引入,修饰函数
    # ------------------------------------------------------------
    '''
    #
    # def deco(func):
    #     print("======deco装饰器运行======")
    #     return func
    #
    #
    # @deco    # 装饰tets()函数 ,相当于 test = deco(test)
    # def test():
    #     print("test函数运行")
    #
    
    # test()            # 这个被屏蔽掉了之后,deco的print函数仍然会触发,但是test()函数中的print就不会运行了
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ======deco装饰器运行======
    # # test函数运行
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 11、装饰器修饰 类
    # # # 类中的装饰器的运行的情况,是跟上面的函数的装饰器是有所区别的; 类中的是下运行类,之后再运行装饰器的运行
    # # # 而函数中的,是先运行装饰器中的内容,之后再运行函数的内容
    # ------------------------------------------------------------
    '''
    #
    # def deco(func):
    #     print("======deco装饰器运行======")
    #     return func
    #
    #
    # @deco    # 装饰 Foo ,相当于 Foo = deco(Foo)
    # class Foo:
    #     print(" 类 Foo 运行")
    #
    # print("分割线".center(150,"-"))
    # print(Foo.__dict__)               # 装饰器只是修饰作用,没有出现在类的字典中
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # #  类 Foo 运行
    # # ======deco装饰器运行======
    # # -------------------------------------------------------------------------分割线--------------------------------------------------------------------------
    # # {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    # 09 类的装饰器增强版
    # 09 类的装饰器增强版
    
    '''
    # ------------------------------------------------------------
    # # 12、函数也是有字典的
    # ------------------------------------------------------------
    '''
    #
    # def deco(func):
    #     print("======deco装饰器运行======")
    #     # obj.x = 1
    #     # obj.y = 2
    #     # obj.z = 3
    #     return func
    #
    #
    # @deco    # 装饰tets()函数 ,相当于 test = deco(test)
    # def test():
    #     print("test函数运行")
    #
    # print( test.__dict__ )
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ======deco装饰器运行======
    # # {}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 12.1、给函数的字典添加属性
    # # # 函数也可以像类一像添加属性,因为函数的本质就是类;python中的一切都是对像
    # ------------------------------------------------------------
    '''
    #
    # def deco(obj):
    #
    #     print("======deco装饰器运行======")
    #     obj.x = 1
    #     obj.y = 2
    #     obj.z = 3
    #     return obj
    #
    #
    # @deco    # 装饰tets()函数 ,相当于 test = deco(test)
    # def test():
    #     print("test函数运行")
    #
    # print("分割线".center(150,"-"))
    # test()
    # print(" test.__dict__   ",  test.__dict__ )
    # test()
    # test.name = "新加的name"
    # print(" test.__dict__   ",  test.__dict__ )
    # print(" type(test)  ",  type(test) )
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ======deco装饰器运行======
    # # -------------------------------------------------------------------------分割线--------------------------------------------------------------------------
    # # test函数运行
    # #  test.__dict__    {'x': 1, 'y': 2, 'z': 3}
    # # test函数运行
    # #  test.__dict__    {'x': 1, 'y': 2, 'z': 3, 'name': '新加的name'}
    # #  type(test)   <class 'function'>
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 13、使用装饰器给类中的字典添加属性
    # ------------------------------------------------------------
    '''
    #
    # def deco(obj):
    #
    #     print("======deco装饰器运行======")
    #     obj.x = 1
    #     obj.y = 2
    #     obj.z = 3
    #     return obj
    #
    #
    # @deco    # 装饰tets()函数 ,相当于 test = deco(test)
    # class Foo:
    #     print("Foo 运行")
    #
    #
    # print("分割线".center(150,"-"))
    #
    # print(" Foo.__dict__   ",  Foo.__dict__ )
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # Foo 运行
    # # ======deco装饰器运行======
    # # -------------------------------------------------------------------------分割线--------------------------------------------------------------------------
    # #  Foo.__dict__    {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None, 'x': 1, 'y': 2, 'z': 3}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 14、使用装饰器给类中的字典添加属性
    # # # 只能在装饰器中内部给定值的情况
    # ------------------------------------------------------------
    '''
    #
    # def Typed(**kwargs):
    #     def deco(obj):
    #         print("======deco装饰器运行======")
    #         obj.x = 1
    #         obj.y = 2
    #         obj.z = 3
    #         return obj
    #     return deco
    #
    #
    # @Typed(x="我是随便写的")    # 1、Typed(x="我是随便写的")--》deco  2、deco--》Foo = deco(Foo)
    # class Foo:
    #     print("Foo 运行")
    #
    #
    # print("分割线".center(150,"-"))
    #
    # print(" Foo.__dict__   ",  Foo.__dict__ )
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # Foo 运行
    # # ======deco装饰器运行======
    # # -------------------------------------------------------------------------分割线--------------------------------------------------------------------------
    # #  Foo.__dict__    {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None, 'x': 1, 'y': 2, 'z': 3}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 14.1、使用装饰器给类中的字典添加属性1
    # # # 解决只能在装饰器中内部给定值的情况
    # ------------------------------------------------------------
    '''
    
    # def Typed(**kwargs):
    #     def deco(obj):
    #         print("======deco装饰器运行======")
    #         print(obj)
    #         for key, val in kwargs.items():
    #             print("key = %s, type = %s"%(key, type(key)))
    #             # obj.key = val               # 这种方式是不可以的,因为key会被当作是实例的属性名
    #             # obj.__dict__[key] = val     # 报错!从原理上是可以这么做的,但是编译器里是不支持这种做法! TypeError: 'mappingproxy' object does not support item assignment
    #             setattr(obj, key, val)
    #         return obj
    #     return deco
    #
    #
    # @Typed(x=1, y =2, z =3)    # 1、Typed(x="我是随便写的")--》deco  2、deco--》Foo = deco(Foo)
    # class Foo:
    #     print("Foo 运行")
    #
    #
    # print("分割线2222".center(150,"-"))
    #
    # print(" Foo.__dict__   ",  Foo.__dict__ )
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # Foo 运行
    # # ======deco装饰器运行======
    # # key = x, type = <class 'str'>
    # # key = y, type = <class 'str'>
    # # key = z, type = <class 'str'>
    # # -----------------------------------------------------------------------分割线2222------------------------------------------------------------------------
    # #  Foo.__dict__    {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None, 'x': 1, 'y': 2, 'z': 3}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    # 11 装饰器的应用
    # 11 装饰器的应用
    
    '''
    # ------------------------------------------------------------
    # # 15、装饰器的应用(与前面的序号10对比)
    # ------------------------------------------------------------
    '''
    #
    #
    # class Typed:
    #     def __init__(self,key,expected_type):
    #         self.key=key
    #         self.expected_type=expected_type
    #
    #     def __get__(self, instance, owner):
    #         print('get方法')
    #         # print('instance参数【%s】' %instance)
    #         # print('owner参数【%s】' %owner)
    #         return instance.__dict__[self.key]
    #
    #     def __set__(self, instance, value):
    #         print('set方法')
    #         # print('instance参数【%s】' % instance)
    #         # print('value参数【%s】' % value)
    #         # print('====>',self)
    #         if not isinstance(value,self.expected_type):
    #             # print('你传入的类型不是字符串,错误')
    #             # return
    #             raise TypeError('%s 传入的类型不是%s' %(self.key,self.expected_type))
    #         instance.__dict__[self.key]=value
    #
    #     def __delete__(self, instance):
    #         print('delete方法')
    #         # print('instance参数【%s】' % instance)
    #         instance.__dict__.pop(self.key)
    #
    #
    # def deco(**kwargs):                      # kwargs={'name':str,'age':int}
    #     def wrapper(obj):                    # obj=People
    #         for key,val in kwargs.items():   # (('name',str),('age',int))
    #             setattr(obj,key,Typed(key,val))
    #             # setattr(People,'name',Typed('name',str)) #People.name=Typed('name',str)
    #         return obj
    #     return wrapper
    #
    #
    # @deco(name=str,age=int)     # @wrapper ===>People=wrapper(People)
    # class People:
    #     name='我是谁,我是谁'               # 这里会被装饰器所覆盖,因此无效
    #     # name=Typed('name',str)            # 装饰器就是为了实现该功能
    #     # age=Typed('age',int)              # 装饰器就是为了实现该功能
    #
    #     def __init__(self,name,age,salary):
    #         self.name=name
    #         self.age=age
    #         self.salary=salary
    #
    # p1 = People("alex", 11, 6666)
    # # p2 = People("egon", '22', 5555)   # 会报错,因为这里实例age采用了Typed进行描述,而age要求的是整数类型
    #
    # print("分割线111".center(100, "-"))
    # print("p1:              ", p1)
    # print("People:          ", People)
    # print("p1.__dict__      ", p1.__dict__)
    # print("People.__dict__  ", People.__dict__)
    #
    # print("分割线222".center(100, "-"))
    # print( "p1.age:     ", p1.age)
    # print( "p1.name:    ",p1.name)
    # print( "p1.salary:  ",p1.salary)
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # set方法
    # # set方法
    # # -----------------------------------------------分割线111-----------------------------------------------
    # # p1:               <__main__.People object at 0x0000000002957E48>
    # # People:           <class '__main__.People'>
    # # p1.__dict__       {'name': 'alex', 'age': 11, 'salary': 6666}
    # # People.__dict__   {'__module__': '__main__', 'name': <__main__.Typed object at 0x0000000002966B00>, '__init__': <function People.__init__ at 0x00000000039EEAE8>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None, 'age': <__main__.Typed object at 0x0000000002957E10>}
    # # -----------------------------------------------分割线222-----------------------------------------------
    # # get方法
    # # p1.age:      11
    # # get方法
    # # p1.name:     alex
    # # p1.salary:   6666
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    # 11 自定制property
    # 11 自定制property
    
    '''
    # ------------------------------------------------------------
    # # 16、property 的使用
    # # # property() 函数的作用是在新式类中返回属性值。
    # # # 下面例子中,(原)r1.area()-->>(现)r1.area 
    # ------------------------------------------------------------
    '''
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @property         # (Room类)area=property((Room类)area)
    #     def area(self):
    #         print("【area】")
    #         return self.width * self.length
    #
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # r1 = Room('厕所', 1, 1)
    #
    # print(r1.area)          # 'area': <property object at 0x00000000020E8688>
    # print(r1.area1())       # 'area1': <function Room.area1 at 0x00000000039EE8C8>,
    #
    # print("r1.__dict__:     ", r1.__dict__)
    # print("Room.__dict__:   ", Room.__dict__)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【area】
    # # 1
    # # 【area1】
    # # 1
    # # r1.__dict__:      {'name': '厕所', 'width': 1, 'length': 1}
    # # Room.__dict__:    {'__module__': '__main__', '__init__': <function Room.__init__ at 0x00000000039EE7B8>, 'area': <property object at 0x00000000020E8688>, 'area1': <function Room.area1 at 0x00000000039EE8C8>, '__dict__': <attribute '__dict__' of 'Room' objects>, '__weakref__': <attribute '__weakref__' of 'Room' objects>, '__doc__': None}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 17、property引入 , 类的装饰器
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):
    #         print("=======>>>",func)        # <function Room.area at 0x00000000039EE8C8>
    #
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty  # (Room类)area = Lazyproperty( (Room类)area )
    #     def area(self):
    #         print("【area】")
    #         return self.width * self.length
    #
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # print("分割线22".center(150,"-"))
    # print(r1.area)                         # <__main__.Lazyproperty object at 0x00000000029CC358>
    # print("分割线33".center(150,"-"))
    # print(r1.area1())
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # =======>>> <function Room.area at 0x00000000039EE8C8>
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # <__main__.Lazyproperty object at 0x00000000029CC358>
    # # ------------------------------------------------------------------------分割线33-------------------------------------------------------------------------
    # # 【area1】
    # # 1
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 18、property装饰器初步 , 类的装饰器
    # # # print(r1.area.func(r1))   实现了基本的装饰器功能
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):
    #         # 运行时,先程序自己先预读了; <function Room.area at 0x00000000039EE8C8>
    #         # 这里,func实际上接收的是 Room 类 中的 area函数的地址
    #         print("=======>>>",func)
    #         self.func = func
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty   # (Room类)area = Lazyproperty( (Room类)area )
    #     def area(self):
    #         '''
    #         运行@Lazyproperty 的时候,相当于进行实例化,形式如下: (Room类)area = Lazyproperty( (Room类)area ),其中,area传入的是一个Room 类中的一个函数的地址
    #
    #         :return:
    #         '''
    #         print("【area】")
    #         return self.width * self.length
    #
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    # print(r1)                       # <__main__.Room object at 0x0000000002377A90>
    #
    # print("分割线22".center(150,"-"))
    # # property装饰器初步,我们要实现的就是 r1.area就可以实现该功能
    # # r1.area.func(r1)  如何理解:
    # print(r1.area)                  # <__main__.Lazyproperty object at 0x0000000001DBD128>
    # print(r1.area.func)             # <function Room.area at 0x00000000039EE8C8>
    # print(r1.area.func(r1))
    # print("分割线33".center(150,"-"))
    # print(r1.area1())
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # =======>>> <function Room.area at 0x00000000039EE8C8>
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # 【area】
    # # 1
    # # ------------------------------------------------------------------------分割线33-------------------------------------------------------------------------
    # # 【area1】
    # # 1
    # #
    # # Process finished with exit code 0
    #
    #
    #
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 18.1、property装饰器初步之 __get__ , 类的装饰器
    # # # 目标: print(r1.area.func(r1)) ==>> 等价于执行   print(r1.area) 
    # # # __get__ 接受被修饰对象中的实例, 
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):
    #         print("=======>>>",func)              # Room 类定义的函数,def area ;   <function Room.area at 0x00000000039EE8C8>
    #         self.func = func
    #
    #     def __get__(self, instance, owner):
    #         print("【get】")
    #         print("instance:    ", instance)          # 实际上,就是 Room 类产生的实例 r1;  <__main__.Room object at 0x0000000002267A58>
    #         print("owner:       ", owner)             # Room 类;,     class '__main__.Room'>
    #
    #
    # class Room:
    #     x = Lazyproperty('这个是用来测试的')
    #
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty   # 新(Room类)area = Lazyproperty( 旧(Room类)area )
    #     def area(self):
    #         print("【area】")
    #         return self.width * self.length
    #
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # print("分割线22".center(150,"-"))
    # print(r1.area)       # 相当于Lazyproperty的一个实例; 'area': <__main__.Lazyproperty object at 0x0000000002297A90>,
    #
    #
    # print("分割线33".center(150,"-"))
    # print("r1.__dict__:     ", r1.__dict__)
    # print("Room.__dict__:   ", Room.__dict__)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # =======>>> 这个是用来测试的
    # # =======>>> <function Room.area at 0x00000000039EE950>
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # <__main__.Room object at 0x0000000002267A58>
    # # 【get】
    # # instance:     <__main__.Room object at 0x0000000002267A58>
    # # owner:        <class '__main__.Room'>
    # # None
    # # ------------------------------------------------------------------------分割线33-------------------------------------------------------------------------
    # # r1.__dict__:      {'name': '厕所', 'width': 1, 'length': 1}
    # # Room.__dict__:    {'__module__': '__main__', 'x': <__main__.Lazyproperty object at 0x0000000001DBD128>, '__init__': <function Room.__init__ at 0x00000000039EE8C8>, 'area': <__main__.Lazyproperty object at 0x0000000002267A90>, 'area1': <function Room.area1 at 0x00000000039EE9D8>, '__dict__': <attribute '__dict__' of 'Room' objects>, '__weakref__': <attribute '__weakref__' of 'Room' objects>, '__doc__': None}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 18.2、property装饰器“实现”之 __get__ 返回运行的内容, 类的装饰器
    # # # 目标(实现): print(r1.area.func(r1)) ==>> 等价于执行   print(r1.area) 
    # # # __get__ 接受被修饰对象中的实例, 
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):
    #         print("=======>>>",func)              # Room 类定义的函数,def area ;   <function Room.area at 0x00000000039EE8C8>
    #         self.func = func
    #
    #     def __get__(self, instance, owner):
    #         print("【get】")
    #         print("instance:    ", instance)          # 实际上,就是 Room 类产生的实例 r1;  <__main__.Room object at 0x0000000002267A58>
    #         print("owner:       ", owner)             # Room 类;,     class '__main__.Room'>
    #         res = self.func(instance)                 # 相当于 Room 类中,运行 res = area1( r1 )
    #         return res
    #
    # class Room:
    #     x = Lazyproperty('这个是用来测试的')
    #
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty   # 新(Room类)area = Lazyproperty( 旧(Room类)area )
    #     def area(self): # self 代表的是实例本身;这里 self == 实例r1
    #         '''
    #         运行过程: 进行 Lazyproperty 中的 __get__ 函数 --> self.func(instance) ==  Room 类中的 area( r1 ) ->
    #                    运行Room 类中的 area( r1 )的内容 --> res 得到运行结果 ( Lazyproperty 中的 __get__ 函数)-->
    #                    return res
    #         :return:
    #         '''
    #
    #         print("【area】")
    #         return self.width * self.length
    #
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # print("分割线22".center(150,"-"))
    # print(r1.area)       # 相当于Lazyproperty的一个实例; 'area': <__main__.Lazyproperty object at 0x0000000002297A90>,
    #
    # print(r1.area1() )   # 运行过程:  r1.area1() --> Room 类 --> area1(r1)运行 --> 得到返回值
    # print("分割线33".center(150,"-"))
    # print("r1.__dict__:     ", r1.__dict__)
    # print("Room.__dict__:   ", Room.__dict__)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # =======>>> 这个是用来测试的
    # # =======>>> <function Room.area at 0x00000000039EE950>
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # 【get】
    # # instance:     <__main__.Room object at 0x0000000002997A90>
    # # owner:        <class '__main__.Room'>
    # # 【area】
    # # 1
    # # 【area1】
    # # 1
    # # ------------------------------------------------------------------------分割线33-------------------------------------------------------------------------
    # # r1.__dict__:      {'name': '厕所', 'width': 1, 'length': 1}
    # # Room.__dict__:    {'__module__': '__main__', 'x': <__main__.Lazyproperty object at 0x00000000029A6B00>, '__init__': <function Room.__init__ at 0x00000000039EE8C8>, 'area': <__main__.Lazyproperty object at 0x0000000002997E10>, 'area1': <function Room.area1 at 0x00000000039EE9D8>, '__dict__': <attribute '__dict__' of 'Room' objects>, '__weakref__': <attribute '__weakref__' of 'Room' objects>, '__doc__': None}
    # #
    # # Process finished with exit code 0
    #
    #
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 18.3、property装饰器“实现” (简洁版)
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):        # 传入的是 Room 类定义的函数地址,
    #         self.func = func
    #
    #     def __get__(self, instance, owner):
    #         '''
    #
    #         :param instance: 实例 r1
    #         :param owner:    Room 类
    #         :return:
    #         '''
    #         print("【get】")
    #         res = self.func(instance)
    #         return res
    #
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty   # 新(Room类)area = Lazyproperty( 旧(Room类)area )
    #     def area(self): # self 代表的是实例本身;这里 self == 实例r1
    #         '''
    #         运行过程: 进行 Lazyproperty 中的 __get__ 函数 --> self.func(instance) ==  Room 类中的 area( r1 ) ->
    #                    运行Room 类中的 area( r1 )的内容 --> res 得到运行结果 ( Lazyproperty 中的 __get__ 函数)-->
    #                    return res
    #         :return:
    #         '''
    #
    #         print("【area】")
    #         return self.width * self.length
    #
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # print("分割线22".center(150,"-"))
    # print(r1.area)                   # r1.area 相当于Lazyproperty的一个实例
    # print(r1.area1() )               # 运行过程:  r1.area1() --> Room 类 --> area1(r1)运行 --> 得到返回值
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # 【get】
    # # 【area】
    # # 1
    # # 【area1】
    # # 1
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 18.4、property装饰器“实现” (简洁版) 与 内置的property装饰器对比1
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):        # 传入的是 Room 类定义的函数地址,
    #         self.func = func
    #
    #     def __get__(self, instance, owner):
    #         '''
    #
    #         :param instance: 实例 r1
    #         :param owner:    Room 类
    #         :return:
    #         '''
    #         print("【get】")
    #         res = self.func(instance)
    #         return res
    #
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty   # 新(Room类)area = Lazyproperty( 旧(Room类)area )
    #     def area(self): # self 代表的是实例本身;这里 self == 实例r1
    #         '''
    #         运行过程: 进行 Lazyproperty 中的 __get__ 函数 --> self.func(instance) ==  Room 类中的 area( r1 ) ->
    #                    运行Room 类中的 area( r1 )的内容 --> res 得到运行结果 ( Lazyproperty 中的 __get__ 函数)-->
    #                    return res
    #         :return:
    #         '''
    #
    #         print("【area】")
    #         return self.width * self.length
    #
    #     @property
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # print("分割线22".center(150,"-"))
    # print(r1.area)                   # r1.area 相当于Lazyproperty的一个实例
    # print(r1.area1 )               # 运行过程:  r1.area1() --> Room 类 --> area1(r1)运行 --> 得到返回值
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # 【get】
    # # 【area】
    # # 1
    # # 【area1】
    # # 1
    # #
    # # Process finished with exit code 0
    #
    
    
    
    
    
    
    
    
    
    
    
    
    # 12 自定制property流程分析
    # 12 自定制property流程分析
    # ?????
    # ?????
    # ?????
    
    
    
    '''
    # ------------------------------------------------------------
    # # 19、property装饰器,之类调用静态属性 对比
    # # # “实现” (简洁版) 与 内置的property装饰器
    
    说明: 
        Room调用 property装饰器 修饰的函数成为静态属性之后,print(Room.area1) 返回的是一个 <property object at 0x00000000027D8778>
        而自己实现的 Lazyproperty 装饰器中,会出错            
    
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):        # 传入的是 Room 类定义的函数地址,
    #         self.func = func
    #
    #     def __get__(self, instance, owner):
    #         '''
    #
    #         :param instance: 实例 r1
    #         :param owner:    Room 类
    #         :return:
    #         '''
    #         print("【get】")
    #         print("instance:    ", instance)          # 实际上,就是 Room 类产生的实例 r1;  <__main__.Room object at 0x0000000002267A58>
    #         print("owner:       ", owner)             # Room 类;,     class '__main__.Room'>
    #         res = self.func(instance)
    #         return res
    #
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty   # 新(Room类)area = Lazyproperty( 旧(Room类)area )
    #     def area(self): # self 代表的是实例本身;这里 self == 实例r1
    #         '''
    #         运行过程: 进行 Lazyproperty 中的 __get__ 函数 --> self.func(instance) ==  Room 类中的 area( r1 ) ->
    #                    运行Room 类中的 area( r1 )的内容 --> res 得到运行结果 ( Lazyproperty 中的 __get__ 函数)-->
    #                    return res
    #         :return:
    #         '''
    #
    #         print("【area】")
    #         return self.width * self.length
    #
    #     @property
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # print("分割线22".center(150,"-"))
    # print(Room.area1)
    #
    # print("分割线33".center(150,"-"))
    # print(Room.area)
    #
    #
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # <property object at 0x00000000027B8F98>
    # # ------------------------------------------------------------------------分割线33-------------------------------------------------------------------------
    # # 【get】
    # # instance:     None
    # # owner:        <class '__main__.Room'>
    # # 【area】
    # # Traceback (most recent call last):
    # #   File "D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py", line 1886, in <module>
    # #     print(Room.area)
    # #   File "D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py", line 1851, in __get__
    # #     res = self.func(instance)
    # #   File "D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py", line 1871, in area
    # #     return self.width * self.length
    # # AttributeError: 'NoneType' object has no attribute 'width'
    # #
    # # Process finished with exit code 1
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 19.1、property装饰器,之类调用静态属性,实现property的完整功能( 类无法调用静态属性)
    # # # “实现” (简洁版) 与 内置的property装饰器
    
    说明: 
        Room调用 property装饰器 修饰的函数成为静态属性之后,print(Room.area1) 返回的是
        一个 <property object at 0x00000000027D8778>; 实际上,这个就是 Property 对象本身 
        而自己实现的 Lazyproperty 装饰器中,会出错            
    
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):        # 传入的是 Room 类定义的函数地址,
    #         self.func = func
    #
    #     def __get__(self, instance, owner):
    #         '''
    #         :self : 是 类 Lazyproperty
    #         :param instance: 实例 r1
    #         :param owner:    Room 类
    #         :return:
    #         '''
    #         print("【get】")
    #         # print("instance:    ", instance)          # 类调用的时候,返回值是一个 None
    #         # print("owner:       ", owner)             # Room 类;,     class '__main__.Room'>
    #         if instance is None:
    #             return self
    #         res = self.func(instance)
    #         return res
    #
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty   # 新(Room类)area = Lazyproperty( 旧(Room类)area )
    #     def area(self): # self 代表的是实例本身;这里 self == 实例r1
    #         '''
    #         运行过程: 进行 Lazyproperty 中的 __get__ 函数 --> self.func(instance) ==  Room 类中的 area( r1 ) ->
    #                    运行Room 类中的 area( r1 )的内容 --> res 得到运行结果 ( Lazyproperty 中的 __get__ 函数)-->
    #                    return res
    #         :return:
    #         '''
    #
    #         print("【area】")
    #         return self.width * self.length
    #
    #     @property
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # print("分割线22".center(150,"-"))
    # print("Room.area1:  ", Room.area1)
    #
    # print("分割线33".center(150,"-"))
    # print("Room.area:   ", Room.area)
    #
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # Room.area1:   <property object at 0x0000000001D98778>
    # # ------------------------------------------------------------------------分割线33-------------------------------------------------------------------------
    # # 【get】
    # # Room.area:    <__main__.Lazyproperty object at 0x0000000002986DD8>
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    # 13 实现延迟计算;
    # 13 实现延迟计算;
    
    '''
    # ------------------------------------------------------------
    # # 20、__name__获取函数的名字
    # # # 用来获取运行的模块的名字,  或者对应的对象的名字(类是获取不到名字的)
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):        # 传入的是 Room 类定义的函数地址,
    #         self.func = func
    #         print("【func.__name__】      ", func.__name__)
    #         print("【self.func.__name__】 ", self.func.__name__)
    #
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #
    #     @Lazyproperty
    #     def area(self):
    #         pass
    #
    #     @property
    #     def area1(self):
    #         pass
    #
    #     def test(self):
    #         pass
    #
    # def info():
    #     pass
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # # print(r1.__name__)                    # 报错, 这个是无法获取明名的
    # # print(r1.area.__name__)               # 报错, 这个是无法获取明名的
    #
    # print(Lazyproperty.__name__)
    # print(Room.__name__)
    # print("当前的运行的名字", __name__)
    #
    #
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【func.__name__】       area
    # # 【self.func.__name__】  area
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # Lazyproperty
    # # Room
    # # 当前的运行的名字 __main__
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 21、property装饰器,之类调用静态属性,实现property的完整功能
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------
    '''
    #
    # class Lazyproperty:
    #     def __init__(self, func):
    #         '''
    #
    #         :param func: 传入的是 Room 类定义的函数地址,
    #         '''
    #         self.func = func
    #
    #     def __get__(self, instance, owner):
    #         '''
    #
    #         :self : 是 类 Lazyproperty
    #         :param instance: 实例 r1;     类调用的时候,返回值是一个 None
    #         :param owner:    Room 类
    #         :return:
    #         '''
    #         print("【get】")
    #         if instance is None:
    #             return self
    #         res = self.func(instance)
    #         setattr(instance, self.func.__name__, res)          # 实现延迟计算; 当传入的值是重复的时候,
    #         return res
    #
    #
    # class Room:
    #     def __init__(self, name, width, length):
    #         self.name = name
    #         self.width = width
    #         self.length = length
    #
    #     @Lazyproperty   # 新(Room类)area = Lazyproperty( 旧(Room类)area )
    #     def area(self): # self 代表的是实例本身;这里 self == 实例r1
    #         '''
    #         运行过程: 进行 Lazyproperty 中的 __get__ 函数 --> self.func(instance) ==  Room 类中的 area( r1 ) ->
    #                    运行Room 类中的 area( r1 )的内容 --> res 得到运行结果 ( Lazyproperty 中的 __get__ 函数)-->
    #                    return res
    #         :return:
    #         '''
    #
    #         print("【area】")
    #         return self.width * self.length
    #
    #     @property
    #     def area1(self):
    #         print("【area1】")
    #         return self.width * self.length
    #
    #
    # print("分割线11".center(150,"-"))
    # r1 = Room('厕所', 1, 1)
    #
    # print("分割线22".center(150,"-"))
    # print("Room.area1:  ", Room.area1)
    #
    # print("分割线33".center(150,"-"))
    # print("Room.area:   ", Room.area)
    #
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ------------------------------------------------------------------------分割线11-------------------------------------------------------------------------
    # # ------------------------------------------------------------------------分割线22-------------------------------------------------------------------------
    # # Room.area1:   <property object at 0x0000000001E18778>
    # # ------------------------------------------------------------------------分割线33-------------------------------------------------------------------------
    # # 【get】
    # # Room.area:    <__main__.Lazyproperty object at 0x0000000002976DA0>
    # #
    # # Process finished with exit code 0
    
    
    
    '''
    # # # classmethod  staticmethod 装饰器的实现 
    # # # 见:
    # # # 面向对象进阶 - linhaifeng - 博客园
    # https://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12
    '''
    
    
    
    
    
    #
    # 15 元类介绍
    # 15 元类介绍
    
    
    '''
    # ------------------------------------------------------------
    # # 21.1、元类的引入
    # # # python中一切皆为对象。类的本身也是一个对象,由 type 产生
    # ------------------------------------------------------------
    '''
    #
    # class Foo:
    #     pass
    #
    # f1 = Foo()    # 1是通过Foo类实例化的对象
    #
    # print(type(f1))
    # print(type(Foo))
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # <class '__main__.Foo'>
    # # <class 'type'>
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 22、type 元类来产生 类
    
    # # # FFo = type("FFo", (object,), {'x': 1})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3:{'x': 1},    类的属性字典
    # ------------------------------------------------------------
    '''
    
    #
    # class Foo:
    #     def __init__(self):
    #         pass
    #
    #
    # FFo = type("FFo", (object,), {'x': 1})
    #
    # print(Foo)
    # print(Foo.__dict__)
    #
    # print("分割线".center(150, "-"))
    # print(FFo)
    # print(FFo.__dict__)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # <class '__main__.Foo'>
    # # {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000039EE7B8>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
    # # -------------------------------------------------------------------------分割线--------------------------------------------------------------------------
    # # <class '__main__.FFo'>
    # # {'x': 1, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'FFo' objects>, '__weakref__': <attribute '__weakref__' of 'FFo' objects>, '__doc__': None}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 22.1、type 元类来产生 类
    # # # 给类中添加类的初始化属数,类的数值属性, 类的函数属性
    
    # # # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3: {'x':1, '__init__':__init__, 'test':test},    类的属性字典
    # # # 'x':1  相当于在类中定义数值属性   x = 1
    # # # '__init__':__init__  相当于在类中定义类初化始的函数属性   def __init__(self)
    # # # 'test':test          相当于在类中定义类的函数属性   def test(self)
    # ------------------------------------------------------------
    '''
    #
    # class Foo:
    #     def __init__(self):
    #         pass
    #
    # print(Foo)
    # print(Foo.__dict__)
    #
    # def __init__(self, name, age):
    #     self.name = name
    #     self.age  = age
    #
    # def test(self):
    #     print("【test】")
    #
    #
    # print("分割线".center(150,"-"))
    # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    #
    # print(FFo)
    # print(FFo.__dict__)           # 属性字典里头找到了FFo类的定义的属性
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # <class '__main__.Foo'>
    # # {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000039EE7B8>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
    # # -------------------------------------------------------------------------分割线--------------------------------------------------------------------------
    # # <class '__main__.FFo'>
    # # {'x': 1, '__init__': <function __init__ at 0x0000000002965620>, 'test': <function test at 0x00000000039EE840>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'FFo' objects>, '__weakref__': <attribute '__weakref__' of 'FFo' objects>, '__doc__': None}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 22.2、type 元类产生的类进行  实例化
    # # # 给类中添加类的初始化属数,类的数值属性, 类的函数属性
    
    # # # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3: {'x':1, '__init__':__init__, 'test':test},    类的属性字典
    # # # 'x':1  相当于在类中定义数值属性   x = 1
    # # # '__init__':__init__  相当于在类中定义类初化始的函数属性   def __init__(self)
    # # # 'test':test          相当于在类中定义类的函数属性   def test(self)
    # ------------------------------------------------------------
    '''
    #
    # def __init__(self, name, age):
    #     self.name = name
    #     self.age  = age
    #
    #
    # def test(self):
    #     print("【test】")
    #
    #
    # print("分割线".center(150,"-"))
    # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    #
    # ff1 = FFo("我是ff1", "999")
    # print("ff1.__dict__:    ", ff1.__dict__)
    # ff1.name = "这是啥一"
    # ff1.sex  = "None"
    # ff1.test()
    #
    # print("分割线".center(150,"-"))
    # print("ff1.name     ", ff1.name)
    # print("ff1.sex      ", ff1.sex)
    # # 可以看到,通过 type 产生的类能够进行实例化,这个与使用class定义的无差别
    # print("ff1.__dict__:    ", ff1.__dict__)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # -------------------------------------------------------------------------分割线--------------------------------------------------------------------------
    # # ff1.__dict__:     {'name': '我是ff1', 'age': '999'}
    # # 【test】
    # # -------------------------------------------------------------------------分割线--------------------------------------------------------------------------
    # # ff1.name      这是啥一
    # # ff1.sex       None
    # # ff1.__dict__:     {'name': '这是啥一', 'age': '999', 'sex': 'None'}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 22.3、类的产生总结
    # # # 类的产生有两种方式,1、通过 class来定义类;       2、通过type来产生类
    # ------------------------------------------------------------
    '''
    
    
    # 16 自定义元类
    # 16 自定义元类
    
    '''
    # ------------------------------------------------------------
    # # 23、自定义元类引入,元类定义自己的元类type
    # ------------------------------------------------------------
    '''
    #
    # class Foo():
    #     def __init__(self, name):     # FFo 类定义自己的元类
    #         self.name = name
    #
    #     def test(self):
    #         print("Foo【test】")
    #
    # class FFo(metaclass=type):       # FFo 类定义自己的元类; 相当于触发了 type('Foo', (object, ){})
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def test(self):
    #         print("FFo【test】")
    #
    #
    # print("Foo.__dict__:    ", Foo.__dict__)
    # print("FFo.__dict__:    ", FFo.__dict__)
    #
    # print(Foo)
    # print(FFo)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # Foo.__dict__:     {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000039EE7B8>, 'test': <function Foo.test at 0x00000000039EE840>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
    # # FFo.__dict__:     {'__module__': '__main__', '__init__': <function FFo.__init__ at 0x00000000039EE8C8>, 'test': <function FFo.test at 0x00000000039EE950>, '__dict__': <attribute '__dict__' of 'FFo' objects>, '__weakref__': <attribute '__weakref__' of 'FFo' objects>, '__doc__': None}
    # # <class '__main__.Foo'>
    # # <class '__main__.FFo'>
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 24、自定义元类引入,__call__ 方法介绍
    # # # 实例运加括号的时候,即实例 f1() 时候,会触发所属的类中的 __call__方法
    # ------------------------------------------------------------
    '''
    #
    # class Foo:
    #     def __call__(self, *args, **kwargs):
    #         print("我是__call__,我执行了!!")
    #
    # f1 = Foo()
    # print("f1()")
    #
    # f1()                    # f1的类Foo 下的__call__
    #
    # print("Foo()")
    # Foo()
    # print( Foo() )
    #
    # # D:Anaconda3python.exe D:/C_cache/py/day27_MianXiangDuiXiangJinJie/day27_MianXiangDuiXiangJinJie.py
    # # 我是__call__,我执行了!!
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 24.1、自定义元类引入,__call__ 方法介绍
    # # # 实例运加括号的时候,即实例 f1() 时候,会触发所属的类中的 __call__方法
    # ------------------------------------------------------------
    # '''
    #
    # class Foo:
    #     def __call__(self, *args, **kwargs):
    #         print("我是__call__,我执行了!!")
    #         print(args, kwargs)
    #
    # f1 = Foo()
    #
    # f1("11",22)            # f1的类Foo 下的__call__
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 我是__call__,我执行了!!
    # # ('11', 22) {}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 25.1、自定义元类引入1,元类定义自己的元类type
    # ------------------------------------------------------------
    '''
    #
    # class MyType(type):
    #     def __init__(self, a, b,c):
    #         '''
    #
    #         :param a:  类的名称, 这里是字符串 "Foo"
    #         :param b:  () 继承的对象,与上面的type 对比的话,可以发现,使用type定义时候,
    #             继承的是 object
    #         :param c:  类的属性字典,相当于 Foo.__dict__
    #         '''
    #         print("【元类执行了】")
    #         print("a:   ", a)
    #         print("b:   ", b)
    #         print("c:   ", c)
    #
    #
    #     '''
    #       FFo 类定义自己的元类; 如果是 默认的 Foo(metaclass=type)相当于触发了 type('Foo', (object, ),{})
    #       这里的Foo(metaclass=MyType) 就是 Mytype('Foo', (), Foo.__dict__)
    #
    #     '''
    # class Foo(metaclass=MyType):
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def test(self):
    #         print("FFo【test】")
    #
    #
    # print("dict:",Foo.__dict__)
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【元类执行了】
    # # a:    Foo
    # # b:    ()
    # # c:    {'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x00000000039EE840>, 'test': <function Foo.test at 0x00000000039EE8C8>}
    # # dict: {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000039EE840>, 'test': <function Foo.test at 0x00000000039EE8C8>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 25.2、自定义元类引入2,元类定义自己的元类type
    # ------------------------------------------------------------
    '''
    
    # class MyType(type):
    #     def __init__(self, a, b,c):
    #         '''
    #         注释:    Foo类,在编译器进行预编译处理的时候,就会运行这个 __init__
    #         :param a:  类的名称, 这里是字符串 "Foo"
    #         :param b:  () 继承的对象,与上面的type 对比的话,可以发现,使用type定义时候,
    #             继承的是 object
    #         :param c:  类的属性字典,相当于 Foo.__dict__
    #         '''
    #         print("【元类执行了】")
    #         # print("a:   ", a)
    #         # print("b:   ", b)
    #         # print("c:   ", c)
    #
    #     def __call__(self, *args, **kwargs):
    #         print("【__call__】")
    #
    #     '''
    #       FFo 类定义自己的元类; 如果是 默认的 Foo(metaclass=type)相当于触发了 type('Foo', (object, ),{})
    #       这里的Foo(metaclass=MyType) 就是 Mytype('Foo', (), Foo.__dict__)
    #
    #     '''
    # class Foo(metaclass=MyType):
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def test(self):
    #         print("FFo【test】")
    #
    #
    # print("dict:",Foo.__dict__)
    # # 运行Foo() 会触发Foo对应元类中的【__call__】;  注意到,这个操作实际上,就是相当于在使用类 Foo 进行实例化
    # Foo()
    # # Foo实例化的时候,触发,类 Foo 的元类中的 _call__方法
    # f1 = Foo("aaa")
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【元类执行了】
    # # dict: {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000039EE8C8>, 'test': <function Foo.test at 0x00000000039EE950>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
    # # 【__call__】
    # # 【__call__】
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 25.3、自定义元类引入2( 实例传入的内容信息),自定义元类中的 __call__ 方法
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    # # # __call__ 接收着,我们使用 Foo类 进行实例化时候的信息
    # ------------------------------------------------------------
    '''
    #
    # class MyType(type):
    #     def __init__(self, a, b,c):
    #         '''
    #         注释:    Foo类,在编译器进行预编译处理的时候,就会运行这个 __init__
    #         :param a:  类的名称, 这里是字符串 "Foo"
    #         :param b:  () 继承的对象,与上面的type 对比的话,可以发现,使用type定义时候,
    #             继承的是 object
    #         :param c:  类的属性字典,相当于 Foo.__dict__
    #         '''
    #         print("【元类执行了】")
    #         print("a:   ", a)
    #         print("b:   ", b)
    #         print("c:   ", c)
    #
    #     def __call__(self, *args, **kwargs):
    #         '''
    #                 说明:   这个部分的内容,实际上,储存着我们使用类进行实例化时候,传入的实例化的内容信息
    #                 self :  实例本身,这里传进来的是实例  Foo,  也叫 类Foo
    #         :param args:    接收 在 Foo进行实例化时候的内容信息
    #         :param kwargs: 接收 在 Foo进行实例化时候的内容信息
    #         :return:
    #         '''
    #         print("【__call__】")
    #         print("self:    ", self)
    #         print("args:    ", args)
    #         print("kwargs:  ", kwargs)
    #         print("分割线__call__".center(150, "-"))
    #
    #     '''
    #       FFo 类定义自己的元类; 如果是 默认的 Foo(metaclass=type)相当于触发了 type('Foo', (object, ),{})
    #       这里的Foo(metaclass=MyType) 就是 Mytype('Foo', (), Foo.__dict__)
    #
    #     '''
    # class Foo(metaclass=MyType):
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def test(self):
    #         print("FFo【test】")
    #
    #
    # print("dict:",Foo.__dict__)
    # # 运行Foo() 会触发Foo对应元类中的【__call__】;  注意到,这个操作实际上,就是相当于在使用类 Foo 进行实例化
    # Foo()
    # # Foo实例化的时候,触发,类 Foo 的元类中的 _call__方法
    # f1 = Foo("aaa")
    # f2 = Foo("f2在线", name="我是谁", age= "多少岁了", height=6.66)
    #
    # # print( f2.name)    # 报错,因为在 Foo类 的元类 __call__ 中,只是对该实例的内容进行接收,而没有储存着
    # #
    # #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【元类执行了】
    # # dict: {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000039EE8C8>, 'test': <function Foo.test at 0x00000000039EE950>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
    # # 【__call__】
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 25.3、自定义元类实现,自定义元类中的 __call__ 方法
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    
    # ------------------------------------------------------------
    '''
    #
    # class MyType(type):
    #     def __init__(self, a, b,c):
    #         '''
    #         注释:      1、Foo类,在编译器进行预编译处理的时候,就会运行这个 __init__
    #                     2、 这个是默认传入4个参数的,其中self是自动传入的,关于self,self是在使用类进行
    #                       实例化的时候,会自动传入的参数
    #
    #             self:  实例本身,这里传进来的是实例  Foo,  也叫 类Foo
    #         :param a:  类的名称, 这里是字符串 "Foo"
    #         :param b:  () 继承的对象,与上面的type 对比的话,可以发现,使用type定义时候,
    #             继承的是 object
    #         :param c:  类的属性字典,相当于 Foo.__dict__
    #         '''
    #         print("【元类执行了】")
    #         print("a:   ", a)
    #         print("b:   ", b)
    #         print("c:   ", c)
    #
    #     def __call__(self, *args, **kwargs):
    #         '''
    #                 说明:   这个部分的内容,实际上,储存着我们使用类进行实例化时候,传入的实例化的内容信息
    #                 self :  实例本身,这里传进来的是实例  Foo,  也叫 类Foo
    #         :param args:    接收 在 Foo进行实例化时候的内容信息
    #         :param kwargs: 接收 在 Foo进行实例化时候的内容信息
    #         :return:
    #         '''
    #         print("【__call__】")
    #         print("args:    ", args)
    #         print("kwargs:  ", kwargs)
    #         # 相当于进行object.__new__( Foo ); 这里是产生实例d对象,新式类中的对象继承的是object
    #         obj = object.__new__(self)
    #         self.__init__(obj, *args, **kwargs)
    #         print("分割线__call__".center(150, "-"))
    #         return obj      # 设置完成后,返回该对象
    #
    #     '''
    #       FFo 类定义自己的元类; 如果是 默认的 Foo(metaclass=type)相当于触发了 type('Foo', (object, ),{})
    #       这里的Foo(metaclass=MyType) 就是 Mytype('Foo', (), Foo.__dict__)
    #
    #     '''
    # class Foo(metaclass=MyType):
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def test(self):
    #         print("FFo【test】")
    #
    #
    # print("dict:",Foo.__dict__)
    # # 运行Foo() 会触发Foo对应元类中的【__call__】;  注意到,这个操作实际上,就是相当于在使用类 Foo 进行实例化
    # # Foo()         # 报错,因为这里需要传入一个类Foo 初始化的参数 name
    #
    # # Foo实例化的时候,触发,类 Foo 的元类中的 _call__方法 进行相关的属性设置
    # f1 = Foo("aaa")
    #
    # print( "f1.name:    ", f1.name)
    #
    # # f2 = Foo("f2在线", name="我是谁", age= "多少岁了", height=6.66)  # 报错,类 Foo 中只是有一个默认的参数
    #
    #
    #
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # 【元类执行了】
    # # a:    Foo
    # # b:    ()
    # # c:    {'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x00000000039EE8C8>, 'test': <function Foo.test at 0x00000000039EE950>}
    # # dict: {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000039EE8C8>, 'test': <function Foo.test at 0x00000000039EE950>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
    # # 【__call__】
    # # args:     ('aaa',)
    # # kwargs:   {}
    # # ---------------------------------------------------------------------分割线__call__----------------------------------------------------------------------
    # # f1.name:     aaa
    # #
    # # Process finished with exit code 0
    
    
    
    
    
    
    
    
    
    
    
    
    
    '''
    # ------------------------------------------------------------
    # # 25.4、自定义元类实现(简洁版)
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    # ------------------------------------------------------------
    '''
    #
    # class MyType(type):
    #     def __init__(self, a, b, c):
    #         '''
    #         注释:      Foo类,在编译器进行预编译处理的时候,就会运行这个 __init__
    #             self:  实例本身,这里传进来的是实例  Foo,  也叫 类Foo
    #         :param a:  类的名称, 这里是字符串 "Foo"
    #         :param b:  () 继承的对象,与上面的type 对比的话,可以发现,使用type定义时候,
    #             继承的是 object
    #         :param c:  类的属性字典,相当于 Foo.__dict__
    #         '''
    #         # print("【元类执行了】")
    #
    #     def __call__(self, *args, **kwargs):
    #         '''
    #                 说明:   这个部分的内容,实际上,储存着我们使用类进行实例化时候,传入的实例化的内容信息
    #                 self :  实例本身,这里传进来的是实例  Foo,  也叫 类Foo
    #         :param args:    接收 在 Foo进行实例化时候的内容信息
    #         :param kwargs: 接收 在 Foo进行实例化时候的内容信息
    #         :return:
    #         '''
    #         # print("【__call__】")
    #         # 相当于进行object.__new__( Foo ); 这里是产生实例d对象,新式类中的对象继承的是object
    #         obj = object.__new__(self)
    #         self.__init__(obj, *args, **kwargs)
    #         print("分割线__call__".center(150, "-"))
    #         return obj      # 设置完成后,返回该对象
    #
    #     '''
    #       FFo 类定义自己的元类; 如果是 默认的 Foo(metaclass=type)相当于触发了 type('Foo', (object, ),{})
    #       这里的Foo(metaclass=MyType) 就是 Mytype('Foo', (), Foo.__dict__)
    #
    #     '''
    # class Foo(metaclass=MyType):
    #     def __init__(self, name):
    #         self.name = name
    #
    #     def test(self):
    #         print("FFo【test】")
    #
    #
    # # Foo实例化的时候,触发,类 Foo 的元类中的 _call__方法 进行相关的属性设置
    # f1 = Foo("aaa")
    #
    # print( "f1.name:    ", f1.name)
    #
    # # D:Anaconda3python.exe D:/C_cache/py/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi/Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi.py
    # # ---------------------------------------------------------------------分割线__call__----------------------------------------------------------------------
    # # f1.name:     aaa
    # #
    # # Process finished with exit code 0
    

      


    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # ------------------------------------------------------------
    #
    # 参考资料:(未有转载)
    # 面向对象进阶 - linhaifeng - 博客园
    # https://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12
    #
    # python之函数介绍及使用 - 病毒尖er - 博客园
    # http://www.cnblogs.com/leguan1314/articles/6116928.html
    #
    # 元类metaclass - linhaifeng - 博客园
    # http://www.cnblogs.com/linhaifeng/articles/8029564.html
    #
    # ------------------------------------------------------------
    # ******************** day28-描述符应用与类的装饰器 *******************
    # ******************** day28-描述符应用与类的装饰器 *******************
    # =====>>>>>>内容概览
    # =====>>>>>>内容概览
    # Day28_MiaoShuFuYingYong_LeiDeZhuangShiQi


    # ------------------------------------------------------------
    # # 1、总结:
    # # # hasattr, getattr, setattr;;  getitem, setitem, delitem;; set, get, delete;; __del__
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 2、 __enter__ 与 __exit__
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3、 __enter__ 与 __exit__ 之文件异常引入
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3.1、 __enter__ 与 __exit__ 之文件异常引入1
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # # # 这个使用的方法是类似于 with open() as 文件名;    
    # # # 其中,文件打开时,触发 __enter__ , 文件运行到结束的时候,会触发 __exit__
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3.2、 __exit__ 中 exc_type, exc_val, exc_tb 之文件异常引入1
    # # # __exit__ 中的 exc_type, exc_val, exc_tb 就是文件异常的信息内容
    # # # __exit__ 中没有进行文件异常处理,一旦异常,后文件程序内容都不会运行的
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3.3、 __exit__ 中 exc_type, exc_val, exc_tb 之文件异常
    # # # __exit__ 中的 exc_type, exc_val, exc_tb 就是文件异常的信息内容
    # # # __exit__ 中的返回值设置为True时,文件的异常会结束该文件内容的操作,但是对于
    # # # 该操作外的操作信息不会有所影响,仍能够正常运行 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 3.4、总结 __enter__ 与 __exit__ 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 4、描述符的应用的引入
    # # # test给定的参数中,如果是字符串或者整形数字就输出,否则留报错!显然,
    # # # 下面的例子中,是不能够满足该要求的;  下面关于描述符的应用就是为了解决该问题
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 5、描述符中 __set__ 中的各个参数
    # # # __set__中的各个参数:
    # # # instance : 修饰的实例本身(下例中,就是实例p1)
    # # # value    :实例中修饰的那个值(下例中,就是 alex)
    # # # self     :描述符所在的类本身
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 6、描述符中 __get__ 中的各个参数
    # # # __get__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # # # owner    :修饰的实例所属的类(下例中,是类People)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 6.1、描述符中 __get__ 中的各个参数
    # # # __get__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # # # owner    :修饰的实例所属的类(下例中,是类People)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 6.2、描述符中 __delete__ 中的各个参数
    # # # __delete__ 中的各个参数:
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 7、__set__  使用描述符给给定的实例中传入值  
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 8、__set__  使用描述符对给定的实例 获取对应的值  
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 9、使用描述符对给定的实例 的值的设定进行限制1
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 9.1、使用描述符对给定的实例 的值的设定进行限制2
    # # # 对类进行修饰的时候,直接指定数值属性的  类型 ,如name 是str类型
    # # # instance :修饰的实例本身(下例中,就是实例p1)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 10、装饰器的引入,修饰函数
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 11、装饰器修饰 类
    # # # 类中的装饰器的运行的情况,是跟上面的函数的装饰器是有所区别的; 类中的是下运行类,之后再运行装饰器的运行
    # # # 而函数中的,是先运行装饰器中的内容,之后再运行函数的内容
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 12、函数也是有字典的
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 12.1、给函数的字典添加属性
    # # # 函数也可以像类一像添加属性,因为函数的本质就是类;python中的一切都是对像
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 13、使用装饰器给类中的字典添加属性
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 14、使用装饰器给类中的字典添加属性
    # # # 只能在装饰器中内部给定值的情况
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 14.1、使用装饰器给类中的字典添加属性1
    # # # 解决只能在装饰器中内部给定值的情况
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 15、装饰器的应用(与前面的序号10对比)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 16、property 的使用
    # # # property() 函数的作用是在新式类中返回属性值。
    # # # 下面例子中,(原)r1.area()-->>(现)r1.area 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 17、property引入 , 类的装饰器
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18、property装饰器初步 , 类的装饰器
    # # # print(r1.area.func(r1))   实现了基本的装饰器功能
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18.1、property装饰器初步之 __get__ , 类的装饰器
    # # # 目标: print(r1.area.func(r1)) ==>> 等价于执行   print(r1.area) 
    # # # __get__ 接受被修饰对象中的实例, 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18.2、property装饰器“实现”之 __get__ 返回运行的内容, 类的装饰器
    # # # 目标(实现): print(r1.area.func(r1)) ==>> 等价于执行   print(r1.area) 
    # # # __get__ 接受被修饰对象中的实例, 
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18.3、property装饰器“实现” (简洁版)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 18.4、property装饰器“实现” (简洁版) 与 内置的property装饰器对比1
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 19、property装饰器,之类调用静态属性 对比
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 19.1、property装饰器,之类调用静态属性,实现property的完整功能( 类无法调用静态属性)
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 20、__name__获取函数的名字
    # # # 用来获取运行的模块的名字,  或者对应的对象的名字(类是获取不到名字的)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 21、property装饰器,之类调用静态属性,实现property的完整功能
    # # # “实现” (简洁版) 与 内置的property装饰器
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 21.1、元类的引入
    # # # python中一切皆为对象。类的本身也是一个对象,由 type 产生
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 22、type 元类来产生 类

    # # # FFo = type("FFo", (object,), {'x': 1})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3:{'x': 1},    类的属性字典
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 22.1、type 元类来产生 类
    # # # 给类中添加类的初始化属数,类的数值属性, 类的函数属性

    # # # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3: {'x':1, '__init__':__init__, 'test':test},    类的属性字典
    # # # 'x':1  相当于在类中定义数值属性   x = 1
    # # # '__init__':__init__  相当于在类中定义类初化始的函数属性   def __init__(self)
    # # # 'test':test          相当于在类中定义类的函数属性   def test(self)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 22.2、type 元类产生的类进行  实例化
    # # # 给类中添加类的初始化属数,类的数值属性, 类的函数属性

    # # # FFo = type("FFo", (object,), {'x':1, '__init__':__init__, 'test':test})
    # # # type(位置1, 位置2, 位置3)
    # # # 位置1:"FFo",      类名
    # # # 位置2:(object,),  对象, 新式类的对象是 object, python3中所有的类都是新式类
    # # # 位置3: {'x':1, '__init__':__init__, 'test':test},    类的属性字典
    # # # 'x':1  相当于在类中定义数值属性   x = 1
    # # # '__init__':__init__  相当于在类中定义类初化始的函数属性   def __init__(self)
    # # # 'test':test          相当于在类中定义类的函数属性   def test(self)
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 22.3、类的产生总结
    # # # 类的产生有两种方式,1、通过 class来定义类;       2、通过type来产生类
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 23、自定义元类引入,元类定义自己的元类type
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 24、自定义元类引入,__call__ 方法介绍
    # # # 实例运加括号的时候,即实例 f1() 时候,会触发所属的类中的 __call__方法
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 24.1、自定义元类引入,__call__ 方法介绍
    # # # 实例运加括号的时候,即实例 f1() 时候,会触发所属的类中的 __call__方法
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.1、自定义元类引入1,元类定义自己的元类type
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.2、自定义元类引入2,元类定义自己的元类type
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.3、自定义元类引入2( 实例传入的内容信息),自定义元类中的 __call__ 方法
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    # # # __call__ 接收着,我们使用 Foo类 进行实例化时候的信息
    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.3、自定义元类实现,自定义元类中的 __call__ 方法
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):

    # ------------------------------------------------------------

    # ------------------------------------------------------------
    # # 25.4、自定义元类实现(简洁版)
    # # # 这里需要关注的是 __call__下的参数的内容==》》 def __call__(self, *args, **kwargs):
    # ------------------------------------------------------------

     

    # ------------------------------------------------分割线-------------------------------------------------
    # ------------------------------------------------分割线-------------------------------------------------
    # ------------------------------------------------分割线-------------------------------------------------
  • 相关阅读:
    数组中[::-1]或[::-n]的区别,如三维数组[:,::-1,:]
    类中__iter__与__next__的说明
    LoadRunner 事务响应时间的组成
    LoadRunner 中调用c函数生成随机字符串
    LoadRunner系列之—-02 基于webservice协议的接口测试(脚本实例)
    java 生成压测数据
    java实现从报文中获取投保单号
    接口测试怎么做
    LoadRunner中存储表格参数------关联数组
    视频录制软件&远程支持软件
  • 原文地址:https://www.cnblogs.com/jyfootprint/p/9492640.html
Copyright © 2011-2022 走看看