python面向对象第二周魔术方法详解

魔法方法及其使用
__开头和结束的方法,定义外部没有办法直接调用,但会有影响使用
运算符号的魔法方法, + ,-,*,/,%,//,**, __add__,__sub__,__mul__,__truediv__,__mod__,__floordiv__,__pow__,
__divmod__(?),
系统内部对于数值型,字符串型,容器内型都定义了其中部分或者全部的运算符使用要求和办法,
我们在类中定义这些魔法方法,可以使得它们按照需要对对象类型进行运算符运算, 仍需要满足一些基本的概念
比如加减乘除都是在两个对象而言的,所以形参数量要为二 ,且其中一个为self(类自身的对象)其他大部分的运算符魔法方法对于参数数量和类型也有类似要求,
其他变种运算符 +=,-=,*=,/=,%=,//=,**= ,它们的魔法方法写法就是相应的名称前加一个i,它们对于形参数和类型也与前面的类似
判断运算符 <,<=,==,>,>=,!=
和运算符号的一样,他么的返,定义一般要求两个参数,且其中一个为self(类自身的对象),它们不一定要求返回布尔型的值,可以没有或者返回其他类型的值
在使用这些运算符对系统数据类型使用这些符号时不会有覆盖,或者不能使用的问题,因为他们内部的类中有魔法方法定义使用这些符号的使用规则,即使我们在自定义的类中对基本数据类型时使用运算符,依然能够准确表达含义

容器相关方法:__len__,__iter__,__contains__,__getitem__,__setitem__,__missing__
获取长度,迭代器, in运算符,索引访问,索引设置,其它
容器相关方法,在基本数据类型中的容器类型,list,tuple,set,dict中有实现其中大部分或全部方法,
对他们调用 len( ),可以使用是因为实现了__len__的魔法方法,在类中可以定义它,使得我们也可以在外部调用该方法,这个方法要求只有一个形参,且为类的对象,要有返回值且为整型,使用 len(对象)会调用这个方法
当迭代一个对象(使用for in 遍历)时会调用__iter__的方法,获取该方法返回的迭代器,for in 遍历的实质是遍历这个迭代器,所以这个对象可以被成为可迭代对象,任何数据类型如果实现__iter_就是一个可迭代类型. 实现__iter__
方法要求传入一个参数,为self(类自身的对象)返回一个迭代器 (iter( )函数,yield from iterable都可以返回一个迭代器)
__contains__(self,item) 使用判断语句 in 的时候调用的方法 如果使用 ” item in 对象 ” 就会调用这个方法
如果没有定义该方法依然可以使用,in 语句 自是他会自动调用 对象的 __iter__方法获取它的迭代器 相当于对对迭代器使用 in 语句. __contains__ 方法要求有返回值且为布尔型,若不为布尔型根据返回值是否为空类型返回True 或 False
索引访问 对象[ ] ,调用__getitem__方法 __getitem__(self,item) item为索引
形参只能为两个(如果不定义两个调用时将会出现无法处理的错误),item为传入中括号中的值,但系统对这个值要求非常松,可以为任意类型
使用索引赋值(赋值即定义) 对象[ ] =值 ,调用__setitem__方法 __setitem__(self,key,value) key为中括号中的值,value为等号右边的值
其他 __missing__, 当调用了__getitem__()方法,而key不存在就会调用这个方法(只能被动的调用)

总结:魔法方法,在使用中不像普通方法一样调用方法名就能够使用,他是系统中设置好的,我们在类中能够对它重写,对于运算符,重写的要求很简单,传入两个参数对于函数内部实现没有要求. 对于函数体实现没有要求.
对于容器类型的相关方法,它的参数可能要求很低,但使用中可能会出错,很多对于返回值也有要求,要求有且返回
指定类型. 实际在一个容器中,对于函数的实现它的要求其实会更高,例如它要实现索引设置和获取,要求把设置的内容保存,获取时从内部获取.基本数据类型中除了容器类型,还有其他类型实现了其中的部分方法

对象的打印,正常使用print函数打印一个对象会获得<__main__.A object at 0x00000272662DF6A0>这样的结果
__repr__ , __str__ 两个方法可以作为对象的显示方法
在print 和 format 函数中如果要打印对象会优先调用__str__方法, 如果打印一个包装了对象的基本数据类型的时候,会先执行打印基本数据类型的方法,其中的对象只会调用对象的__repr__方法

可调用对象__call__ 如果一个对象可以像函数一样的访问,因为实现了这个方法,对参数,返回值没有要求
__enter__,__exit__,使用条件苛刻,上下文管理(with语句)时才会执行,这两个方法都是被动调用的

@functools.total_ordering装饰器
类中实现包含等于,包含大于小于之一的两个方法就会实现六个方法

反射相关魔术方法:
首先看看反射相关的内建函数 getattr(对象,name[,default]) 通过name(字符串类型) 获取对象中叫作name的属性,没有就返回default,没设置会报错
setattr(对象,name,value) 设置对象的属性和值,有就覆盖,没有就新增
hasattr(对象,name) 判断对象是否有这个名字的属性
__getattr__(self,item) 外部对对象使用 对象.name 访问时,访问字典不能得到,最后执行的方法
__setattr__(self,key,value) 需要通过 对象.key = value 来为对象添加属性的时候自动调用,并拦截添加或覆盖操作,需要在其中重写这个方法,或用属性字典手动添加
__delattr__ 使用del语句删除对象时调用,并拦截删除
__getattribute__ 获取对象属性时会优先执行,如果要能正常执行获得真实结果返回
return object.__getattribute__(self.item)

总结:魔术方法,如果定义只要满足调用的条件就会自动的触发,暂时没有出现可以自行设置触发条件的魔术方法.
方法中,系统实现的部分直接或间接指示了参数含义,如果不顺着系统意思,在实际调用中可能会出现意想不到的错误. 类中的方法在实现时如果满足类中定义的魔术方法触发条件,将会触发. 魔术方法除了有方便应用和表达含义的符号,还有的实现特殊功能的,比如上下文管理 ,__call__外部访问,这些方法极大地扩展了类的功能.
显示和反射有关的魔术方法都属于工程,工具类型的魔术方法

描述器和它的三个魔术方法
:__get__ (self,instance,owner), __set__(self,instance,value) , __delete__(self, instance)
__get__ 外部的类的属性(类变量)访问就会调用,这个方法, 对象如果通过类变量访问,也会调用,它的返回值为访问到的值
__set__ 外部的类中设置对象属性值会调用,并拦截对象属性的设置

一个类中如果有这几个方法之一它就是一个描述器
如果一个类中的类属性(类变量)引入了一个描述器对象, 修饰器就能够作用于这个类. 满足条件的情况就会调用描述器中的方法. 分为很多情况
1,只有__get__, 描述器被类访问,会调用描述方法,且类变量的值为它的返回值,如果它对象通过类变量访问到修饰器,也会执行相同的操作
2,只有__set__, 在类的内部或外部,给类的对象添加或修改与描述器变量名相同的属性, 会触发描述器方法,它的返回值没有意义
3,有__del__, 在外部使用del 作用对象访问的,与描述器变量名想同的属性时,会调用 ,如果是用类访问到的不会调用

对于一个描述器有多个这样的方法,如果满足各自的条件就会触发访问,其中只有__get__为 非数据描述器
有__get__和__set__成为为数据描述器. 描述器的使用大概分为三块:1,定义描述器2,生成被描述的类并加载描述器3,外部调用被描述类的属性触发描述方法,后两种它可以起到对特定属性的监视作用.
数据描述器功能比非数据描述器强大

应用实例定义一个静态方法装饰器
class StaticMtd:
def __init__(self,fn):
self.fn = fn
def __get__(self, instance, owner):
print(‘get’)
return self.fn
def __set__(self, instance, value):
print(self,instance,value)
print(‘set’)
class A:
@StaticMtd # add = StaticMtd(add) 相当与引入了一个描述器
def add(x,y):
print(x,y)
A.add(4,5) #使用类访问触发描述器的方法
a =A()
a.add = 3 #使用对象添加与描述器变量名相同属性,触发set方法

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/88806

(1)
daishitongdaishitong
上一篇 2017-11-21
下一篇 2017-11-23

相关推荐

  • Linux磁盘和文件系统管理

      Linux磁盘和文件系统管理.pdf Part.I 磁盘管理 1.cfdisk   #图形化的很简单. 不知道你们用什么 反正我喜欢这个 ^_^ cfdisk – display or manipulate disk partition table 必要参数的具体说明如下: -a用箭头表示选取,而不是以反白表示 …

    Linux干货 2016-04-05
  • 第五周练习

    1、显示当前系统上root、fedora或user1用户的默认shell; egrep “^(root|fedora|user1)” /etc/passwd | cut -d: -f7 2、找出/etc/rc.d/init.d/functions文件中某单词后边跟一组小括号的行,形如:hello(); grep “\<.*\>()” /etc/r…

    Linux干货 2017-08-04
  • grep、egrep正则表达式之初窥门径

    何谓正则表达式 正则表达式,又称正规表示法、常规表示法(Regular Expression,在代码中常简写为regex、regexp或RE),是一类字符所书写的模式,其中许多字符不表示其字面意义,而是表达控制或通配等功能。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的…

    2015-03-19
  • Shell脚本编程基础

    1编程基础 程序:指令+数据 程序编程分格: 过程式:以指令为中心,数据服务于指令 对象式:以数据为中心,指令服务于数据 Shell程序:提供了编程能力,解释执行 程序的执行方式 计算机:运行二进制指令 编程语言: 低级:汇编 高级:编译:高级语言->编译器->目标代码 编译性语言编写的程序通常是需要通过编译器去转换成计算机可以识别的二进制文件,…

    2017-11-27
  • 进程管理

    一、进程概述 1、进程的概念        用户通过执行命令,将程序提起到内存中运行,运行中的程序即称为进程。内核为了方便管理,根据内核发起者的权限、属性等参数,为每个进程设置一个独立的PID号,通过PID号来判断进程的权限。 2、进程的分类:    &nbs…

    Linux干货 2016-09-07
  • nmcli命令用法简介

    nmcli:地址配置工具 用法:nmcli [OPTIONS] OBJECT { COMMAND | help } 一般使用的情况有: 设备:正在使用的网络端口 链接:一组配置设置,对于一个单一的设备可以有多个连接,可以在链接之间切换 常用命令:     nmcli connection show &nbsp…

    Linux干货 2016-09-07