今天开始学习魔法方法和特性。
魔法方法
魔法(特殊)方法是开头结尾都是两个下划线的名称。
构造函数
构造函数会在创建后自动调用,以init命名:
class foo:
def __init__(self,val=6):
self.exp=val
bar=foo()
print(bar.exp)
bar1=foo(7)
print(bar1.exp)
在继承中,构造函数会被覆盖,我们可以这样解决覆盖问题:
class foo:
def __init__(self,val=6):
self.exp=val
class foo2(foo):
def __init__(self):
foo.__init__(self)
self.vall=1
我们也可以使用函数super:
class foo:
def __init__(self,val=6):
self.exp=val
class foo2(foo):
def __init__(self):
super().__init__()
self.vall=1
基本的映射和序列协议
函数 | 作用 |
---|---|
__len__ (self) |
返回集合包含的项数 |
__getitem__ (self,key) |
返回与指定键关联的值 |
__setitem__ (self,key,value) |
储存键-值对 |
__delitem__ (self,key) |
删除键-值对 |
要了解更复杂的抽象基类,请阅读模块collections的文档。
我们可以实现一个无穷序列:
def check(key): #判断key是否可接受
if not isinstance(key,int): raise TypeError
if(key<0):raise IndexError
class seq:
def __init__(self,start=0,step=1):#初始化起点和步长
self.start=start
self.step=step
self.changed={}
def __getitem__(self,key):#如果被修改就返回修改后的,没有则计算值
check(key)
try:return self.changed[key]
except KeyError:
return self.start+key*self.step
def __setitem__(self,key,value):#赋新值
check(key)
self.changed[key]=value
s=seq(1,2)
print(s[2])
s[2]=100
print(s[2])
此类没有__len__
,因为长度是无穷的。也不能使用del删除,因为没写delitem。
从list、dict和str继承
模块collections提供了抽象和具体的基类,我们也可以继承内置类型。
特性
我们可以用property来动态调整:
class seq:
def __init__(self):
self.start=0
self.step=0
def set(self,size):
self.start,self.step=size
def get(self):
return self.start,self.step
size=property(get,set)
s=seq()
s.start=1
s.step=2
print(s.size)
s.size=150,200
print(s.size)
关于装饰器,由于不常用,此处不作讨论。
我们可以拦截访问企图并自动调用类中的魔法方法:
函数 | 作用 |
---|---|
__getattribute__ (self,name) |
访问时自动调用 |
__getattr__ (self,name) |
属性被访问而对象没有这样的属性时自动调用 |
__setattr__ (self,name,value) |
试图给属性赋值时自动调用 |
__delattr__ (self,name) |
试图删除属性时自动调用 |
上面的无穷序列可以使用此法上面的示例而不用property。