title: ‘python——day_10:魔法方法’
date: 2019-11-05 20:08:56
categories:
- python基础
tags: - python基础
python——day_10:魔法方法
构造和析构
-
魔法方法总是被双下划线包围
-
魔法方法是面向对象的python的一切
# 为什么类中有时候有__init__?因为需求 class Rectangle: def __init__(self,x,y): self.x = x # 这里是可以理解为 self.x是实例化对象的元素 self.y = y def getPeri(self): return (self.x+self.y)*2 def getArea(self): return self.x*self.y rect = Rectangle(3,4) rect.getPeri()
魔法方法
-
__init__函数没有返回值:
class A: def __init__(self): return "1" a = A()#不要给init做返回 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-3-8592369aa820> in <module> 2 def __init__(self): 3 return "1" ----> 4 a = A() TypeError: __init__() should return None, not 'str'
-
new(cls[…])第一个被调用的方法,返回cls的对象
# __new__(cls[....])第一个被调用的方法,返回cls的对象 class CapStr(str): def __new__(cls,string): string = string.upper()#变成大写后字符串 return str.__new__(cls,string) a = CapStr("I love FishC.com") a#解释是因为重写了str的方法,所以这里返回的就是默认转换为大写 'I LOVE FISHC.COM'
-
del(self)当对象销毁的时候,自动调用,垃圾回收机制自动销毁
#__del__(self)当对象销毁的时候,自动调用,垃圾回收机制自动销毁 class C: def __init__(self): print("我是__init__方法,我被调用了") def __del__(self): print("我是del方法") c1 = C() 我是__init__方法,我被调用了
-
类似于type也是一个__init__方法
type(len) builtin_function_or_method type(int) type class C: pass type(C)#工厂函数就是类对象
-
__add__方法:
#这里贴图片 class New_int(int): def __add__(self,other): return int.__sub__(self,other) a = New_int(1) b = New_int(3) a+b -2
错误实例:无限递归
#自己重写 class Try_int(int): def __add__(self,other): return self+other a = Try_int(1) b = Try_int(3) a+b# 先调用a的add方法,self就是a,others是b,然后+又来,然后递归了 #无限递归了
-
反运算操作符
# 反运算操作符 class Nint(int): def __radd__(self,other): return int.__sub__(self,other) 1+b # 反运算操作符 class Nint(int): def __rsub__(self,other): return int.__sub__(self,other) a = Nint(5) 3 - a
简单定制(定时器)
import time as t
class MyTimer():
def __init__(self):
self.prompt = "未开始计时"
self.unit= ['年','月','日','时','分','秒']
self.lasted = []
# self.start = 0# 属性覆盖方法
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.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]
print(self.prompt)
#为下一轮计时进行初始化
self.begin = 0
self.end = 0
t1 = MyTimer()
属性访问:
-
举个简单例子:
class C: def __init__(self): self.x = 'x-man' c = C() c.x
-
对属性访问抽象方法的解释:
class C: def __getattribute__(self,name):#定义当该类的属性被访问时候的行为 print("getattribute") return super().__getattribute__(name) def __getattr__(self,name):#定义当用户试图获取一个不存在的属性时的行为 print("getattr") def __setattr__(self,name,value):# 当一个属性被设置的行为 print("setattr") super().__setattr__(name,value) def __delattr__(self,name):# 定义当一个属性被删除时候的行为 print("delattr") super().__delattr__(name) c = C() c.x #
-
错误实例:
#实例 class Rectangle: def __init__(self,width=0,height=0): self.width = width self.height = height def __setattr__(self,name,value): if name=='square': self.width = value self.height = value else: self.name = value def getarea(self): return self.width *self.height r1 = Rectangle(4,5) #报错原因时 init函数,然后递归调用自身
-
修改上面代码:
#修改 class Rectangle: def __init__(self,width=0,height=0): self.width = width self.height = height def __setattr__(self,name,value): if name=='square': self.width = value self.height = value else: super().__setattr__(name,value) def getarea(self): return self.width *self.height r1 = Rectangle(4,5)
描述符
-
描述符就是将某种特殊属性的类的实例指派给另一个类的属性
-
get(self,instance,owner)
用于访问属性,它返回属性的 -
set(self,instance,value)
将在属性分配操作中调用,不返回任何内容 -
delete(self,instance)
控制删除操作,不返回任何内容 -
实例1:
class MyDecriptor: def __get__(self,instance,owner): print("getting..",self,instance,owner) def __set__(self,instance,value): print("setting..",self,instance,value) def __delete__(self,instance): print("delete...",self,instance) class Test: x = MyDecriptor() test = Test() test.x getting.. <__main__.MyDecriptor object at 0x0000014CBBF3BD30> <__main__.Test object at 0x0000014CBB9A8898> <class '__main__.Test'>
-
实例2:
class MyProperty: def __init__(self,fget=None,fset = None,fdel = 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 C: def __init__(self): self._x = None def getX(self): return self._x def setX(self,value): self._x = value def delX(self): del self._x x = MyProperty(getX,setX,delX) c = C() c.x = 1 c.x 1
-
实例三:
class Celsius: def __init__(self,value=26.0): 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 temp.cel = 30 temp.fah
容器定制
- 容器类型的协议
- 如果说定制容器不可变的话,只需要定义__len__和__getitem__方法
- 如果定制容器可变的话,不仅需要上面方法,还需要多定义__setitem__和__delitem__
-
实例:
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]
迭代器
-
for i in "fishc": print(i)
-
links = {"小甲鱼":"采购","鱼":'金鱼'} for each in links: print("%s->%s"%(each,links[each]))
-
it = iter(string) while True: try: each = next(it) except StopIteration: break print(each)
-
迭代器魔法方法
# 迭代器魔法方法 __iter__() __next__() class Fibs: def __init__(self): self.a = 0 self.b = 1 def __iter__(self): return self def __next__(self): self.a,self.b = self.b,self.a+self.b return self.a fibs = Fibs() for each in fibs: if each < 20: print(each)
生成器
-
# 生成器: a = [i for i in range(100) if not(i%2) and i % 3]
-
c = {i for i in [1,1,2,3,5]}