获取属性

  • __ getattr __(self, name) 定义当用户试图获取一个不存在的属性时的行为
  • __ getattribute __(self, name) 定义当该类的属性被访问时的行为 (获取属性一定会走到这个方法,获取不到属性去访问 __ getattr __)
  • __ setattr __(self, name, value) 定义当一个属性被设置时的行为,小心递归调用
  • __ delattr __(self, name) 定义当一个属性被删除时的行为
  • __ dir __(self) 定义当 dir() 被调用时的行为
  • __ get __(self, instance, owner) 定义当描述符的值被取得时的行为
  • __ set __(self, instance, value) 定义当描述符的值被改变时的行为
  • __ delete __(self, instance) 定义当描述符的值被删除时的行为

实例对象属性寻找的顺序如下:

① 首先访问 getattribute() 魔法方法(隐含默认调用,无论何种情况,均会调用此方法)

② 去实例对象t中查找是否具备该属性: t.dict 中查找,每个类和实例对象都有一个 dict 的属性

③ 若在 t.dict 中找不到对应的属性, 则去该实例的类中寻找,即 t.class.dict

④ 若在实例的类中也招不到该属性,则去父类中寻找,即 t.class.bases.__dict__中寻找

⑤ 若以上均无法找到,则会调用 getattr 方法,执行内部的命令(若未重载 getattr 方法,则直接报错:AttributeError)

以上几个流程,即完成了属性的寻找。

注意: 第④步,一个类一旦重载了 getattribute() 方法,如果找不到属性,则必须要手动加入第④步,否则无法进入到 第⑤步 (getattr)的。可以用super解决


class Test:
def __getattr__(self, name):
print('__getattr__') def __getattribute__(self, name):
print('__getattribute__')
super().__getattribute__(name) def __setattr__(self, name, value):
print('__setattr__') def __delattr__(self, name):
print('__delattr__') >>> t=Test()
>>> t.x
__getattribute__
__getattr__

某个类,只要是内部定义了方法 get, set, delete 中的一个或多个,就可以称为描述符


class Desc(object): def __get__(self, instance, owner):
print("__get__...")
print("self : \t\t", self)
print("instance : \t", instance)
print("owner : \t", owner)
print('='*40, "\n") def __set__(self, instance, value):
print('__set__...')
print("self : \t\t", self)
print("instance : \t", instance)
print("value : \t", value)
print('='*40, "\n") class TestDesc(object):
x = Desc() #以下为测试代码
t = TestDesc()
t.x #以下为输出信息: __get__...
self : <__main__.Desc object at 0x0000000002B0B828>
instance : <__main__.TestDesc object at 0x0000000002B0BA20>
owner : <class '__main__.TestDesc'>

注意: 查找顺序问题:当Python解释器发现实例对象的字典中,有与描述符同名的属性时,描述符优先,会覆盖掉实例属性。

属性查询优先级小总结

    ① getattribute(), 无条件调用

    ② 数据描述符:由 ① 触发调用 (若人为的重载了该 getattribute() 方法,可能会导致无法调用描述符)

    ③ 实例对象的字典(若与描述符对象同名,会被覆盖哦)

    ④ 类的字典

    ⑤ 非数据描述符

    ⑥ 父类的字典

    ⑦ getattr() 方法

基本魔术方法

  • __ new __(cls[, ...])

  • new 是在一个对象实例化的时候所调用的第一个方法

  • 它的第一个参数是这个类,其他的参数是用来直接传递给 init 方法

  • new 决定是否要使用该 init 方法,因为 new 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 new 没有返回实例对象,则 init 不会被调用

  • new 主要是用于继承一个不可变的类型比如一个 tuple 或者 string

  • __ init __(self[, ...])

    构造器,当一个实例被创建的时候调用的初始化方法

  • __ del __(self)

    析构器,当一个实例被销毁的时候调用的方法

  • __ call __(self[, args...])

    允许一个类的实例像函数一样被调用:x(a, b) 调用 x.call(a, b)

  • __ len __(self)

    定义当被 len() 调用时的行为

  • __ repr __(self)

    定义当被 repr() 调用或者直接执行对象时的行为

  • __ str __(self)

    定义当被 str() 调用或者打印对象时的行为

  • __ bytes __(self)

    定义当被 bytes() 调用时的行为

  • __ hash __(self)

    定义当被 hash() 调用时的行为

  • __ bool __(self)

    定义当被 bool() 调用时的行为,应该返回 True 或 False

  • __ format __(self, format_spec)

    定义当被 format() 调用时的行为

切片和索引

class Student(object):
def __init__(self, name, scores):
self.name = name
self.scores = scores # 索引的是学生的成绩
def __getitem__(self, index): # 1).索引值的获取
print(index, type(index))
return self.scores[index] def __setitem__(self, key, value): # 2). 索引值的重新赋值
self.scores[key] = value def __delitem__(self, key): # 3). 删除索引值
del self.scores[key] def __mul__(self, other): # 4). 实现*的效果, 具体返回什么取决于代码的业务需求
"""对于学生的每一门成绩乘3"""
return [i*other for i in self.scores] def __add__(self, other): # 5). 连接的时候必须是同一种数据;类型
# 将两个学生的成绩拼接起来
return self.scores + other.scores def __contains__(self, item): # 6). 判断某个元素是否存在于这个对象中?
return item in self.scores def __iter__(self): # 7). 迭代, 使得该对象可以实现for循环
# 将列表转换为迭代的类型, 可以for循环, 一定要返回iter类型的数据;
return iter(self.scores) def __lt__(self, other): # 8). 比较两个对象的大小;
return (sum(self.scores)/3) < (sum(other.scores)/3) liming = Student('liming', [100, 89, 100]) # # 1).索引值的获取
# print(liming[0])
# print(liming[1])
# print(liming[2])
#
# # 2).索引值的重新赋值
# liming[0] = 90
# print(liming[0])
#
# # 3). 删除索引值
# del liming[0]
# # print(liming[:2])
# # # 1).切片值的获取
# print(liming[:2])
# print(liming[-2:])
#
#
# # 2).切片值的重新赋值
# liming[:2] = [10, 10]
# print(liming.scores)
#
# # 3). 删除切片值
# del liming[:2]
# print(liming.scores) #
# # 4). 判断是否可以重复?
# print(liming * 3)
#
# # 5). 连接?
xiaohong = Student('小红', [100, 90, 90])
# print(xiaohong + liming)
#
#
#
# # 6). 成员操作符? 判断是否在对象里面存在?
# print(100 in xiaohong)
# print(101 in xiaohong)
# print(101 not in xiaohong)
#
# # # 7). 实现for循环?
# for item in liming:
# print(item) # 8). 比较对象的大小?
# print(liming > xiaohong)
print(liming < xiaohong)

比较操作符

  • __ lt __(self, other) 定义小于号的行为:x < y 调用 x.lt(y)
  • __ le __(self, other) 定义小于等于号的行为:x <= y 调用 x.le(y)
  • __ eq __(self, other) 定义等于号的行为:x == y 调用 x.eq(y)
  • __ ne __(self, other) 定义不等号的行为:x != y 调用 x.ne(y)
  • __ gt __(self, other) 定义大于号的行为:x > y 调用 x.gt(y)
  • __ ge __(self, other) 定义大于等于号的行为:x >= y 调用 x.ge(y)

算数运算符

  • __ add __(self, other) 定义加法的行为:+
  • __ sub __(self, other) 定义减法的行为:-
  • __ mul __(self, other) 定义乘法的行为:*
  • __ truediv __(self, other) 定义真除法的行为:/
  • __ floordiv __(self, other) 定义整数除法的行为://
  • __ mod __(self, other) 定义取模算法的行为:%
  • __ divmod __(self, other) 定义当被 divmod() 调用时的行为
  • __ pow __(self, other[, modulo]) 定义当被 power() 调用或 ** 运算时的行为
  • __ lshift __(self, other) 定义按位左移位的行为:<<
  • __ rshift __(self, other) 定义按位右移位的行为:>>
  • __ and __(self, other) 定义按位与操作的行为:&
  • __ xor __(self, other) 定义按位异或操作的行为:^
  • __ or __(self, other) 定义按位或操作的行为:|

反运算

  • __ radd __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rsub __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rmul __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rtruediv __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rfloordiv __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rmod __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rdivmod __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rpow __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rlshift __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rrshift __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rand __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ rxor __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
  • __ ror __(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)

增量赋值运算

  • iadd(self, other) 定义赋值加法的行为:+=
  • isub(self, other) 定义赋值减法的行为:-=
  • imul(self, other) 定义赋值乘法的行为:*=
  • itruediv(self, other) 定义赋值真除法的行为:/=
  • ifloordiv(self, other) 定义赋值整数除法的行为://=
  • imod(self, other) 定义赋值取模算法的行为:%=
  • ipow(self, other[, modulo]) 定义赋值幂运算的行为:**=
  • ilshift(self, other) 定义赋值按位左移位的行为:<<=
  • irshift(self, other) 定义赋值按位右移位的行为:>>=
  • iand(self, other) 定义赋值按位与操作的行为:&=
  • ixor(self, other) 定义赋值按位异或操作的行为:^=
  • ior(self, other) 定义赋值按位或操作的行为:|=

一元操作符

  • pos(self) 定义正号的行为:+x
  • neg(self) 定义负号的行为:-x
  • abs(self) 定义当被 abs() 调用时的行为
  • invert(self) 定义按位求反的行为:~x

类型转换

  • complex(self) 定义当被 complex() 调用时的行为(需要返回恰当的值)
  • int(self) 定义当被 int() 调用时的行为(需要返回恰当的值)
  • float(self) 定义当被 float() 调用时的行为(需要返回恰当的值)
  • round(self[, n]) 定义当被 round() 调用时的行为(需要返回恰当的值)
  • index(self)
  • 当对象是被应用在切片表达式中时,实现整形强制转换
  • 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 index
  • 如果 index 被定义,则 int 也需要被定义,且返回相同的值

上下文管理(with 语句)

  • enter(self)
  • 定义当使用 with 语句时的初始化行为
  • enter 的返回值被 with 语句的目标或者 as 后的名字绑定
  • exit(self, exc_type, exc_value, traceback)
  • 定义当一个代码块被执行或者终止后上下文管理器应该做什么
  • 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作

容器类型

  • len(self) 定义当被 len() 调用时的行为(返回容器中元素的个数)
  • getitem(self, key) 定义获取容器中指定元素的行为,相当于 self[key]
  • setitem(self, key, value) 定义设置容器中指定元素的行为,相当于 self[key] = value
  • delitem(self, key) 定义删除容器中指定元素的行为,相当于 del self[key]
  • iter(self) 定义当迭代容器中的元素的行为
  • reversed(self) 定义当被 reversed() 调用时的行为
  • contains(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为

python魔术方法总结的更多相关文章

  1. python魔术方法

    在类中有一些特殊的方法具有特殊的意义,比如__init__和__del__方法,它们的重要性我们已经学习过了. 一般说来,特殊的方法都被用来模仿某个行为.例如,如果你想要为你的类使用x[key]这样的 ...

  2. Python 魔术方法笔记

    魔术方法总是被__包围, 如__init__ , __len__都是常见的魔术方法,这里主要写一下我遇到的一些魔术方法 setitem 对某个索引值赋值时 即可以进行赋值操作,如 def __seti ...

  3. 记一次 Apache HUE 优化之因使用 Python 魔术方法而遇到的坑

    最近的工作是基于 Apache HUE 做二次开发.刚接手 HUE 的代码的时候,内心是崩溃的:开源的代码,风格很多种, 代码比较杂乱; 虽是基于 Django 开发的,但是项目的结构改变很大; 很多 ...

  4. Python魔术方法-Magic Method

    介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...

  5. Python 魔术方法指南

    入门 构造和初始化 构造定制类 用于比较的魔术方法 用于数值处理的魔术方法 表现你的类 控制属性访问 创建定制序列 反射 可以调用的对象 会话管理器 创建描述器对象 持久化对象 总结 附录 介绍 此教 ...

  6. 032.Python魔术方法__new__和单态模式

    一 __new__ 魔术方法 1.1 介绍 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当前的类,其他根据情况决定 返回值 ...

  7. [python]魔术方法

    一.初始化: 1.__new__方法,初始化过程中第一个用到的方法(用处不大). 2.之后,__init__方法,构造方法. 3.最后,在对象回收时,调用__del__方法.如果解释器退出时,对象还存 ...

  8. Python 魔术方法及调用方式

    魔术方法 调用方式 解释 __new__(cls [,...]) instance = MyClass(arg1, arg2) __new__ 在创建实例的时候被调用 __init__(self [, ...

  9. python魔术方法(__init__,__call__,被双下划线包围的方法)

    转载link:http://pycoders-weekly-chinese.readthedocs.io/en/latest/issue6/a-guide-to-pythons-magic-metho ...

随机推荐

  1. Innodb表空间迁移过程

    1.大致流程 将a实例的表的数据迁移到b实例上. 1.在目标实例b上创建一个相同的表 2.在目标库b上执行ALTER TABLE t DISCARD TABLESPACE; 3.在源库a上执行FLUS ...

  2. 【java从入门到精通】day10-Java流程控制2-switch多选择结构

    1.switch多选择结构 switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支. switch语句中的变量类型可以是: byte.short.int或者char 从j ...

  3. iscsi客户端常用操作

    说明 本篇主要记录iscsi的客户端的一些常用的一些操作 iscsi服务端常用操作 删除一个lun tgtadm --lld iscsi --mode logicalunit --op delete ...

  4. DockerPush

    1.阿里云镜像发布流程 2.镜像生成 语法:docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]] [root@pluto data]# docker imag ...

  5. 04、MyBatis DynamicSQL(Mybatis动态SQL)

    1.动态SQL简介 动态 SQL是MyBatis强大特性之一. 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似. MyBatis 采用功能强大的基于 OGNL 的表达式来 ...

  6. 工作流(workflow)

    1,JBPM 工作流(开源历史悠久) 2,activity 工作流(开源历史悠久) 3,workable 工作流(功能比较强大,但是开源维护缓慢,比较注重商业化) 以上三个是主流的工作流

  7. char 和 byte 区别

    byte 是字节数据类型 ,是有符号型的,占1 个字节:大小范围为-128-127 . char 是字符数据类型 ,是无符号型的,占2字节(Unicode码 ):大小范围 是0-65535 :char ...

  8. sql bypass waf fuzz python

    从freebuf copy过来的,先保存,有空再改 #encoding=utf-8 import requests url = "http://127.0.0.1/index.php?id= ...

  9. c# 调用Go 动态库

    [StructLayout(LayoutKind.Sequential)] public struct GoMem { public IntPtr data; public UInt64 len; p ...

  10. 如何在FL Studio中使用自动剪辑(上)

    一.什么是FL Studio Automation FL Studio automation可以通过许多不同的方法实现.一种方法是使用自动化剪辑(automation clip).自动化剪辑(或包络线 ...