面向对象十三类的魔术方法

Posted youxiu123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象十三类的魔术方法相关的知识,希望对你有一定的参考价值。

 一、 __getattribute__
技术图片
class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print(执行的是我)
        # return self.__dict__[item]

f1=Foo(10)
print(f1.x)
f1.xxxxxx #不存在的属性访问,触发__getattr__

回顾__getattr__
回顾__getattr__
技术图片
class Foo:
    def __init__(self,x):
        self.x=x

    def __getattribute__(self, item):
        print(不管是否存在,我都会执行)

f1=Foo(10)
f1.x
f1.xxxxxx

 __getattribute__
__getattribute__
class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print(执行的是我)
        # return self.__dict__[item]
    def __getattribute__(self, item):
        print(不管是否存在,我都会执行)
        raise AttributeError(哈哈)

f1=Foo(10)
f1.x
f1.xxxxxx

#当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError

二者同时出现

二、__getitem__,__setitem__,__delitem__

同__getattr__,__setattr__,__delattr__;

只是在操作时以字典的方式操作

技术图片 代码演示

三、自定制__str__、__repr__

技术图片 默认情况下
技术图片 定制__str__

__repr__同__str__

__repr__应用在解释器中显示

技术图片 二者同时出现时

 四、自定制格式化方法__fomat__

技术图片 定制显示时间格式

 五、__slots__

技术图片 slots使用
技术图片 View Code

 六、__doc__

技术图片 View Code
技术图片 View Code

七、__module__和__class__

__module__ 表示当前操作的对象在那个模块

__class__     表示当前操作的对象的类是什么

技术图片 View Code
技术图片 View Code

 八、__del__

析构方法,当对象在内存中被释放时,自动触发执行。

注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了__del__

技术图片 代码演示

典型的应用场景:

创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中

当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源

这与文件处理是一个道理:

技术图片
f=open(‘a.txt‘) #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件
del f #只回收用户空间的f,操作系统的文件还处于打开状态

#所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是
f=open(‘a.txt‘)
读写...
f.close()
很多情况下大家都容易忽略f.close,这就用到了with上下文管理
技术图片

 九、__cal__

对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

技术图片 View Code

十、__next__和__iter__实现迭代器协议

技术图片 简单示范
技术图片 简单示例
技术图片 斐波那契数列

 十一、__get__,__set__,__delete__描述符

1 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发

技术图片 定义一个描述符

2 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)

技术图片 引子:描述符类产生的实例进行属性操作并不会触发三个方法的执行
技术图片 描述符应用之何时?何地?

3 描述符分两种
一 数据描述符:至少实现了__get__()和__set__()

1 class Foo:
2      def __set__(self, instance, value):
3          print(‘set‘)
4      def __get__(self, instance, owner):
5          print(‘get‘)

二 非数据描述符:没有实现__set__()

1 class Foo:
2      def __get__(self, instance, owner):
3          print(‘get‘)

4 注意事项:
一 描述符本身应该定义成新式类,被代理的类也应该是新式类
二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
三 要严格遵循该优先级,优先级由高到底分别是
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()

技术图片 类属性>数据描述符
技术图片 数据描述符>实例属性
技术图片 实例属性>非数据描述符
技术图片 再次验证:实例属性>非数据描述符
技术图片 非数据描述符>找不到

5 描述符使用

众所周知,python是弱类型语言,即参数的赋值没有类型限制,下面我们通过描述符机制来实现类型限制功能

技术图片牛刀小试
技术图片 拔刀相助
技术图片 磨刀霍霍
技术图片 大刀阔斧

大刀阔斧之后我们已然能实现功能了,但是问题是,如果我们的类有很多属性,你仍然采用在定义一堆类属性的方式去实现,low,这时候我需要教你一招:独孤九剑

技术图片 类的装饰器:无参
技术图片 类的装饰器:有参

终极大招

技术图片 刀光剑影

6 描述符总结

描述符是可以实现大部分python类特性中的底层魔法,包括@classmethod,@staticmethd,@property甚至是__slots__属性

描述符是很多高级库和框架的重要工具之一,描述符通常是使用到装饰器或者元类的大型框架中的一个组件

 

 

以上是关于面向对象十三类的魔术方法的主要内容,如果未能解决你的问题,请参考以下文章

面向对象

面向对象的程序设计

面向对象之魔术方法

python面向对象魔术方法补充

Python面向对象-魔术方法

面向对象之魔术方法