python(魔术方法)

魔法方法

https://fishc.com.cn/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403)
1.构造和析构

  1. new 是在一个对象实例化的时候所调用的第一个方法
  2. 它的第一个参数是这个类,其他的参数是用来直接传递给 init 方法
  3. new 决定是否要使用该 init 方法,因为 new 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 new 没有返回实例对象,则 init 不会被调用
    定义:魔法方法总是被双下划线包围
    特征:总能在适当的时候被自动调用
    1.init(self)
    构造方法,实例化对象时,会首先被调用
    Eg:class CC:
    Def init (self, x, y):
    Self.x = x
    Self.y = y

Self.x:类实例化对象的局部变量
X:实例化对象时传的参数
注意:new有返回值,构造函数(init)没有返回值
2.new(cls[,…])
含义:对象实例化时调用的方法,和其他魔术方法不同,第一个参数是class,在init()之前被调用,返回class类的实例对象(一般情况下很少去重写new方法,当继承一个不可变的类时,又需要进行修改的时候才会重写)
Eg:
class String1(str):
def new(cls, string):
string = string.upper()
return str.new(cls, string)
a = String1(“hello python”)
print(a)
实行结果:
HELLO PYTHON
3.del(self) 析构器(垃圾回收机制)
Del x != x.del() 是不相等的
Eg:
class String1(str):
def new(cls, string):
print(“new”)
string = string.upper()
return str.new(cls, string)
def init(self,x):
print(“init”)
def del(self):
print(“del”)
a = String1(“hello python”)
b = a
c = a
d = a
del c
del b
del d
print(a)
del a
实行结果:
new
init
HELLO PYTHON
del
结论|:类中魔法方法调用顺序:new->init->del
在创建实例化对象a的同时,将a的引用给类b,c,d,使用del删除这些引用时候,不会调用类对象中的__del__(self)函数,在最后程序结束时才会调用类对象的__del__(self)函数
Eg:
class String1(str):
def new(cls, string):
print(“new”)
string = string.upper()
return str.new(cls, string)
def init(self,x):
print(“init”)
def del(self):
print(“del”)
a = String1(“hello python”)
b = a
c = a
d = a
del c
del b
del d

print(a)

del a #真正删除实例化对象a

print(a)

new
init
del
2.算术运算:魔法方法提供了自定义对象的数值处理,通过对魔法方法的重写,自定义任何对象间的算术运算
a = int(“123”)
b = int(“456”)
解析:类对象int通过参数“123”,”465”实例化一个对象,赋值给a,b
a + b = 579(对象还可以进行算术运算)
1.算术运算
class Add(int):
def add(self, other): # 重写类int中的魔法方法add
return int.add(self, other) # 返回类int中的魔法方法add
def sub(self, other): # # 重写类int中的魔法方法sub
return int.sub(self, other) # 返回类int中的魔法方法sub
a = Add(5)
b = Add(9)
print(“a+b:”, a + b)
实行结果:
a+b: 14
虽然重写了int类中的魔法方法,但是还是返回int类中的魔法方法add/sub方法
class Add_tyr1(int):
def add(self, other): # 重写类int中的魔法方法add
return int.sub(self, other) # 返回类int中的魔法方法sub
def sub(self, other): # # 重写类int中的魔法方法sub
return int.add(self, other) # 返回类int中的魔法方法add
a = Add_tyr1(5)
b = Add_tyr1(9)
print(“a+b:”, a + b)
print(“a-b:”, a - b)
实行结果:
a+b: -4
a-b: 14
重写了类int中的魔法方法add/sub, 返回类int中的魔法方法sub/add方法
注意:不要写成无限递归
class Add_tyr1(int):
def add(self, other): # 重写类int中的魔法方法add
return self + other #
a = Add_tyr1(5)
b = Add_tyr1(9)
print(“a+b:”, a + b) # 这里a和b对象的加法在类杜对象中会被识别,调用add函数,return self + other 继续被识别调用add函数,无限递归
正确方法
class Add_tyr1(int):
def add(self, other): # 重写类int中的魔法方法add
return int(self) + int(other) # 把a,b对象进行转型
a = Add_tyr1(5)
b = Add_tyr1(9)
print(“a+b:”, a + b) # 这里a+b 这里有“+”调用a对象的add方法,调用add函数

类型
len(self)
repr(self)
str(self) 如果要把一个类的实例变成 str,就需要实现特殊方法__str__(),Python 定义了__str__()和__repr__()两种方法,
str()用于显示给用户,而__repr__()用于显示给开发人员。
bytes(self)
hash(self)
bool(self)
format(self, format_spec)
Eg
1.repr和str
class Person(object):
def init(self, name, gender):
self.name = name
self.gender = gender
def str(self):
return ‘(Person: %s, %s)’ % (self.name, self.gender)
repr = str
class Student(Person):
def init(self, name, gender, score):
super().init(name, gender)
# Person.init(self, name, gender)
self.score = score
def str(self):
return ‘(Person: %s, %s, %s)’ % (self.name, self.gender,self.score)
repr = str
s = Student(“张三”, “98”, “00”)
print(s)
(Person: 张三, 98, 00)
divmod(self,other)

反运算
class Radd(int):
def radd(self, other): # 对radd反函数运算函数进行重写
return int.pow(self, other) # 返回self的other次方
a = Radd(“4”)
b = Radd(“2”)
print(a + b)
print(4 + b)

解析:
反运算:两个数的算术运算,先找第一个数的对象中的魔术方法,如果找不到,则找第二个数中的反运算函数。
运算流程:
当计算a+b时候,遇到“+”号,先找对象a的__Add()方法,a是int的对象则能找到,进行加法运算。
当计算4+b的时候,4不具备int对象的__Add
()方法,会调用b对象中的魔法方法的反函数__radd(self, other)__方法,此时,radd函数的参数中self是b对象,other则是a。
属性访问

class A:
def getattribute(self, item):
print(“getattribute”) # 获取属性的时候就会调用(先调用这个函数),如果属性不存在则调用__getattr__方法
return super().getattribute(item)
def getattr(self, item): # 获取一个不存在的属性的时候就会调用
print(“getattr”)
def setattr(self, key, value): # 当一个属性被设置的时会调用
print(“setattr”)
super().setattr(key, value)
def delattr(self, item): # 当一个属性被删除的时会调用
print(“delattr”)
super().delattr(item)
a = A()
print(a.x)
a.x = 1
print(a.x)
实行结果:
getattribute
getattr
None
setattr
getattribute
1
解析:当print(a.x)实行时,会先调用getattribute,属性不存咋,在调用getattr方法,返回值为None,a.x = 1实行时,会调用setattr方法。print(a.x)调用时候,调用getattribute,通过属性字典找到了,所以直接返回对应的数值,不会在去调用getattr方法

class A():
def init(self,weight = 0, height = 0):
self.weight = weight
self.height = height

def setattr(self, key, value):
if key == “s”:
self.weight = value
self.height = value
else:
# self.key = value 使用此种方法会无限递归循环,在init方法中,使用“=”赋值,会调用setattribute,属性不存在,则调用setattr,走到else,又使用“=”进行赋值,还会调用setattribute,属性不存在,调用setattr方法无限循环
# super().setattr(key,value) #方法1 调用父类的setattr方法
self.dict[key] = value #方法2 使用字典直接赋值
def getArea(self):
return self.weight * self.height
a = A(4,5)
print(a.getArea())
a.s = 10
print(a.weight)
print(a.height)
print(a.getArea())

解析:重写了魔术方法后,很容易进入死循环,另外,赋值的方法有三种,写明父类进行调用的方法没写,缺点是如果类继承有问题,则代码修改量增大

扫描二维码关注公众号,回复: 4272110 查看本文章

魔术方法汇总:
魔法方法 含义 测试
  基本的魔法方法  
new(cls[, …]) 1. new 是在一个对象实例化的时候所调用的第一个方法 maru
2. 它的第一个参数是这个类,其他的参数是用来直接传递给 init 方法
3. new 决定是否要使用该 init 方法,因为 new 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 new 没有返回实例对象,则 init 不会被调用
4. new 主要是用于继承一个不可变的类型比如一个 tuple 或者 string
init(self[, …]) 构造器,当一个实例被创建的时候调用的初始化方法 maru
del(self) 析构器,当一个实例被销毁的时候调用的方法 maru
call(self[, args…]) 允许一个类的实例像函数一样被调用:x(a, b) 调用 x.call(a, b) maru
len(self) 定义当被 len() 调用时的行为 maru
repr(self) 定义当被 repr() 调用时的行为
补充:repr(实例化对像) 时会调用
注意:__str__方法的返回值必须是字符串 maru
str(self) 定义当被 str() 调用时的行为
补充:print(实例化对像) 时会调用
注意:1.str__方法的返回值必须是字符串
2.当一个类中,同时重写了repr和str 方法的时候,在print(实例化对像)的时候会调用str的方法,repr方法不会被调用
3.当类中只有一个(str或repr)的时候,两者一样,使用repr()会调用__str__方法,使用print()会调用__repr
maru
bytes(self) 定义当被 bytes() 调用时的行为  
hash(self) 定义当被 hash() 调用时的行为  
bool(self) 定义当被 bool() 调用时的行为,应该返回 True 或 False  
format(self, format_spec) 定义当被 format() 调用时的行为  
  有关属性  
getattr(self, name) 定义当用户试图获取一个不存在的属性时的行为,相当于等于号 maru
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) maru
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) 定义加法的行为:+ maru
sub(self, other) 定义减法的行为:- maru
mul(self, other) 定义乘法的行为:* maru
truediv(self, other) 定义真除法的行为:/  
floordiv(self, other) 定义整数除法的行为://  
mod(self, other) 定义取模算法的行为:%  
divmod(self, other) 定义当被 divmod() 调用时的行为定义当被divmod()调用时的行为,divmod(a,b) 返回a%b的余数  
pow(self, other[, modulo]) 定义当被 power() 调用或 ** 运算时的行为 maru
lshift(self, other) 定义按位左移位的行为:<<  
rshift(self, other) 定义按位右移位的行为:>>  
and(self, other) 定义按位与操作的行为:& maru
xor(self, other) 定义按位异或操作的行为:^  
or(self, other) 定义按位或操作的行为:| maru
  反运算  
radd(self, other) (与上方相同,当左操作数不支持相应的操作时被调用) maru
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) 定义赋值加法的行为:+= maru
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)时的行为

猜你喜欢

转载自blog.csdn.net/weixin_42970234/article/details/84350899