Python--25 魔法方法:构造和析构 魔法方法总结

魔法方法总是被双下划线包围,例如__init__

魔法方法是面向对象的Python的一切,如果你不知道魔法方法,说明你还没有意识到面向对象Python的强大

魔法方法的‘魔力’体现在他们总能够在适当的时候被调用

1.__init__(self[,...])  返回一个None对象

  类在实例化的时候默认会调用的函数

>>> class Rectangle:
...     def __init__(self,x,y):
...             self.x = x
...             self.y = y
...     def getPeri(self):
...             return (self.x + self.y) * 2
...     def getArea(self):
...             return self.x * self.y
... 
>>> rect = Rectangle(3,4)
>>> rect.getPeri()
14
>>> rect.getArea()
12

2.__new__(cls[,...])对象实例化第一次调用的方法,返回类的实例对象

  继承一个不可变类型的时候,又需要进行修改的时候,那么这个特性就特别重要

>>> class CapStr(str):
...     def __new__(cls,string):
...             string = string.upper()
...             return str.__new__(cls,string)
... 
>>> a = CapStr('I love you')
>>> a
'I LOVE YOU'

3.__del__(self) 析构器

  垃圾回收机制,当这个数据没有任何变量与之相关联的时候

>>> class C:
...     def __init__(self):
...             print('我是init方法,我被执行了')
...     def __new__(self):
...             print('我是new方法,我被执行了')
...     def __del__(self):
...             print('我是__del__方法,我被执行了')
... 
>>> 
>>> class C: 
...     def __init__(self):
...             print('我是__init__方法,我被执行了')
...     def __del__(self):
...             print('我是__del__方法,我被执行了')
... 
>>> c1 = C()
我是__init__方法,我被执行了
>>> c2 = c1
>>> c3 = c1
>>> del c3
>>> del c2
>>> del c1
我是__del__方法,我被执行了

算术运算

Python将两个int对象进行向相加的操作

Python的魔法方法还提供了自定义数值的处理,通过对魔法方法的重写 ,进行对象间的算术运算

>>> type(len)
<class 'builtin_function_or_method'>
>>> type(dir)
<class 'builtin_function_or_method'>
>>> type(int)
<class 'type'>
>>> type(list)
<class 'type'>
>>> class C:
...     pass
... 
>>> type(C)
<class 'type'>
>>> a = int('123')
>>> b = int('456')
>>> a + b
579

算术运算1

方法名 方法说明
__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) 定义按位或操作的行为:|
>>> class New_int(int):
...     def __add__(self,other):
...             return int.__sub__(self,other)
...     def __sub__(self,other):
...             return int.__add__(self,other)
... 
>>> a = New_int(3)
>>> b = New_int(5)
>>> a + b
-2
>>> a - b
8

注意:

>>> class Try_int(int):
...     def __add__(self, other):
...             return self + other
...     def __sub__(self, other):
...             return self + other
... 
>>> a = Try_int(3)
>>> b = Try_int(5)
>>> a + b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __add__
  File "<stdin>", line 3, in __add__
  File "<stdin>", line 3, in __add__
  [Previous line repeated 329 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object

WHY?

   a + b   -> return self + other = a + b

修改:

>>> class Try_int(int):
...     def __add__(self, other):
...             return int(a) + int(b)
... 
>>> a =Try_int(3)
>>> b = Try_int(5)
>>> a + b
8
>>> a = divmod(5,3)
>>> a 
(1, 2)

算术运算2

>>> class int(int):
...     def __add__(self, other):
...             return int.__sub__(self,other)
... 
>>> a = int('5')
>>> a
5
>>>  b = int('3')
>>> b = int('3')
>>> a + b
2

 

魔法方法 含义
基本的魔法方法
__new__(cls[, ...])

1.__new__是在一个对象实例化的时候所调用的第一个方法

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

3. __new__ 决定是否要使用 该 __init__ 方法,因 为 __new__ 可以 调 用其他 类 的构造
方法或者直接返回 别 的 实 例 对 象来作 为 本 类 的 实 例,如果 __new__ 没有返回 实 例 对
象, 则 __init__ 不会被 调 用
4. __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() 调 用 时 的行 为
有 关 属性
__getattr__(self, name) 定义当用 戶试图获 取一个不存在的属性 时 的行 为
__getattribute__(self, name) 定义当 该类 的属性被 访问时 的行 为
__setattr__(self, name, value) 定义当一个属性被 设 置 时 的行 为
__delattr__(self, name) 定义当一个属性被 删 除 时 的行 为
__dir__(self) 定义当 dir() 被 调 用 时 的行 为
__get__(self, instance, owner) 定义当描述符的 值 被取得 时 的行 为
__set__(self, instance, value) 定义当描述符的 值 被改 变时 的行 为
__delete__(self, instance) 定义当描述符的 值 被 删 除 时 的行 为
比 较 操作符
__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)

1. 当 对 象是被 应 用在切片表达式中 时,实现 整形强制 转换
2. 如果你定义了一个可能在切片 时 用到的定制的数 值 型,你 应该 定义 __index__
3. 如果 __index__ 被定义, 则 __int__ 也需要被定义,且返回相同的 值

上下文管理(with 语 句)
__enter__(self)

1. 定义当使用 with 语 句 时 的初始化行 为
2. __enter__ 的返回 值 被 with 语 句的目 标 或者 as 后的名字 绑 定

__exit__(self, exc_type, exc_value,traceback)

1. 定义当一个代 码块 被 执 行或者 终 止后上下文管理器 应该 做什么
2. 一般被用来 处 理异常,清除工作或者做一些代 码块执 行完 毕 之后的日常工作

容器 类 型  
__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 )时 的行 为

 a + b

 当 a 加法不支持的时候,python会自动选择b的加法 即加法反运算

 

>>> class Rint(int):
...     def __radd__(self,other):
...             return int.__sub__(self,other)
... 
>>> a = Rint(4)
>>> b = Rint(2)
>>> a + b
6
>>> 1 + b
1

 

注意: self,other位置

>>> class Rint(int):
...     def __rsub__(self,other):
...             return int.__sub__(other,self)
... 
>>> a = Rint(5)
>>> 3 - a
-2

 

posted @ 2017-09-12 20:33  110528844  阅读(204)  评论(0编辑  收藏  举报