第十一章.魔法方法
1. 构造和折构
- __init__(self[,…])
#一般需要对类初始化定义参数,就需要用到__init__
#对于定义一个类中的参数,在类的开头使用__init__
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
r = rectangle(3,4)
r.getArea() # >>> 12
r.getPeri() # >>> 14
-
__new__(cls[,…])
-
__del__(self)
当对象将被销毁时(python内设的垃圾回收机制启动时),这个方法会被调用。这个方法是解析器自动调用的,一般情况下不重写。
class C:
def __init__(self):
print("init")
def __del__(self):
print("del")
c1 = C() # >>> init
c2 = c1
c3 = c1
del c1
del c2 #当销毁掉最后一个对应C类的对象时,调用__del__内的方法
del c3 # >>> del
2. 算术运算
- 算数操作符
定义相关的算数操作符所做的操作
class a(int):
def __add__(self,other):
return int.__sub__(self,other) #将加法运算符的操作改成减法
def __sub__(self,other):
return int.__add__(self,other) #将减法运算符的操作改成加法
x = a(3)
y = a(4)
x + y # >>> -1
x - y # >>> 7
3 + y # >>> 7
[外链图片转存失败(img-w1SEUP9U-1569063914352)(pic/python_5.png ‘算数运算符的魔法方法’)]
- 反运算
反运算与算术运算符一一对应,只是在前面多了一个’r’
class Nint(int):
def __radd__(self,other):
return int.__sub__(self,other)
a = Nint(5)
b = Nint(3)
a + b # >>> 8
5 + b # >>> -3 此时b为self,5为other
- 简单定制
定制一个计数器
import time as t
class myTimer():
def __init__(self):
self.unit = ['年','月','日','小时','分钟','秒']
self.prompt = '未开始计数!'
self.lasted=[]
self.begin = 0
self.end = 0
def __str__(self):
return self.prompt
__repr__ = __str__
def __add__(self,other):
prompt = '总共运行了'
result = []
for index in range(6):
result.append(self.lasted[index] + other.lasted[index])
if result[index]:
prompt += (str(result[index]) + self.unit[index])
return prompt
#开始计时
def start(self):
self.begin = t.localtime()
self.prompt = '提示:请先调用stop()停止计时!'
print("计时开始")
#停止计时
def stop(self):
if not self.begin:
print("提示:请先调用start()进行计时!")
else:
self.end = t.localtime()
self._calc()
print("计时结束!")
#内部方法,计算运行时间
def _calc(self):
self.lasted = []
self.prompt = '总共运行了'
for index in range(6):
self.lasted.append(self.end[index] - self.begin[index])
if self.lasted[index]:
self.prompt += (str(self.lasted[index]) + self.unit[index])
#清零本次结果
self.begin = 0
self.end = 0
self.lasted=[]
- 属性访问
#当用户试图获取一个不存在的属性时的行为
__getattr__(self,name)
#当该类的属性被访问时的行为
__getattribute__(self,name)
#当一个属性被设置时的行为
__setattr__(self,name,value)
#当一个属性被删除时的行为
__delattr__(self,name)
- 描述符
描述符就是将某种特殊类型的类的实例指派给另一个类的属性。
class decriptor:
#上述特殊类指代至少引用一下三种魔法方法中的其中一种的类
def __get__(self,instance,owner): #用于访问属性,它返回属性的值
print("get..",self,instance,owner)
def __set__(self,instance,value): #将在属性分配操作中调用,不返回任何内容
print("set...",self,instance,value)
def __delete__(self,instance): #控制删除操作,不反悔任何内容
print("delete",self,instance)
class test:
x = decriptor() # decriptor就是x的描述符
t = test()
t.x # >>> get... <self == decriptor> , <instance == x> , <owner == test>
t.x = '6' # >>> set... <self == decriptor> , <instance == x> , <owner == 6>
del t.x # >>> delete... <self == decriptor> , <instance == x>
例子:定义一个温度类,并定义两个描述符类用于描述摄氏度和华氏度两个属性。要求两个属性会自动进行转换,即摄氏度与华氏度属性可自动转换(转换公式:摄氏度*1.8 + 32 = 华氏度。
class Celsius:
def __init__(self,value = 26.0): #初始化为26摄氏度
self.value = float(value)
def __get__(self,instance,owner):
return self.value
def __set__(self,instance,value):
self.value = float(value)
class Fahrenheit:
def __get__(self,instance,owner):
return instance.cel*1.8 +32
def __set__(self,instance,value):
instance.cel = (float(value) - 32) / 1.8
class temperature:
cel = Celsius()
fah = Fahrenheit()
temp = temperature()
temp.cel = 30
temp.fah # 86.0
temp.fah = 100
temp.cel #37.7777777777778
- 容器
#编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数
class CountList:
def __init__(self,*args):
self.values = [x for x in args]
self.count = {}.fromkeys(range(len(self.values)),0)
def __len__(self):
return len(self,values)
def __getitem__(self,key):
self.count.key +=1
return self.values[key]
c = CountList(1,2,3,4)
c[1] # >>> 3
c.count # >>> {1:0 , 2:1 , 3:0 , 4:0}
- 迭代器
string = "abcdefg"
i = iter(string)
next(i) # >>> a
next(i) # >>> b
j = iter(string)
while True:
try:
each = next(j)
except StopIteration:
break
print(each,end='') # >>> abcdefg
#迭代的魔法方法
class Fibs:
def __init__(self,n=100):
self.a = 0
self.b = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
self.a , self.b = self.b , self.a + self.b
if self.a > self.n:
raise StopIteration
return self.a
fibs = Fibs()
for i in fibs:
print(i) #将会打印出值为100以内的数列
- 生成器
协同程序:可以运行的dulling函数调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始。生成器就是一种可以用于受控制的迭代计算机制。
def gen():
print ("start")
yield print("step 1")
yield print("step 2")
yield print("step 3")
m = gen()
next(m) # >>> start step 1
next(m) # >>> step 2
next(m) # >>> step 3
#产生一个生成器数列
e = (i for i in range(10) if (i % 2)) #生成一个1到10的奇数
next(e) # >>> 1
next(e) # >>> 3
for x in e:
print(x,end='') # >>> 579
第十二章.模块
-
多文档编辑程序
模块就是已经打包好的程序文档,保存在.py文件当中。 -
导入模块
#第一种
import 模块名 #声明引用该模块
模块名.函数名 #调用模块中的函数
#第二种
import 模块名 as 新名字
- if name == ‘main’
在作为程序运行时,__name__属性是’main’,而作为模块导入时,该值为模块名。可用来判别当前情况下是否符合继续将程序进行下去的条件。
def add(a,b):
return a+b
if __name__ == '__main__':
add(1,2)
#上述代码如果在自身程序中运行时,将会打印 >>> 3
#若是作为模块被调用在其它的程序当中运行时,则不会执行 add(1,2) 的功能
- 搜索路径
lib \ site-packages 目录一般用以存放模块
import sys
sys.path #查看模块sys的路径
sys.path.append("...") # 在...中写入需要添加的路径文件夹