Python学海无涯路【第41回】:类的其他内置函数

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/chuhe163/article/details/101678068


1、isinstance

class Animal:
    pass

if __name__ == '__main__':
    animal=Animal()
    print(isinstance(animal,Animal))

输出:
True

2、__getitem____setitem____delitem__

  • 以字典形式访问的是__getitem__系列,如animal["name"]
  • “.”的形式访问的是__getattr__系列,如animal.name
class Animal:
    def __init__(self,name):
        self.name=name

    def __getitem__(self, item):
        print("访问的是【%s】%item")


if __name__ == '__main__':
    animal=Animal("佩奇")
    animal["name"]    #属性存在

输出:
访问的是【%s】%item

3、__str____repr__

3.1、__str__

  • 类中默认有个__str__方法
  • __str__方法类似Java中的toString方法
  • 必须要有返回值,且必须是字符串
class Animal:
    def __init__(self,name):
        self.name=name

    def __str__(self):        
        return "name的属性是%s,%self.name"


if __name__ == '__main__':
    animal=Animal("佩奇")
    print(animal)

输出:
name的属性是%s,%self.name

3.2、__repr__

  • __repr__功能和__str__基本一致
  • 不同是__repr__是在python解释器中调用的
    在这里插入图片描述

3.2、__str____repr__共存

  • __str____repr__共存,会调用__str__方法
  • 类中只有__repr__,没有__str__才会调用__repr__

4、__format__

4.1、__format__触发的条件

  • 当format的参数传入类的实例对象时会调用__format__方法
class Animal:
    def __init__(self,name):
        self.name=name
    
    def __format__(self, format_spec):
        print("执行了__format__")
        return "__format__的返回值"


if __name__ == '__main__':
    animal=Animal("佩奇")
    print(format(animal))

输出:
执行了__format__
__format__的返回值

4.2、__format__实例演示

class Animal:
    format_dic = {
        "1": "姓名:{0.name}",
        "2": "姓名:{0.name},年龄:{0.age}"
    }

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __format__(self, format_spec):
        if not format_spec or format_spec not in self.format_dic:
            format_spec="1" #如果传入的参数是空,则默认为"1"
        fm = self.format_dic[format_spec]
        return fm.format(self)


if __name__ == '__main__':
    animal = Animal("佩奇", 1)
    print(format(animal, "1"))
    print(format(animal, "2"))
    print(format(animal))  # 不传参,用默认
    print(format(animal, "aaa"))  # 传参不正确,用默认

输出:
姓名:佩奇
姓名:佩奇,年龄:1
姓名:佩奇
姓名:佩奇

5、__slots__

5.1、__slots__的介绍

  • __slots__是一个类变量
  • 变量值可以是列表、元组,或者可迭代对象
  • 也可以是一个字符串(意味着所有实例只有一个数据属性)
  • 使用“.”来访问属性,本质是在访问类或者对象的__dict__属性字典
  • 类的字典是共享的,而每个实例的是独立的

5.2、为什么使用__slots__

  • 字典会占用大量内存,如果有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__
  • 当定义__slots__后,__slots__就会为实例使用一种更加紧湊的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个
  • 字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。
  • 使用__slots__后,不能再给实例添加新的属性,只能使用__slots__中定定义的那些属性名
  • 注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。
  • 另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。
  • 大多数情况下,你应该只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。
  • __slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。
  • 更多的是用来作为一个内存优化工具。
class Animal:
    __slots__=["name","age"]

    def __init__(self,name,age):
        self.name=name
        self.age=age



if __name__ == '__main__':
    animal=Animal("佩奇",1)
    #print(animal.__dict__) #__dict__这个属性将不再支持
    print(animal.__slots__)

6、__doc__

  • __doc__属性无法继承给子类
class Animal:
    '类的描述信息'
    pass

if __name__ == '__main__':
    animal=Animal()
    print(animal.__doc__)

输出:
类的描述信息

7、__module____classs__

  • __module__返回的是该对象是引用的哪个模块
  • 如果是当前模块,输出__main__
  • __classs__返回的是类名
class Animal:    
    pass

if __name__ == '__main__':
    animal = Animal()
    print(animal.__module__)
    print(animal.__class__)

8、__del__

  • 析构函数,当对象在内存中被释放时,自动触发执行
  • 此方法一般无须定义,因为Python是一门高级语言,程序员无需关心内存的分配和释放,所以析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

9、__call__

  • 类中定义了__call__,可以像这样animal(),调用实例,并且触发__call__
class Animal:
    def __call__(self, *args, **kwargs):
        print("执行了__call__")
        pass

if __name__ == '__main__':
    animal=Animal()
    animal      #不会触发__call__
    animal()    #会触发__call__

输出:
执行了__call__

10、__next__和__iter__实现迭代器协议

10.1、什么是迭代器协议

  • 迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)

  • 可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)

  • 协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。

10.2、将类变成可迭代对象

  • 需要实现__iter__()方法
  • 需要实现 next
  • 需要引起一个StopIteration异常,以终止迭代
class A:
    def __init__(self,n):
        self.n=n

    def __iter__(self,n):
        return self

    def __next__(self):
        if self.n==5:
            raise StopIteration("迭代终止了")
        self.n+=1
        return self.n


if __name__ == '__main__':
    a=A(1)
    print(a.__next__())
    print(next(a))
    print(next(a))
    print(next(a))
 

输出:
2
3
4
5

10.3、迭代器打印斐波那契数列

  • 斐波那契数列:这个数列从第3项开始,每一项都等于前两项之和
class Fib:
    def __init__(self):
        self._a=1
        self._b=1

    def __iter__(self):
        return self

    def __next__(self):
        if self._a>50:
            raise StopIteration("终止了")
        self._a,self._b=self._b,self._a+self._b
        return self._a

if __name__ == '__main__':
    fib=Fib()
    for i in fib:
        print(i)

输出:
1
2
3
5
8
13
21
34
55

11、描述符__get__、__set__、__delete__

  • 描述符是新式类中至少实现了__get__、__set__、__delete__方法中的一个
  • 也被称为描述符协议

11.1、触发方式

  • __get__调用一个属性时,触发
  • __set__为一个属性赋值时,触发
  • __delete__采用del删除属性时,触发
class A:
    def __get__(self, instance, value):
        print("执行了__set__")

class B:
    x=A()  #B类中调用了A类

if __name__ == '__main__':
    b=B()
    b.x     #此时触发A中的__get__ 方法

输出:
执行了__set__

11.2、描述符的分类

  • 数据描述符:至少实现了__get____set__
  • 非数据描述符:没有实现__set__

11.3、描述符的注意事项

  • 描述符本身应定义成新式类,被代理的类也应是新式类
  • 必须把描述符定义成这个类的属性,不能定义到构造函数中
  • 严格遵循优先级
  • 优先级由高到低分别是:
    • 类属性
    • 数据描述符
    • 实例属性
    • 非数据描述符
    • 找不到的属性触发__getattr__

12、上下文管理协议__enter____exit__

12.1、触发条件

  • with Animal() as a:触发__enter__
  • whith块下面的语句执行完触发__exit__
  • whith中的语句抛出异常时也会触发__exit__
  • whith中的语句抛出异常时:
    • __exit__若返回True表示,已处理了异常
    • __exit__若返回False表示,将此异常抛出
  • __exit__运行结束就代表了with语句结束
class Animal:
    def __enter__(self):
        print("执行了enter")
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("执行了exit")

if __name__ == '__main__':
    animal=Animal()
    with Animal() as a:
        print("第一步")
        print("第二步")
        print("第三步")

输出:
执行了enter
第一步
第二步
第三步
执行了exit

12.2、异常信息的内容

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/chuhe163/article/details/101678068