-
被两条下划线所包围的方法(魔法方法或魔法属性)
-
魔法方法是Python的一切
一 init()
构造方法(初始化方法)---构造器
二 new()
1. 在创建对象时init并不是第一个被调用的方法,而是new()
2. 作用:用于创建对象
3. 不建议修改new方法
new方法负责创建对象(在内存中开辟一块空间,并创建一个对象数据)
自省---(类或对象都有自己的魔法成员,可以通过魔法成员的修改反过来影响类或对象的性质)
创建对象时的参数,先传递给new方法,进一步传递给构造方法
规律:
1. 给原有的功能做修改
2. 覆盖父类中的同名方法
3. 修改
4. 重新调用父类中的方法
三 del()
析构方法---析构器
当一个对象在消亡的时候,自动调用__del__
1. __del__和del语句无关
垃圾回收机制:
1. 如果一个对象没有任何引用,则会被视为垃圾,通过垃圾回收器回收掉
2. 对象一旦被视为垃圾,并不会马上消亡,而是被存储到垃圾缓存中
3. 如果python在对象消亡前,需要被创建,则不会创建新的对象,而是从缓存中将已经置位垃圾的对 象重新使用
4. 不建议重复删除并创建同一个类型的对象
2. 如果对象的引用被删除,不会触发del方法,只有当对象消亡时才会触发del方法
四 运算相关魔法方法
数据和对象不一样 1是数据,只能用于数学运算 int(1)是对象,对象间运算
1. + 触发对象的__add__()
2. a+b 调用形式:
a.__add__(b)
class MyInt(int):
def __add__(self, other):
print('this is add method')
# return int.__add__(self,other)
# return 10000
# print('self:%s'%self)
# print('other:%s'%other)
return int(self)+int(other) # 避免无限递归
a=MyInt(100)
b=MyInt(200)
print(a+b) # 加好前后的值的位置和add方法有关---
五 返运算
1. 更改方法调用的主动性
主动性:运算符被解析成方法调用的形式,被调用的对象拥有主动的
class MyInt(int):
def __add__(self, other):
print('this is add method')
# return int.__add__(self,other)
# return 10000
# print('self:%s'%self)
# print('other:%s'%other)
return int(self)+int(other)
def __radd__(self, other):
print('this is radd')
return int.__radd__(self,other)
a=MyInt(100)
b=MyInt(200)
# print(a+b)
# print(b+a)
# print(a+1) # a.__add__(1)
print(1+a) #
六 补充
add:+
sub:-
mul:*
truediv:/
floordiv://
mod:%
pow:**
lshift:<<
rshift:>>
and:&
xor:^
or:|
七 和属性相关的魔法方
1. __getattr__(self,name)
当访问一个属性,该属性不存在时,自动调用该方法
2. __getattribute__(self,name)
只要访问属性,自动调用该方法
3. __setattr__(self,name,value)
设置属性时,会自动调用该方法
4. __delattr__(self,name)
删除属性时,会自动调用该方法
class A(object):
age=18
def __init__(self):
self.hehe=100
def __getattribute__(self, item):
print('this is getattribute')
return super().__getattribute__(item)
# return '您想找的属性存在,但就不告诉你'
def __getattr__(self, item):
print('this is getattr')
return '该属性不存在'
def __setattr__(self, key, value):
print('this is setattr')
super().__setattr__(key,value)
def __delattr__(self, item):
print('this is delattr')
# super().__delattr__(item)
# del self.__dict__[item]
a=A()
# print(a.age)
# print(a.hehe)
# print(a.age)
# a.age=20
# print(a.age)
del a.hehe
# print(a.hehe)
八 描述符
描述符:descriptor --- 是Python2.2版本引入的 是Python特有的
1. 是一个类实现了__get__(),__set__(),__delete__()三个方法中至少一个方法的类,该类则称之为描 述符(描述符类)
2. 作用:
更加真实的将一个对象模拟成一个属性
3. 使用:
描述符的使用,至少需要两个类,通过描述符类创建的实例对象,作为另一个类的类属性
另一个类:拥有者类owner
描述符类:slave类(佣人类)---描述符
4. 方法:
1. __get__(self,instance,owner)
拥有者类访问自己的属性时,自动调用描述符类的get方法
2. __set__(self,instance,value)
拥有者类设置自己的属性时,自动调用描述符类的set方法
3. __delete__(self,instance)
拥有者类删除自己的属性时,自动调用描述符类的delete方法
self:指代当前对象(self一定是描述符对象)
instance:拥有者的实例对象
owner:拥有者的类对象
class A:
def __init__(self,hehe):
self.hehe=hehe
def __get__(self,instance,owner):
print('this is get method')
return self.hehe
def __set__(self,instance,value):
print('this is set method')
self.hehe=value
def __delete__(self, instance):
print('this is delete method')
del self.hehe
class B:
age=A(18)
b=B()
print(b.age)
b.age=20
print(b.age)
九 描述符的作用
1. 代码书写更加优雅
2. 提高代码的可重用性
3. 更加真实的将一个对象模拟成属性
class Score:
def __get__(self,instance,owner):
return self.score
def __set__(self,instance,value):
if 100>=value>=0:
self.score=value
else: print('输入有误')
class CheckScore:
score=Score()
def __init__(self,score):
self.score=score
def check(self):
if self.score>=60:
return '及格'
else:
return '不及格'
a=CheckScore(30)
a.score=80
print(a.check())
补充 :
property是一个描述符,底层实现如下:
class MyProperty:
def __init__(self,fget=None,fset=None,fdel=None,doc=None):
self.fget=fget
self.fset=fset
self.fdel=fdel
def __get__(self, instance, owner):
return self.fget(instance)
def __set__(self, instance, value):
self.fset(instance,value)
def __delete__(self, instance):
self.fdel(instance)
class A:
def __init__(self,age):
self.__age=age
def setAge(self,newAge):
self.__age=newAge
def getAge(self):
return self.__age
def delAge(self):
del self.__age
x=MyProperty(getAge,setAge,delAge)
a=A(18)
print(a.x)
a.x=20
print(a.x)
del a.x
print(a.x)
十 定制序列
1. 协议:protocols --- 接口(标准)
2. 定制序列协议:
1. 不可变类型协议
__len__()
__getitem__()
2. 可变类型协议
__len__()
__getitem__()
__setitem__()
__delitem__()
# class MyList: # 不可变序列
# def __init__(self,*args):
# self.l=[i for i in args]
#
# def __len__(self):
# return len(self.l)
#
# def __getitem__(self, item):
# return self.l[item]
#
# l=MyList(1,2,3,4,5)
# print(len(l))
# print(l[3])
class MyList: # 不可变序列
def __init__(self,*args):
self.l=[i for i in args]
def __len__(self):
return len(self.l)
def __getitem__(self, item): # item:下标
return self.l[item]
def __setitem__(self, key, value): # key:下标 value:值
self.l[key]=value
def __delitem__(self, key):
del self.l[key]
l=MyList(1,2,3,4,5)
print(len(l))
print(l[3])
l[0]=100
print(l.l)
十一 迭代器
可迭代对象中包含迭代器
1. 迭代器是一个特殊的可迭代对象
2. 迭代器是自己的迭代器
3. 任何实现了__iter__ 和__next__方法的对象
# 斐波那契数列
# result=int(input('请输入想要查询的项数'))
#
# def fun(n):
# count = 0
# a, b = 0, 1
# while count < n:
# count += 1
# print(a)
# a, b = b, a + b
# fun(result)
class Fib:
def __init__(self):
self.a,self.b=0,1
def __iter__(self):
return self
def __next__(self):
self.a,self.b=self.b,self.a+self.b
return self.a
f=Fib()
for i in range(12):
# print(next(f))
print(f.__next__())
补充
1. __str__
使用print函数打印对象时,会自动调用该方法
2. __repr__
在交互式界面直接显示对象时,会自动调用该方法