• 语言基础篇15——Python中的面向对象编程


    面向对象编程

    基本组成

    类和对象、属性和方法(变量与函数)

    class Person:
        uuid = "123456"  # 类属性
    
        def __init__(self, name, age, sex):  # 方法
            self.name = name  # 对象属性
            self.age = age  # 对象属性
            self.sex = sex  # 对象属性
    
        def walk(self, n):  # 方法
            print(self.name + "走路" + str(n) + "步")
            
        def run(self):
            print(str(self) + "跑路")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注:使用对象概念时,有广义和狭义之分,广义上,指Python一切皆对象,类、函数或方法、变量或属性皆为对象,狭义上,特指某场景下类实例化出来的独享。如在对象实例化p = Person("张三", 15, "男")中,广义上,pPerson"张三"15均为对象,狭义上,p为对象,Person为类。

    属性,attribute

    属性分为类属性和对象属性,对象属性为对象独有,类属性为该类所有对象共享。Python中支持类属性和对象属性的动态创建和删除,正因如此,仅仅通过类定义无法分析类或对象的全部属性。

    类属性和对象属性

    # 定义类
    class Person:
        uuid = "123456"
    
        def __init__(self, name, age, sex):  # 方法
            self.name = name
            self.age = age
            self.sex = sex
    
        def walk(self, n):
            print(self.name + "走路" + str(n) + "步")
            
        def run(self):
            print(str(self) + "跑路")
    
    
    # 实例化对象
    a, b = Person("张三", 15, "男"), Person("洛五", 17, "女")
    
    # 类属性方访问
    print(a.uuid, b.uuid, Person.uuid)  # 123456 123456 123456
    Person.uuid = "654321"
    print(a.uuid, b.uuid, Person.uuid)  # 654321 654321 654321
    
    # 类属性动态添加
    Person.uuid2 = "uuid2"
    print(a.uuid2, b.uuid2, Person.uuid2)  #
    
    # 类属性动态删除
    del Person.uuid2
    # print(Person.uuid2)  # AttributeError: type object 'Person' has no attribute 'uuid2'.
    
    # 对象属性访问
    print(a.name, b.name)  # 张三 洛五
    a.name, b.name = b.name[0], a.name[0]
    print(a.name, b.name)  # 洛 张
    
    # 对象属性动态创建,uuid为对象属性
    a.uuid, b.uuid = "1", "2"
    print(a.uuid, b.uuid, Person.uuid)
    
    # 对象属性动态删除,打印类属性
    del a.uuid, b.uuid
    print(a.uuid, b.uuid, Person.uuid)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    property

    property装饰器修饰类中的方法,用于定义动态属性。

    • 属性名与property装饰的函数名一致,如r,可以直接以.访问属性,如c.r
    • 获取属性r会执行r.getter修饰的方法r
    • 修改属性会执行r.setter修饰的方法r
    • 删除属性的值会执行r.setter修饰的方法r
    • 注意r名称上的一致。
    • 若不定义r.getter修饰的方法,则获取属性r时会执行property修饰的函数。
    from math import pi
    
    
    class Circle:
    
        def __init__(self):
            self.__r = 0
    
        @property
        def r(self):
            print("property")
            return pi
    
        @r.getter  # getter
        def r(self):
            print("getter")
            return self.__r
    
        @r.setter  # setter
        def r(self, r):
            print("setter")
            self.__r = r
    
        @r.deleter
        def r(self):
            print("deleter")
            self.__r = 0
    
        @property
        def area_property(self):
            return pi * self.r ** 2
    
        def area_func(self):
            return pi * self.r ** 2
    
    
    c = Circle()
    print(c.r)
    # getter
    # 0
    
    c.r = 3
    # setter
    
    print(c.area_property)
    # getter
    # 28.274333882308138
    
    print(c.area_func())
    # getter
    # 28.274333882308138
    
    del c.r
    # deleter
    
    print(c.r)
    # getter
    # 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    方法,method

    方法分为一般方法(对象方法)、类方法、静态方法。

    一般方法

    一般方法即对象方法,默认第一个参数为该类的实例化对象。习惯上使用对象.方法(除对象参数之外的参数列表)形式调用,调用形式直接指明对象参数,参数列表中无需手动传入,语法上支持类.方法(对象, 除对象参数之外的参数列表),调用形式未直接指明对象参数,需要手动传入对象,对象一般是该方法所属类的实例化对象,但允许传入任意对象。

    class Person:
        uuid = "123456"
    
        def __init__(self, name, age, sex):  # 方法
            self.name = name
            self.age = age
            self.sex = sex
    
        def walk(self, n):
            print(self.name + "走路" + str(n) + "步")
    
        def run(s):  # 方法的第一个形参通常用于指向当前对象,习惯上命名为self,允许其他命名
            print(str(s) + "跑路")
    
    
    def run(self):  # 习惯上,函数的形参一般不命名为self,允许该命名
        print(str(self) + "跑路")
    
    
    a, b = Person("张三", 15, "男"), Person("洛五", 17, "女")
    
    # 方法的调用
    a.walk(520)  # 张三走路520步
    Person.walk(a, 520)  # 张三走路520步
    b.run()  # <__main__.Person object at 0x000001EE375447D0>跑路
    Person.run(b)  # <__main__.Person object at 0x000001EE375447D0>跑路
    Person.run("删库")  # 删库跑路,指定与Person类无关的"删库"对象
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    类方法

    类方法是以装饰器classmethod修饰的方法,默认第一个参数为类。类方法用于执行与对象无关的操作,若操作与对象五无关,何必实例化再调用方法。习惯上,以类.方法(除类参数之外的参数列表)形式调用,调用形式直接指明类参数,参数列表中无需手动传入,语法上支持对象.方法(除类参数之外的参数列表),调用形式上并未指明类,但根据对象可以唯一确定类,同样无需手动传入类参数。

    class Person:
        uuid = "123456"
    
        def __init__(self, name, age, sex):  # 方法
            self.name = name
            self.age = age
            self.sex = sex
    
        @classmethod
        def change_uuid(cls, uuid):
            cls.uuid = uuid
            print(f"{cls.__name__} {uuid}")
    
    
    a = Person("张三", 15, "男")
    a.change_uuid("123")  # Person 123
    Person.change_uuid("456")  # Person 456
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    静态方法

    静态方法是以装饰器classmethod修饰的方法,没有固定的对象参数或者类参数,等同于嵌套在类中但与类无关的函数,习惯上,以类.方法(参数列表)形式调用,同样支持对象.方法(除类参数之外的参数列表)

    class Person:
        uuid = "123456"
    
        def __init__(self, name, age, sex):  # 方法
            self.name = name
            self.age = age
            self.sex = sex
    
        @staticmethod
        def change_uuid(uuid):
            Person.uuid = uuid
            print(f"{Person.__name__} {uuid}")
    
    
    a = Person("张三", 15, "男")
    a.change_uuid("123")  # Person 123
    Person.change_uuid("456")  # Person 456
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    绑定方法与非绑定方法

    绑定方法指绑定到对象或者类的方法,绑定方法参数列表第一个即为绑定的对象或者类,使用对象或者类调用方法可以自动将对象或者类传入方法,特别地,对象调用类方法会传入对象对应的类。类中一般方法都是绑定到对象的方法,可以使用classmethod装饰器将方法绑定到类,可以使用staticmethod将方法解除绑定,既不绑定对象也不绑定类。

    class Person:
        uuid = "123456"
    
        def __init__(self, name, age, sex):  # 方法
            self.name = name
            self.age = age
            self.sex = sex
    
        def walk(self, n):
            print(self.name + "走路" + str(n) + "步")
    
        @classmethod
        def change_uuid1(cls, uuid):
            cls.uuid = uuid
            print(f"{cls.__name__} {uuid}")
    
        @staticmethod
        def change_uuid2(uuid):
            Person.uuid = uuid
            print(f"{Person.__name__} {uuid}")
    
    
    def run(self):
        print(str(self) + "跑路")
    
    
    a = Person("张三", 15, "男")
    print(run)  # 
    print(a.walk)  # >
    print(Person.change_uuid1)  # >
    print(Person.change_uuid2)  # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    访问权限控制

    访问权限控制决定外部可以访问属性或方法与否,分为公有public和私有private.

    • 属性和方法默认公有访问,使用双下划线前缀标记属性或方法为私有,如__属性或方法名
    • 魔术方法(双下方法,前后对双下划线)为公有方法。
    • 私有属性或方法会被自动转换为_类__属性或方法形式的名字,且该转换是内部的,动态添加双下划线前缀属性或方法不会转换。
    class A:
        __uuid = 1
    
        def __init__(self, a, b):
            self.a = a
            self.__b = b
    
        def get_b(self):
            print(f"公有方法get_b -> {self.__b}")
    
        def __get_b(self):
            print(f"私有方法__get_b -> {self.__b}")
    
    
    o = A("a", "b")
    
    print(o.a)  # a
    # print(o.__b)  # AttributeError: 'A' object has no attribute '__b'
    print(o._A__b)  # b
    
    o.get_b()  # 公有方法get_b -> b
    # o.__get_b()  # AttributeError: 'A' object has no attribute '__get_b'. Did you mean: '_A__get_b'?
    o._A__get_b()  # 私有方法__get_b -> b
    
    o.__c = "c"
    print(o.__c)  # c
    # print(o._A__c)  # AttributeError: 'A' object has no attribute '_A__c'. Did you mean: '_A__b'?
    
    o.__get_c = lambda _: "c"
    print(A.__dict__)
    print(o.__dict__)
    o.__get_c(None)
    o._A__get_c(None)  # AttributeError: 'A' object has no attribute '_A__get_c'. Did you mean: '_A__get_b'?
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    抽象、继承、封装、多态

    抽象

    • 类是对现实实体的抽象

    继承

    单继承
    class A:
        def __init__(self):
            print("A __init__")
            self.func()
    
        def func(self):
            print("A func")
    
    
    class B(A):
        def func(self):
            print("B func")
    
    
    b = B()  # 显然使用继承的__init__方法,调用的自己的func
    # A __init__
    # B func
    
    print(b.__dict__)
    print(B.__dict__)
    print(A.__dict__)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    多继承

    多继承经典情形,菱形继承

    class A:
        def __init__(self):
            print("A __init__")
    
        def func(self):
            print("A func")
    
    
    class B(A):
        def func(self):
            print("B func")
    
    
    class C(A):
        def func(self):
            print("C func")
    
    
    class D(B, C):
        pass
    
    
    D().func()
    # A __init__
    # B func
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    实例化链

    某个类实例化对象时,在初始化该类中的对象属性之前应当先初始化父类定义的对象属性,否则可能出现调用继承自父类的方法时,由于父类对象属性未初始化导致方法调用异常。

    初始化对象时,会调用__init__初始化方法使用,在该方法初始化对象属性之前,使用super来调用父类的初始化方法方法,同理,初始化父类对象属性之前,也会先调用父类的父类的初始化方法,依据继承关系,初始化方法会逐层调用直到调用顶层父类初始化方法执行完毕,随后次一层执行完毕,同理逐层执行完毕返回,直到再次回到这个类的初始化方法并执行完毕,此时整个初始化过程结束。

    实例化链在C++Java都有所体现,不同是的,Python中允许中断初始化链。

    class A:
        def __init__(self, a):
            self.a = a
    
        def get_a(self):
            print(self.a)
    
    
    class B(A):
        def __init__(self, a, b):
            super().__init__(a)
            self.b = b
    
    
    class C(A):
        def __init__(self, c):
            self.c = c
    
    
    B(1, 2).get_a()  # 1
    C(1).get_a()  # AttributeError: 'C' object has no attribute 'a'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    方法解析顺序,mro

    Python中使用C3算法确定方法解析顺序,访问类的__mro__属性可以获得线性序列。

    class O:
    
        def func(self):
            s = "O"
            print(s + "()")
            return s
    
    
    class A(O):
        def func(self):
            s = "A"
            print(s + "(" + super().func() + ")" + "  (注意此处,D非A父类)")
            return s
    
    
    class B(O):
        def func(self):
            s = "B"
            print(s + "(" + super().func() + ")")
            return s
    
    
    class C(A):
        def func(self):
            s = "C"
            print(s + "(" + super().func() + ")")
            return s
    
    
    class D(B):
        def func(self):
            s = "D"
            print(s + "(" + super().func() + ")")
            return s
    
    
    class E(C, D):
        def func(self):
            s = "E"
            print(s + "(" + super().func() + ")")
            return s
    
    
    e = E()
    e.func()
    # O()
    # B(O)
    # D(B)
    # A(D)  (注意此处,D非A父类)
    # C(A)
    # E(C)
    print(E.__mro__)
    # (, , , , , , )
    print(E.__base__)
    # 
    print(E.__bases__)
    # (, )
    
    
    print(issubclass(A, O))  # True  是否子类
    print(issubclass(A, D))  # False
    print(issubclass(E, A))  # True
    print(isinstance(e, E))  # True  是否实例
    print(isinstance(e, C))  # True
    
    # https://zhuanlan.zhihu.com/p/151856162
    # https://zh.wikipedia.org/wiki/C3%E7%BA%BF%E6%80%A7%E5%8C%96
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    封装

    • property
    • 访问权限控制

    多态

    python本身便是多态,没有向上转型,没有重载。

    抽象类

    • 抽象类使用ABCMeta元类生成。
    • 抽象方法使用abstractmethod装饰器修饰。
    • 抽象类不能实例化。
    • 继承抽象类的一般类需要实现抽象方法。
    • 继承抽象类的抽象类无需实现抽象方法。
    from abc import abstractmethod, ABCMeta
    
    
    # Abstract Base Class
    class A(metaclass=ABCMeta):
        @abstractmethod
        def func_1(self):
            pass
    
    
    class A_1(A):
        def func_1(self):
            pass
    
    
    a = A_1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    object

    顶层父类,Python3中所有类默认继承object,Python2中可选择性继承object,不继承object的类称之为经典类,继承object的类称之为新式类,Python3中一切类均为新式类。

    class object:
        """
        The base class of the class hierarchy.
        
        When called, it accepts no arguments and returns a new featureless
        instance that has no instance attributes and cannot be given any.
        """
        def __delattr__(self, *args, **kwargs): # real signature unknown
            """ Implement delattr(self, name). """
            pass
    
        def __dir__(self, *args, **kwargs): # real signature unknown
            """ Default dir() implementation. """
            pass
    
        def __eq__(self, *args, **kwargs): # real signature unknown
            """ Return self==value. """
            pass
    
        def __format__(self, *args, **kwargs): # real signature unknown
            """ Default object formatter. """
            pass
    
        def __getattribute__(self, *args, **kwargs): # real signature unknown
            """ Return getattr(self, name). """
            pass
    
        def __getstate__(self, *args, **kwargs): # real signature unknown
            """ Helper for pickle. """
            pass
    
        def __ge__(self, *args, **kwargs): # real signature unknown
            """ Return self>=value. """
            pass
    
        def __gt__(self, *args, **kwargs): # real signature unknown
            """ Return self>value. """
            pass
    
        def __hash__(self, *args, **kwargs): # real signature unknown
            """ Return hash(self). """
            pass
    
        def __init_subclass__(self, *args, **kwargs): # real signature unknown
            """
            This method is called when a class is subclassed.
            
            The default implementation does nothing. It may be
            overridden to extend subclasses.
            """
            pass
    
        def __init__(self): # known special case of object.__init__
            """ Initialize self.  See help(type(self)) for accurate signature. """
            pass
    
        def __le__(self, *args, **kwargs): # real signature unknown
            """ Return self<=value. """
            pass
    
        def __lt__(self, *args, **kwargs): # real signature unknown
            """ Return self
            pass
    
        @staticmethod # known case of __new__
        def __new__(cls, *more): # known special case of object.__new__
            """ Create and return a new object.  See help(type) for accurate signature. """
            pass
    
        def __ne__(self, *args, **kwargs): # real signature unknown
            """ Return self!=value. """
            pass
    
        def __reduce_ex__(self, *args, **kwargs): # real signature unknown
            """ Helper for pickle. """
            pass
    
        def __reduce__(self, *args, **kwargs): # real signature unknown
            """ Helper for pickle. """
            pass
    
        def __repr__(self, *args, **kwargs): # real signature unknown
            """ Return repr(self). """
            pass
    
        def __setattr__(self, *args, **kwargs): # real signature unknown
            """ Implement setattr(self, name, value). """
            pass
    
        def __sizeof__(self, *args, **kwargs): # real signature unknown
            """ Size of object in memory, in bytes. """
            pass
    
        def __str__(self, *args, **kwargs): # real signature unknown
            """ Return str(self). """
            pass
    
        @classmethod # known case
        def __subclasshook__(cls, subclass): # known special case of object.__subclasshook__
            """
            Abstract classes can override this to customize issubclass().
            
            This is invoked early on by abc.ABCMeta.__subclasscheck__().
            It should return True, False or NotImplemented.  If it returns
            NotImplemented, the normal algorithm is used.  Otherwise, it
            overrides the normal algorithm (and the outcome is cached).
            """
            pass
    
        __class__ = None # (!) forward: type, real value is ""
        __dict__ = {}
        __doc__ = ''
        __module__ = ''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113

    魔术方法,magic method

    魔术方法指内置的名称中带有上下划线前后缀的方法,又称双下方法,例如__init__

    __new__,构造方法,用于通过类创建实例

    __init__,初始化方法,实例被创建后调用

    __del__,终结方法,使用del将对象引用减一,引用计数为0时终结方法会被调用

    __repr__,representation,返回一个对象的正式字符串表示,通常是便于解释器理解的,在适当环境下可以基于该字符串重建对象,若不可则返回一个 <...some useful description...>结构的表示信息。在调用内置函数repr时调用。

    __str__,string,返回一个对象非正式的字符串表示,通常是便于人理解的。在调用内置函数strprintformat时调用,若没有__str__实现,会调用__repr__

    s = "yuzao"
    print(str(s))  # yuzao
    print(repr(s))  # 'yuzao'
    print(eval(repr(s)))  # yuzao eval重建对象
    
    d = [1, '2', [3]]
    
    print(str(d))  # [1, '2', [3]]
    print(repr(d))  # [1, '2', [3]]
    
    
    class C:
        def __init__(self, c):
            self.c = c
    
    
    c = C(1)
    print(repr(c))  # <__main__.C object at 0x000001DB21E33C50>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    __bytes__,返回一个bytes对象。

    __format__,返回一个对象的格式化字符串,在调用内置函数format、f-string和str.format()方法时调用。

    比较方法

    使用关系运算符比较两个对象时会调用对应方法。

    __lt__,小于

    __le__,小于等于

    __eq__,等于

    __ne__,不等于

    __gt__,大于

    __ge__,大于等于

    协议,protocol

    PEP 544 – Protocols: Structural subtyping (static duck typing)

    协议用于描述静态鸭子类型,约定有具有双下方法的类型即为同一类型。与Java中接口的概念类似。

    迭代器协议

    实现__iter____next__方法的类型即为迭代器。

  • 相关阅读:
    Web前端vueDemo—实现图片切换功能(二)
    Blender-BlenderGIS插件
    conda创建pytorch环境报错
    【STM32教程】第五章 STM32的定时器
    栈和队列(2)
    C++(20):atomic_ref原子的操作非原子变量
    【线性代数】线性代数的几何意义
    喜大普奔!有软考电子版证书可以正式办理广州落户了!
    3分钟看懂NPDP| 超全版
    LeetCode 2511. 最多可以摧毁的敌人城堡数目
  • 原文地址:https://blog.csdn.net/UZDW_/article/details/132792929