一、魔术方法
- 概念
在python中,所有以
__xxx__
格式的方法统称为“魔术方法” - 方法
- 初始化
__new__
__init__
__del__
- 属性控制
__getattr__
__setattr__
__getitem__
__setitem__
__getattribute__
- 数学运算
__add__
__sub__
__mul__
__div__
__lt__
__gt__
__le__
__ge__
__eq__
__ne__
- 容器相关
__len__
__iter__
__contains__
- 描述对象
__get__
__set__
__delete__
- 可执行
__call__
- 槽
__slots__
- 上下文管理with
__enter__
__exit__
- 初始化
二、属性监听
__getattr__
拦截点号运算。当对未定义的属性名称和实例进行点号运算时,就会用属性名作为字符串调用这个方法。如果继承树可以找到该属性,则不调用此方法
__setattr__
会拦截所有属性的的赋值语句。如果定义了这个方法,self.arrt = value
就会变成self.__setattr__("attr", value)
。这个需要注意,当在__setattr__
方法内对属性进行赋值时,不可使用self.attr = value
,因为他会再次调用self.__setattr__("attr", value)
,则会形成无穷递归循环,最后导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name'] = value
示例
代码语言:javascript复制class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "%s is a good man!He is %d years old"%(self.name, self.age)
# 使用点语法访问不存在的属性时被自动调用
# 作用:调用某些不存在的属性时不想报错,想返回一个默认值
def __getattr__(self, item):
print("__getattr__")
return "%s属性不存在"%item
# 当调用点语法设置属性值时被自动调用
def __setattr__(self, key, value):
# print("----------setattr", key, value)
if key == "age":
if value < 16 or value > 20:
self.__dict__[key] = 18
else:
self.__dict__[key] = value
# 当调[属性名]语法设置属性值时被自动调用
# def __setitem__(self, key, value):
# print("----------setitem", key, value)
#使用点语法获取属性值时被自动调用
#避免使用该方法
# def __getattribute__(self, item):
# return super().__getattribute__(item)
per = Person("sunck", 18)
print("---------------------------------")
# per["age"] = 9
# per.age = 16
print(per.age)
# print(per.money)
三、运算符重载
本质为重写,可以修改运算符的作用
代码语言:javascript复制num1 = 1
num2 = 2
num3 = num1 num2
print(num3)
str1 = "sunck"
str2 = "good"
# 对加法运算符进行了重载(类似于重写,把原有的内容进行重新赋予新的功能)
str3 = str1 str2
print(str3)
实现重载
代码语言:javascript复制class Person(object):
def __init__(self, money):
self.money = money
# 对加号进行重载
# per1 per2 ==> per1.__add__(per2)
def __add__(self, other):
other.money = self.money
self.money = 0
return other.money
# per1 - per2 ==> per1.__sub__(per2)
def __sub__(self, other):
pass
# per1 * per2 == > per1.__mul__(per2)
def __mul__(self, other):
pass
# per1 / per2 == > per1.__truediv__(per2)
def __truediv__(self, other):
pass
# len(per) ==> per.__len__()
def __len__(self):
pass
# per1 < per2 == > per1.__lt__(per2)
def __lt__(self, other):
pass
per1 = Person(100)
per2 = Person(200)
print(per1 per2)
print(per1.money, per2.money)
print(len(per1))