#!/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):
# ------------------------------------------------------------
# ------------------------------------------------分割线------------------------------------------------- # ------------------------------------------------分割线------------------------------------------------- # ------------------------------------------------分割线-------------------------------------------------