Day1:变量、运算符与数据类型
Day2:条件与循环
Day3&4:列表与元组
Day5:字符串与序列
Day6&7:函数与Lambda表达式
Day8:字典与集合
Day9&10:文件与文件系统
Day11:异常处理
Day12:else 与 with 语句
Day13&14:类与对象
Day15&16:魔法方法——>本文
Day17:模块
通俗的讲解Python中的__new__()方法 - SJ2050的博客 - CSDN博客
new(cls[,…])方法是先于__init__方法执行的类构造方法,而__new__和__init__ 配合才是python中真正的类构造器
可以看出,__new__方法的第一个参数是这个类,而其余的参数会在调用成功后再全部传递给__init__方法初始化
同时应注意到,__init__方法传入类的实例化对象(self),而__new__方法返回的值就是一个实例化对象,如果__new__方法返回None,则__init__方法不会被执行
注意,返回值只能调用父类中的__new__方法,而不能调用毫无关系的类的__new__方法
绝大多数情况下,我们都不需要自己重写__new__方法,但在当继承一个不可变的类型(例如str类,int类等)时,它的特性就尤显重要了。
class CapStr(str):
def __new__(cls,string):
string = string.upper()
return super().__new__(cls,string)
a = CapStr("I love China!")
print(a)
#I LOVE CHINA!
方法__del__(self)用于析构对象
需要注意的是,del A(马上删除)并不等于A.del()
是当没有变量引用这个类 的时候系统自动调用__del__()方法
class A():
def __init__(self,Num):
self.num=Num
def printnum(self):
print(self.num)
def __del__(self):
print('__del__被调用')
a1=A(5)
a2=a1
print('删除a1')
del a1
print('删除a2')
del a2
'''
删除a1
删除a2
__del__被调用 在a2被删除之后才调用,与删除顺序无关
'''
可以自定义方法对对象进行算术运算
主要方法如下:
p.s. divmod(a,b)的结果是元组(a//b,a%b)
class new_int(int):
def __add__(self,other): #试将加法定义为减法
return int.__sub__(self,other)
a=new_int(3)
b=new_int(5)
print(a+b)
#-2
注意,这里不能定义类似
class new_int(int):
def __add__(self,other):
return self+other
进行返回,因为我们将self(a)和other(b)都定义成了new_int类型
对于这个类型的两个数据之间,“+”自动再次调用__add__(self,other)方法,造成无尽递归
反运算的方法就是在上述提到的运算方法名前加r
如,__rsub__代表+的反运算,即用右减去左,3 - 5 = 2
比如出现在两个不同类型对象的运算中时(往往其中一个对象的种类继承于另一个对象),因为左边的数找不到用于这两种类型的对应运算法,所以调用了右边的数的反运算方法
class new_int(int):
def __radd__(self,other):
return int.__sub__(self,other)
a=new_int(3)
print(1+a)
#2 因为int中没有int+new_int的方法,所以调用了new_int中的__radd__()方法
增量赋值方法就是在上述提到的运算方法名前加i
如,__isub__代表+的增量赋值运算,即“+=”,a=1,a+=3——>a=4
也可自定义
__str__相当于str(obj),用在被打印的内容是字符串的时候
>>> class A():
... def __str__(self):
... return 'class A'
...
>>> a=A()
>>> a
<__main__.A instance at 0x105ab8b90>
>>> print(a)
class A
__str__相当于print(str(obj)),用在直接将内容转化为字符串打印的时候
>>> class B():
... def __repr__(self):
... return 'class B'
...
>>> b=B()
>>> b
class B
原本用法详见Day13&14:类与对象
class A():
def __getattr__(self, name):
print('getattr')
def __getattribute__(self, name):
print('getattribute')
return super().__getattribute__(name)
myA=A()
print(myA.a)
#myA=A()
#print(myA.a)
描述符就是将某种特殊类型的类的实例指派给另一个类的属性。
class Desc(object):
def __get__(self, instance, owner):
print("__get__...",self,instance,owner)
def __set__(self, instance, value):
print('__set__...',self,instance,value)
def __delete__(self, instance):
return ('__delete__...',self,instance)
class TestDesc(object):
x = Desc()
t = TestDesc()
t.x #希望调用__get__()
#__get__... <__main__.Desc object at 0x1092c3438> <__main__.TestDesc object at 0x1092c33c8>
t.x #希望调用__set__()
#__set__... <__main__.Desc object at 0x10e63e4e0> <__main__.TestDesc object at 0x10e63e470> hello
t.x #希望调用__delete__()
#__delete__... <__main__.Desc object at 0x10e63e4e0> <__main__.TestDesc object at 0x10e63e470>
可以看出,这几个传入的参数分别为:
协议(Protocols)与其它编程语言中的接口很相似,它规定你哪些方法必须要定义。
然而,在 Python 中的协议就显得不那么正式。事实上,在 Python 中,协议更像是一种指南。
方法名 | 具体内容 |
---|---|
1__len__(self) | 定义当被len()调用时的行为(返回容器中元素的个数) |
2__getitem__(self, key) | 定义获取容器中元素的行为,相当于self[key] |
3__setitem__(self, key, value) | 定义设置容器中指定元素的行为,相当于self[key] = value |
4__delitem__(self, key) | 定义删除容器中指定元素的行为,相当于del self[key] |
5__iter__(self) | 定义当迭代容器中元素的行为 |
6__contains__(self,item) | 定义当使用成员测试运算符时的行为 |
class Node(object): #链表节点
def __init__(self,val,p=None):
self.data = val
self.next = p
class LinkList(object):
def __init__(self):
self.head = None
def __getitem__(self, key):
if self.is_empty():
print ('linklist is empty.')
return
elif key <0 or key > self.getlength():
print ('the given key is error')
return
else:
return self.getitem(key)
def __setitem__(self, key, value):
if self.is_empty():
print ('linklist is empty.')
return
elif key <0 or key > self.getlength():
print ('the given key is error')
return
else:
self.delete(key)
return self.insert(key)
def initlist(self,data): #集体初始化
self.head = Node(data[0])
p = self.head
for i in data[1:]:
node = Node(i)
p.next = node
p = p.next
def getlength(self): #获得长度
p = self.head
length = 0
while p!=None:
length+=1
p = p.next
return length
def is_empty(self): #是否为空
if self.head==None:
return True
else:
return False
def clear(self): #清空
self.head = None
def append(self,item): #增加节点
q = Node(item)
if self.head ==None:
self.head = q
else:
p = self.head
while p.next!=None:
p = p.next
p.next = q
def insert(self,index,item):
if index >self.getlength():
print ('OutOfRange.')
return
if index ==0:
q = Node(item,self.head)
self.head = q
else:
p = self.head
post = self.head
j = 0
while p.next!=None and j<index:
post = p
p = p.next
j+=1
if index ==j:
q = Node(item,p)
post.next = q
q.next = p
def delete(self,index):
if (self.head==None or index<0 or index >self.getlength()):
print ('Wrong.')
return
if index ==0:
q=self.head.next
self.head = q
p = self.head
post = self.head
j = 0
while p!=None and p.next!=None and j<index:
post = p
p = p.next
j+=1
if index ==j:
post.next = p.next
break
def index(self,value):
if self.is_empty():
print ('Linklist is empty.')
return
p = self.head
i = 0
while p.next!=None and not p.data ==value:
p = p.next
i+=1
if p.data == value:
return i
else:
return -1
迭代是是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()
字符串,列表或元组对象都可用于创建迭代器
>>> list=[1,2,3,4]
>>> it = iter(list) # 创建迭代器对象
>>> print (next(it)) # 输出迭代器的下一个元素
1
>>> print (next(it))
2
StopIteration 异常用于标识迭代的完成,当被迭代的容器内所有元素都被迭代完了后,继续调用next()会爆出StopIteration异常
list=[1,2,3,4]
it = iter(list)
while True:
try:
print (next(it))
except StopIteration:
print('stop')
break
'''
1
2
3
4
stop
'''
在 next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
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)
'''
1
1
2
3
5
8
13
21
34
55
89
'''
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
同样迭代Fibonacci数列:
def fibonacci(n):
a, b = 0, 1
while True:
if a>n: return
a, b = b, a + b
yield a
fibs = Fibs(100)
for each in fibs:
print(each,end=' ')
#1 1 2 3 5 8 13 21 34 55 89
参考视频:
[小甲鱼]零基础入门学习Python-bilibili