python入门学习笔记——天池task3(day3)——魔法方法
魔法方法
在python中,有一些内置好的特定的方法,这些方法在进行特定的操作时会自动被调用,称之为魔法方法,魔法方法总是被双下划线包围,例如__init__
。
魔法方法的“魔力”体现在它们总能够在适当的时候被自动调用。
魔法方法的第一个参数应为cls(类方法) 或者self(实例方法)。
cls
:代表一个类的名称self
:代表一个实例对象的名称
基本的魔法方法
__ init __:
__init__(self[, ...])
构造器,当一个实例被创建的时候调用的初始化方法
【例子】
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(4, 5)
print(rect.getPeri()) # 18
print(rect.getArea()) # 20
#输出为:
#18
#20
__ new __
-
__ new__(cls[,* argv])
-
__ new__
是在一个对象实例化的时候所调用的第一个方法,它的第一个参数是这个类,其他的参数是用来直接传递给__ init__
方法 -
__ new__
决定是否要使用该__ init__
方法,因为__ new__
可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果__ new__
没有返回实例对象,则__ init__
不会被调用 -
__ new__
主要是用于继承一个不可变的类型比如一个 tuple 或者 string
【例子】
class myMethod(str):
def __new__(cls,string):
string=string.upper()
return str.__new__(cls,string)
X=myMethod('studying')
print(X)
#输出为:
#STUDYING
下面再来一个结合__ init__
和__ new__
两个魔法方法的例子:
class A(object):
pass
class B(A):
def __init__(self):
print('__init__被调用')
def __new__(cls):
print('__new__被调用')
print(id(cls))
return object.__new__(A)
#注意此处采用了参数A而不是cls,__new__没有正确返回当前类cls的实例
b=B()
print(b)
print(type(b)) #类型所继承的基类
print(id(A))
print(id(B))
#输出为:
'''
__new__被调用
2398669464152
<__main__.A object at 0x0000022E7DFF5D88>
<class '__main__.A'>
2398669465096
2398669464152
'''
从运行结果可以看出,__ new__
中的参数cls和B的id是相同的,表明__ new__
中默认的参数cls就是B类本身,而在return时,并没有正确返回当前类cls的实例,而是返回了其父类A的实例,因此__ init__
这一魔法方法并没有被调用,此时__ new__
虽然是写在B类中的,但其创建并返回的是一个A类的实例对象。
现在将return中的参数A变为cls,再来看一下运行结果:
class A(object):
pass
class B(A):
def __init__(self):
print('__init__被调用')
def __new__(cls):
print('__new__被调用')
print(id(cls))
return object.__new__(cls)
#注意此处采用了参数A而不是cls,__new__没有正确返回当前类cls的实例
b=B()
print(b)
print(type(b)) #类型所继承的基类
print(id(A))
print(id(B))
#输出为:
'''
__new__被调用
2398669461320
__init__被调用
<__main__.B object at 0x0000022E7DFEFE88>
<class '__main__.B'>
2398669468872
2398669461320
'''
可以看出,当__ new__
正确返回其当前类cls的实例对象时,__ init__
被调用了,此时创建并返回的是一个B类的实例对象。
__ class__:
获得已知对象的类 ( 对象.__ class__)。
基础格式如下:
class My:
pass
a=A()
print(a.__class__)
#输出为:
#<class '__main__.A'>
__ class__
在下面这种情况中是有用的:即当一个类中的某个成员变量是所有该类的对象的公共变量时.
下面看一个例子:
class My:
count=0
def addcount(self):
self.__class__.count +=1
a=My()
a.addcount()
print(a.count)
print('===='*10)
b=My()
b.addcount()
print(b.count)
#输出为:
'''
1
========================================
2
'''
从运行结果可以看出,虽然a和b是两个不同的My类的实例对象,但采用了__ class__
之后,分别调用两个对象的addcount
方法之后,获取到的对象的count属性却是在不断累加的,此时self.__ class__ .count
不再是单纯的某个对象私有的属性,而是类的所有实例对象的共有属性,它相当于self.A.count。若将self.__ class__ .count += 1
变为self.count += 1,此时__ class__
的效果就十分明显了。
class My:
count=0
def addcount(self):
self.count +=1
a=My()
a.addcount()
print(a.count)
print('===='*10)
b=My()
b.addcount()
print(b.count)
#输出为:
'''
1
========================================
1
'''
__ str__:
在将对象转换成字符串 str(对象) 测试的时候,打印对象的信息,__ str__
方法必须要return一个字符串类型的返回值,作为对实例对象的字符串描述,__ str__
实际上是被print函数默认调用的,当要print(实例对象)时,默认调用__ str__
方法,将其字符串描述返回。如果不是要用str()函数转换。当你打印一个类的时候,那么print首先调用的就是类里面的定义的__ str__
。
class My():
def __init__(self,name):
self.name=name
def __str__(self):
return('我是My类的实例对象my,我的名字叫%s'%self.name)
my=My('张山')
print(My)
print(my)
#输出为:
'''
<class '__main__.My'>
我是My类的实例对象my,我的名字叫张山
'''
类的专有方法
算术运算符
类型工厂函数,指的是“不通过类而是通过函数来创建对象”。
__add__(self, other)
定义加法的行为:+
__sub__(self, other)
定义减法的行为:-
-
__mul__(self, other)
定义乘法的行为:*
__truediv__(self, other)
定义真除法的行为:/
__floordiv__(self, other)
定义整数除法的行为://
__mod__(self, other)
定义取模算法的行为:%
__divmod__(self, other)
定义当被divmod()
调用时的行为divmod(a, b)
把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)
。-
__pow__(self, other[, module])
定义当被power()
调用或**
运算时的行为
__lshift__(self, other)
定义按位左移位的行为:<<
__rshift__(self, other)
定义按位右移位的行为:>>
__and__(self, other)
定义按位与操作的行为:&
__xor__(self, other)
定义按位异或操作的行为:^
__or__(self, other)
定义按位或操作的行为:|
反算术运算符
反运算魔方方法,与算术运算符保持一一对应,不同之处就是反运算的魔法方法多了一个“r”。当文件左操作不支持相应的操作时被调用。
__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[, module])
定义当被 power() 调用或**
运算时的行为__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)
定义赋值按位或操作的行为:|=
一元运算符
__neg__(self)
定义正号的行为:+x
__pos__(self)
定义负号的行为:-x
__abs__(self)
定义当被abs()
调用时的行为__invert__(self)
定义按位求反的行为:~x
属性访问
__getattr__(self, name)
: 定义当用户试图获取一个不存在的属性时的行为。__getattribute__(self, name)
:定义当该类的属性被访问时的行为(先调用该方法,查看是否存在该属性,若不存在,接着去调用__getattr__
)。__setattr__(self, name, value)
:定义当一个属性被设置时的行为。__delattr__(self, name)
:定义当一个属性被删除时的行为。
描述符
描述符就是将某种特殊类型的类的实例指派给另一个类的属性。
__get__(self, instance, owner)
用于访问属性,它返回属性的值。__set__(self, instance, value)
将在属性分配操作中调用,不返回任何内容。__del__(self, instance)
控制删除操作,不返回任何内容。