Python_魔法方法

1)构造和析构

        (1) 为什么使用__init__()

'''需要初始化对象时就需要重写__init__()方法'''
>>> class Rectangle:
	'''定义一个矩形类,
	   需要长和宽两个参数,
	   拥有计算周长和面积两个方法。
	   所以我们需要对象在初始化的时候拥有长宽两个参数,
	   因此需要用__init__()方法'''
	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
>>> class A:
	def __init__(self):
		return 'a'


'''__init__()方法的返回值一定是None,不能是其他'''	
>>> a = A()
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    a = A()
TypeError: __init__() should return None, not 'str'

        (2) __new__(cls[,...])

        事实上,__new__()才是在一个对象实例化的时候调用的第一个方法。它与其他魔法方法不同,它的第一个参数不是self而是这个类(cls),而其他的参数会直接传递给__init__()方法。                    __new__()方法需要返回一个实例对象,通常是cls这个类实例化的对象,当然也可以返回其他对象。                                                                                                                                                    __new__()方法平时很少去重写它,一般让Python用默认的方案执行就可以了。但是有一种情况需要重写这个魔法方法,就是当继承一个不可变的类型的时候,它的特性就显得尤为重要了。

(没搞明白)

>>> class CapStr(str):
	def __new__(cls, string):
		string = string.upper()
		return str.__new__(cls, string)

	
>>> a = CapStr('I love chill moon')
>>> a
'I LOVE CHILL MOON'

        (3) __del__(self)

        如果说__init__()和__new__()方法是对象的构造器的话,那么Python也提供了一个析构器,称为__del__()方法。当对象将要被销毁的时候,这个方法就会被调用。但一定要注意的是,并非del x就相当于自动调用x.__del__(),__del__()方法是当垃圾回收机制回收这个对象的时候调用的。

>>> class C:
	def __init__(self):
		print('我是__init__()方法,我被调用了')
	def __del__(self):
		print('我是__del__()方法,我被调用了')

		
>>> c1 = C()
我是__init__()方法,我被调用了
>>> c2 = c1
>>> c3 = c2
>>> del c1
>>> del c2
>>> del c3
我是__del__()方法,我被调用了
>>> b1 = C()
我是__init__()方法,我被调用了
>>> b2 = b1
>>> a = C()
我是__init__()方法,我被调用了
>>> del a
我是__del__()方法,我被调用了
>>> del b1
>>> del b2
我是__del__()方法,我被调用了

'''猜测:一个实例对象及其衍生出来的(即不是直接由类创造的)
被删干净了才会调用__del__()方法'''

2)算术运算

        工厂函数:Python2.2以后对类和类型进行了统一,做法就是将int()、float()、str()、list()、tuple()这些BIF转换为工厂函数:

>>> type(len)
<class 'builtin_function_or_method'> # 普通BIF
>>> type(int)
<class 'type'> # 工厂函数
>>> type(dir)
<class 'builtin_function_or_method'>
>>> type(list)
<class 'type'>
# <class 'type'>其实就是一个类
>>> class A:
	pass

>>> type(A)
<class 'type'> # 类对象
'''所谓工厂函数,其实就是一个类对象。调用它们的时候,
事实上就是创建一个相应的实例对象'''
>>> a = int('123')
>>> b = int('456')
>>> a + b
579
'''对象是可以进行计算的。当在求a + b等于多少的时候,
事实上Python就是将两个对象进行相加操作。'''

        (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

# 也可以自己写代码,不通过调用Python默认的方案
>>> class Try_int(int):
	def __add__(self, other):
		return self + other
	def __sub__(self, other):
		return self - other

>>> a = Try_int(1)
>>> b = Try_int(3)
>>> a + b
Traceback (most recent call last):
  File "<pyshell#166>", line 1, in <module>
    a + b
  File "<pyshell#163>", line 3, in __add__
    return self + other
  File "<pyshell#163>", line 3, in __add__
    return self + other
  File "<pyshell#163>", line 3, in __add__
    return self + other
  [Previous line repeated 327 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object
'''上面出现了无限递归,因为 return self+other 相当于返回对象本身加另一个对象,
又自动触发调用__add__()方法,就形成了无限递归'''

# 下面这样写就不会触发无限递归了
>>> class New_int(int):
	def __add__(self, other):
		return int(self) + int(other)
	def __sub__(self, other):
		return int(self) - int(other)

>>> a = New_int(1)
>>> b = New_int(2)
>>> a + b
3
>>> a - b
-1

'''有关算术运算的魔法方法,意思是当对象进行了相关的算术运算,
自然而然就会自动触发对应的魔法方法'''
>>> class int(int):
	def __add__(self, other):
		return int.__sub__(self, other)
	
>>> a = int('5')
>>> b = int('3')
>>> a + b
2



        (2)反运算

# 以下方法均为 当左操作数不支持相应的操作时被调用
__radd__(self, other) # 定义加法的行为:+
__rsub__(self, other) # 定义减法的行为:-
__rmul__(self, other) # 定义乘法的行为:*
__rtruediv__(self, other) # 定义真除法的行为:/
__rfloordiv__(self, other) # 定义整数除法的行为://
__rmod__(self, other) # 定义取模算法的行为:%
__rdivmod__(self, other) # 定义当被divmod()调用时的行为
__rpow__(self, other) # 定义当被power()调用调用或**运算时的行为
__rlshift__(self, other) # 定义按位左移位的行为:<<
__rrshift__(self, other) # 定义按位右移位的行为:>>
__rand__(self, other) # 定义按位与操作的行为:&
__rxor__(self, other) # 定义按位异或操作的行为:^
__ror__(self, other) # 定义按位或操作的行为:|

        什么是反运算:a + b这里a是加数, b是被加数,是a主动。如果a对象的__add__()方法没有实现或者不支持相应的操作,那么Python就会自动调用b的__radd__()方法。

>>> class Nint(int):
	def __radd__(self, other):
		return int.__sub__(other, self)
	
>>> a = Nint(5)
>>> b = Nint(3)
>>> a + b
8
# 由于a对象默认有__add__()方法,所以b的__radd__()没有执行
# 于是就有了:
>>> 1 + b
-2
# 注意:对于a+b来说,b的__radd__(self, other)中的self是b对象,other是a对象
# 所以不能这么写:
>>> class Nint(int):
	def __rsub__(self, other):
		return int.__sub__(self, other)
	
>>> a = Nint(5)
>>> 3 - a
2
'''因此,对于注重操作数顺序的运算符(如减法、除法、移位),
在重写反运算魔法方法的时候,就一定要注意顺序问题了'''

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值