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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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:\Anaconda3\python.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):
# ------------------------------------------------------------

 

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

猜你喜欢

转载自www.cnblogs.com/jyfootprint/p/9492640.html