【Python】类的特殊方法

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系统同样会执行该对象特定的方法。这些方法共涉及如下几个:

  1. __getattribute__(self,name):  当程序访问对象的name属性时被自动调用。
  2. __getattr__(self,name):  当程序访问对象的name属性且该属性不存在时被自动调用。
  3. __setattr__(self,name,value):  当程序对对象的name属性赋值时被自动调用。
  4. __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.与反射相关的属性和方法

  • 动态操作属性

在动态检查对象是否包含某些属性(包括方法)相关的函数有如下几个:

  1. hasattr(obj,name):检查obj对象是否包含名为name的属性或方法。
  2. getattr(obj,name[,default]):获取object对象中名为name的属性的属性值。
  3. 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.与序列相关的特殊方法

  • 序列相关方法

  1. __len__(self):该方法的返回值决定序列中元素的个数。
  2. __getitem__(self,key):该方法获取指定索引对应的元素。该方法的key应该是整数值或slice对象,否则该方法会引起KeyError异常。
  3. __contains__(self,item):该方法判断序列是否包含指定元素。
  4. __setitem__(self,key,value):该方法设置指定序列对应元素,该方法的Key应该是整数值或slice对象,否则该方法会引发KeyError异常。
  5. __delitem__(self,key):该方法删除指定索引对应的元素。
  • 实现迭代器

如果开发者需要实现迭代器,只要实现如下两个方法即可。

  1. __iter__(self):该方法返回一个迭代器(iterator),迭代器必须包含一个__next__()方法,该方法返回迭代器的下一个元素。

  2. __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.生成器

  • 创建生成器

创建生成器需要两步操作:

  1. 定义一个包含yield语句的函数
  2. 调用第一步创建的函数得到生成器

yield语句的作用有两点:

  1. 每次返回一个值,类似于return语句。
  2. 冻结执行,程序每次执行到yield语句时就会被暂停。
  • 生成器的方法

生成器运行起来后,程序员可以为生成器提供值,使生成器与外部程序动态地交换数据。

为了实现生成器与外部程序动态地交换数据,需要借助于生成器的send()方法,该方法的功能与前面示例中所使用的next()函数的功能非常相似,都用于获取生成器所生成的下一个值,并将生成器冻结在yield语句处。不同的是,send()方法可以接收一个参数,该参数值会被发送给生成器函数。

总结:

  1. 外部程序通过send()方法发送数据。
  2. 生成器函数使用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()函数向上取整。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值