1.常见的特殊方法
-
重写__repr__方法:
__repr__是Python类中的一个特殊方法,由于object类已提供了该方法,而所有的Python类都是object的子类,因此所有的Python对象都有__repr__方法。
__repr__是一个“自我描述”的方法:当程序员直接打印该对象时,系统将会输出该对象的“自我描述”信息,用来告诉外界该对象具有的状态信息。
__repr__方法总是返回该对象所有令人感兴趣的信息所组成的字符串。
class Item:
def __init__(self,name,price):
self.name = name
self.price = price
#创建一个Item对象
im = Item("鼠标",29.8)
#打印im所引用的Item对象
print(im)
输出的结果为:
<__main__.Item object at 0x0000000001E78198>
改写__repr__方法后:
class Apple:
#实现构造器
def __init(self,color,weight):
self.color = color
self.weight = weight
#重写__repr__方法,用于实现Apple对象的“自我描述”
def __repr__(self):
return "Apple[color=" + self.color +\
",weight=" + str(str.weight) + "]"
a = Apple("红色",5.68)
#打印Apple对象
print(a)
改写__repr__后的结果为:
Apple[color=红色,weight=5.68]
-
析构方法:__del__
与__init__()方法对应的是__del__()方法,__init__()方法用于初始化Python对象,而__del__()方法则用于销毁Python对象——在任何Python对象将要被系统回收的时候,系统都会自动调用该对象的__del__()方法。
需要说明的是,只有当对象的引用计数变成0时,该对象才会被回收。因此,如果有一个对象有多个变量引用它,那么del其中一个变量是不会回收该对象的。
-
__dir__方法
对象的__dir__()方法用于列出该对象内部的所有属性(包括方法)名,该方法将会返回包含所有属性(方法)名的序列。
当程序对某个对象执行dir(object)函数时,实际上就是将该对象的__dir__()方法返回值进行排序,然后包装成列表。
-
__dict__属性
__dict__属性用于查看对象内部存储的所有属性名和属性值组成的字典,通常程序直接使用该属性值即可。程序使用__dict__属性既可查看对象的内部所有状态,也可通过字典语法来访问或修改指定属性的值。
class Item:
def __init__(self,name,price):
self.name = name
self.price = price
im = Item("鼠标",28.9)
print(im.__dict__)
#通过__dict__访问name属性
print(im.__dict__["name"])
#通过__dict__访问price属性
print(im.__dict__["price"])
im.__dict__["name"] = "键盘"
im.__dict__["price"] = 32.8
print(im.name) #键盘
print(im.price) #32.8
-
__getattr__、__setattr__等
当程序操作(包括访问、设置、删除)对象的属性时,Python系统同样会执行该对象特定的方法。这些方法共涉及如下几个:
- __getattribute__(self,name): 当程序访问对象的name属性时被自动调用。
- __getattr__(self,name): 当程序访问对象的name属性且该属性不存在时被自动调用。
- __setattr__(self,name,value): 当程序对对象的name属性赋值时被自动调用。
- __delattr__(self,name): 当程序删除对象的name属性时被自动调用。
class Rectangle:
def __init__(self,width,height):
self.width = width
self.height = height
def __setattr__(self,name,value):
print("----设置%s属性----" %name)
if name == "size":
self.width , self.height = value
else:
self.__dict__[name] =value
def __getattr__(self,name):
print("----读取%s属性----" %name)
if name == "size":
return self.width , self.height
else:
raise AttributeError
def __delattr__(self,name):
print("----删除%s属性----" %name)
if name == "size":
self.__dict__["width"] = 0
self.__dict__["height"] = 0
rect = Rectangle(3,4)
print(rect.size)
rect.size = 6,8
print(rect.width)
del rect.size
print(rect.size)
2.与反射相关的属性和方法
-
动态操作属性
在动态检查对象是否包含某些属性(包括方法)相关的函数有如下几个:
- hasattr(obj,name):检查obj对象是否包含名为name的属性或方法。
- getattr(obj,name[,default]):获取object对象中名为name的属性的属性值。
- setattr(obj,name,value,/):将obj对象的name属性设为value。
class Comment:
def __init__(self,detail,view_times):
self.detail = detail
self.view_times = view_times
def info():
print("一条简单的评论,内容是:%s" %self.detail)
c = Comment("疯狂Python讲义很不错",20)
#判断是否包含指定的属性或方法
print(hasattr(c,"detail")) #True
print(hasattr(c,"view_times")) #True
print(hasattr(c,"info")) #True
#获取指定属性的属性值
print(getattr(c,"detail")) #疯狂Python讲义很不错
print(getattr(c,"view_times")) #20
#为指定属性设置属性值
setattr(c,"detail","天气不错")
setattr(c,"view_times",32)
#输出重新设置后的属性值
print(c.detail)
print(c.view_times)
上面代码运行的结果为:
True
True
True
疯狂Python讲义很不错
20
天气不错
32
setattr()函数还可以添加属性、设置方法:
#设置不存在的属性,即为对象添加属性
setattr(c,"test","新增的测试属性")
#设置不存在的方法,即为对象设置方法
def bar():
print("一个简单的方法")
#将c的info方法设置为bar函数
setattr(c,"info",bar)
c.info()
-
__call__属性
通过hasattr()函数可以判断属性或方法是否存在,但无法判断其是属性还是方法。Python程序中可以通过判断该属性或方法是否包含__call__属性来确定它是否可调用。
class User:
def __init__(self,name,passward):
self.name = name
self.passward = passward
def validLogin(self):
print("验证%s的登录" %self.name)
u = User("crazyit" , "leegang")
#判断u.name是否包含__call__方法,即判断它是否可用
print(hasattr(u.name,"__call__"))#False
#判断u.passward是否包含__call__方法,即判断它是否可用
print(hasattr(u.passward,"__call__")) #False
#判断u.validLogin是否包含__call__方法,即判断它是否可调用
print(hasattr(u.validLogin,"__call__")) #True
3.与序列相关的特殊方法
-
序列相关方法
- __len__(self):该方法的返回值决定序列中元素的个数。
- __getitem__(self,key):该方法获取指定索引对应的元素。该方法的key应该是整数值或slice对象,否则该方法会引起KeyError异常。
- __contains__(self,item):该方法判断序列是否包含指定元素。
- __setitem__(self,key,value):该方法设置指定序列对应元素,该方法的Key应该是整数值或slice对象,否则该方法会引发KeyError异常。
- __delitem__(self,key):该方法删除指定索引对应的元素。
-
实现迭代器
如果开发者需要实现迭代器,只要实现如下两个方法即可。
-
__iter__(self):该方法返回一个迭代器(iterator),迭代器必须包含一个__next__()方法,该方法返回迭代器的下一个元素。
-
__resversed__(self):该方法主要为内建的resversed()反转函数提供支持,当程序调用reversed()函数对指定迭代器执行反转时,是由该方法实现的。
#定义一个代表斐波那契数列的迭代器
class Fibs:
def __init__(self,len):
self.first = 0
self.sec = 1
self.__len = len
#定义迭代器所需的__next__方法
def __next__(self):
#如果__len__属性为0,结束迭代
if self.__len ==0:
raise StopIteration
#完成数列计算
self.first,self.sec = self.sec,self.first +self.sec
#数列长度减一
self.__len -=1
return self.first
#定义__iter__方法,该方法返回迭代器
def __iter__(self):
return self
#创建Fibs对象
fibs = Fibs(10)
#获取迭代器的下一个元素
print(next(fibs))
#使用for循环遍历迭代器
for el in fibs:
print(el,end = " ")
程序可以使用内置的iter()函数将列表、元组等转换成迭代器:
#将列表转换为迭代器
my_iter = iter([2,"fkit",4])
#依次获取迭代器的下一个元素
print(my_iter.__next__()) #2
print(my_iter.__next__()) #fkit
-
扩展列表、元组和字典
#定义ValueDict类,继承dict类
class ValueDict(dict):
#定义构造函数
def __init__(self,*args,**kwargs):
#调用父类的构造函数
super().__init__(*args,**kwargs):
#新增getkeys方法
def getkeys(self,val):
result = []
for key ,value in self.items():
if value == val:
result.append(key)
return result
my_dict = ValueDict(语文=92,数学=89,英语=92)
#获取92对应的所有key
print(my_dict.getkeys(92))#["语文","英语"]
my_dict["编程"] = 92
print(my_dict.getkeys(92)) #["语文","英语","编程"]
4.生成器
-
创建生成器
创建生成器需要两步操作:
- 定义一个包含yield语句的函数
- 调用第一步创建的函数得到生成器
yield语句的作用有两点:
- 每次返回一个值,类似于return语句。
- 冻结执行,程序每次执行到yield语句时就会被暂停。
-
生成器的方法
生成器运行起来后,程序员可以为生成器提供值,使生成器与外部程序动态地交换数据。
为了实现生成器与外部程序动态地交换数据,需要借助于生成器的send()方法,该方法的功能与前面示例中所使用的next()函数的功能非常相似,都用于获取生成器所生成的下一个值,并将生成器冻结在yield语句处。不同的是,send()方法可以接收一个参数,该参数值会被发送给生成器函数。
总结:
- 外部程序通过send()方法发送数据。
- 生成器函数使用yield语句接受数据。
需要注意的是:只有等到生成器被“冻结”之后,外部程序才能使用send()向生成器发送数据。
5.运算符重载的特殊方法
-
与数值运算相关的特殊方法
开发人员可以为自定义类提供如下方法:
object.__add__(self,other):加法运算,为“+”运算符提供支持
object.__sub__(self,other):减法运算,为“-”运算符提供支持
object.__mul__(self,other):乘法运算,为“*”运算符提供支持
object.__matmul__(self,other):矩阵乘法,为“@”运算符提供支持
object.__truediv__(self,other):除法运算,为“/”运算符提供支持
object.__floordiv__(self,other):整除运算,为“//”运算符提供支持
object.__mod__(self,other):求余运算,为“%”运算符提供支持
object.__divmod__(self,other):求余运算,为divmod运算符提供支持
object.__pow__(self,other[,modulo]):乘方运算,为”**“运算符提供支持
object.__lshift__(self,other):左移运算,为”<<“运算符提供支持
object.__rshift__(self,other):右移运算,为”>>“运算符提供支持
object.__and__(self,other):按位与运算,为”&“运算符提供支持
object.__xor__(self,other):按位异或运算,为”^“运算符提供支持
object.__or__(self,other):按位或运算,为”|“运算符提供支持
上述的方法均可以在之前添加r,例如__rxxx__(),那么自定义类的对象就可以出现在对应运算符的右边。
Python还支持各种扩展后的赋值运算符,这些扩展后的赋值运算符也是由特殊方法来提供支持的:
object.__iadd__(self,other):为”+=“运算符提供支持
object.__isub__(self,other):为”-=“运算符提供支持
object.__imul__(self,other):为”*=“运算符提供支持
object.__imatmul__(self,other):为”@=“运算符提供支持
object.__itruediv__(self,other):为”/=“运算符提供支持
object.__ifloordiv__(self,other):为"//="运算符提供支持
object.__imod__(self,other):为”%=“运算符提供支持
object.__ipow__(self,other[,modulo]):为”**=“运算符提供支持
object.__ilshift__(self,other):为”<<=“运算符提供支持
object.__irshift__(self,other):为”>>=“运算符提供支持
object.__iand__(self,other):为”&=“运算符提供支持
object.__ixor__(self,other):为”^=“运算符提供支持
object.__ior__(self,other):为”|=“运算符提供支持
-
与比较运算符相关的特殊方法
下面是与比较运算符相关的特殊方法:
object.__lt__(self,other):为”<“运算符提供支持
object.__le__(self,other):为”<=“运算符提供支持
object.__eq__(self,other):为”==“运算符提供支持
object.__ne__(self,other):为”!=“运算符提供支持
object.__gt__(self,other):为“>”运算符提供支持
object.__ge__(self,other):为“>=”运算符提供支持
-
与单目运算符相关的特殊方法
Python还提供了+(单目求正)、-(单目求负)、~(单目取反)等运算符,这些运算符也有对应的特殊方法:
object.__neg__(self):为单目求负(-)运算符提供支持
object.__pos__(self):为单目求正(+)运算符提供支持
object.__invert__(self):为单目求反(~)运算符提供支持
-
与类型转换相关的特殊方法
Python提供了str()、int()、float()、complex()等函数(其实是这些类的构造器)将其他类型的对象转换成字符串、整数、浮点数和复数。
object.__str__(self):对应与调用内置的str()函数将该对象转换成字符串。
object.__bytes__(self):对应于调用内置的bytes()函数将该对象转换成字节内容。
object.__complex__(self):对应于调用内置的complex()函数将该对象转换成复数。
object.__int__(self):对应于调用内置的int()函数将对象转换成整数。
object.__float__(self):对应与调用内置的float()函数将对象转换成浮点数。
-
与常见的内建函数相关的特殊方法
object.__format__(self,format_spec):对应于调用内置的format()函数将对象转换成格式化字符串。
object.__hash__(self):对应于调用内置的hash()函数来获取该对象的hash码。
object.__abs__(self):对应于调用内置的abs()函数返回绝对值。
object.__round__(self,ndigits):对应与调用内置的round()函数执行四舍五入取整。
object.__trunc__(self):对应于调用内置的trunc()函数执行截断取整。
object.__floor__(self):对应于调用内置的floor()函数执行向下取整。
object.__ceil__(self):对应于调用内置的ceil()函数向上取整。