魔法方法目录
- \__init__(self[, ...])
- \__new__(cls[, ...])
- upper()
- \__del__(self)
- 定时器
- 描述符
- \__get__(self, instance, owner)
- \__set__(self, instance, value)
- \__delete__(self, instance)
- 练习1:摄氏度华氏度转换
- 协议
- 容器类型的协议
- 练习2
- 迭代
- 迭代器
- iter()
- next()
- 版本一
- __iter __()
- __next __()
- 版本二
- 版本三
魔法方法总是被双下划线包围,例如__init__
魔法方法是面向对象的python的一切
魔法方法总能够在适当的时候被自动调用
_init_(self[, …])
问题:在写类定义的时候有些写__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
rect = Rectangle(3, 4)
print(rect.getPeri()) #周长
print(rect.getArea()) #面积
14
12
_new_(cls[, …])
upper()
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return str.__new__(cls, string)
a = CapStr('Hu zhuzhu')
print(a)
HU ZHUZHU
_del_(self)
错误表示: del x = x._del_()
class C:
def __init__(self):
print('我是__init__方法,我被调用了...')
def __del__(self):
print('我是__del__方法,我被调用了...')
c1 = C()
c2 = c1
c3 = c2
del c3
del c1
print(type(len))
print(type(dir))
print(type(int))
print(type(list))
class C:
pass
print(type(C))
print(type(int('123')))
print(type('123'))
<class 'builtin_function_or_method'>
<class 'builtin_function_or_method'>
<class 'type'>
<class 'type'>
<class 'type'>
<class 'int'>
<class 'str'>
class New_int(int):
def __add__(self, other):
return int.__sub__(self, other)
def __sub__(self, other):
return int.__add__(self, other)
a = New_int(3)
b = New_int(5)
print(a+b) #int(a)-int(b)
print(a-b)
-2
8
class Try_int(int):
def __add__(self, other):
return int(self) + int(other)
def __sub__(self, other):
return int(self) - int(other)
a = Try_int(3)
b = Try_int(5)
print(a+b)
print(a-b)
8
-2
class int(int):
def __add__(self, other):
return int.__sub__(self, other) #返回减法
a = int('5')
b = int(3)
print(a+b)
2
class Nint(int):
def __radd__(self, other):
return int.__sub__(self, other)
a = Nint('5')
print(a)
b = Nint(3)
print(a+b)
print(1+b)
5
8
2
class Nint(int):
def __radd__(self, other):
return int.__sub__(other, self)
a = Nint('5')
print(3-a)
-2
定时器
class A():
def __str__(self):
return '胡猪猪'
a = A()
print(a)
class B():
def __repr__(self):
return '胡大猪'
b = B()
print(b)
胡猪猪
胡大猪
import time as t #调用import, t = import
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): #前六个,0-5
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
print(self.prompt)
描述符
就是将某种特殊类型的类的实例指派给另一个类的属性。
_get_(self, instance, owner)
用于访问属性,它返回属性的值
_set_(self, instance, value)
将在属性分配器操作中调用,不返回任何内容
_delete_(self, instance)
控制删除操作,不返回任何内容
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('deleting...', self, instance)
class Test:
x = MyDecriptor()
test = Test()
test.x
print(test)
print(Test)
test.x = 'X.man'
getting... <__main__.MyDecriptor object at 0x0000014D64D845C8> <__main__.Test object at 0x0000014D64D846C8> <class '__main__.Test'>
<__main__.Test object at 0x0000014D64D846C8> #test
<class '__main__.Test'> #Test
setting... <__main__.MyDecriptor object at 0x0000014D64D845C8> <__main__.Test object at 0x0000014D64D846C8> X.man
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 #private
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 = 'X.man' #赋值
print(c.x)
print(c._x)
X.man
X.man
练习1:摄氏度华氏度转换
1、先定义一个温度类,然后定义两个描述符类用于描述摄氏度和华氏度两个属性
2、要求两个属性会自动进行转换,给摄氏度输出华氏度,给华氏度输出摄氏度
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 = 30
print(temp.fah)
temp.fah = 86
print(temp.cel)
86.0
30.0
协议
协议(Protocols)与其他编程语言中的接口很相似,它规定你哪些方法必须要定义。然而,在python中的协议就显得不那么正式。事实上,在python中,协议更像是一种指南。
容器类型的协议
1、如果定制的容器是不可变的,只需定义__len__()和__getitem__()方法。
2、如果定制的容器是可变的,除了__len__()和__getitem__()方法,还需定义__setitem__()和__delitem__()两个方法。
练习2
编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数。
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]
c1 = CountList(1,3,5,7,9)
c2 = CountList(2,4,6,8,10)
print(c1[1])
print(c2[1])
print(c1[1]+c2[1])
print(c1.count)
print(c2.count)
3
4
7
{0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
{0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
迭代
for i in 'FishC':
print(i)
F
i
s
h
C
links = {'胡猪猪':'是猪',\
'胡大猪':'shizhu',\
'胡二猪':'是只猪',\
'胡三猪':'zhu'}
for each in links:
print('%s -> %s' % (each, links[each]))
胡猪猪 -> 是猪
胡大猪 -> shizhu
胡二猪 -> 是只猪
胡三猪 -> zhu
迭代器
iter()
next()
string = 'Fishc'
it = iter(string)
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
F
i
s
h
c
string = 'Fishc'
it = iter(string)
while True:
try:
each = next(it)
except StopIteration:
break
print(each)
for each in string:
print(each)
F
i
s
h
c
F
i
s
h
c
版本一
__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
#self.a = self.b
#self.b = self.a + self.b
return self.a
fibs = Fibs()
for each in fibs:
if each < 20:
print(each)
else:
break #大于等于20跳出循环输出
1
1
2
3
5
8
13 #等于前两个数相加
版本二
class Fibs:
def __init__(self, n = 10):
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 #大于10生成错误输出
return self.a
fibs = Fibs()
for each in fibs:
if each < 20:
print(each)
else:
break
1
1
2
3
5
8
版本三
class Fibs:
def __init__(self, n = 10):
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(100) #这个不一样
for each in fibs:
print(each) #没有了if-else
1
1
2
3
5
8
13
21
34
55
89