Python Core Notes for Test Development (20): Advanced Methods Built-in Classes

When we define a class, Python will automatically provide us with some methods, most of which are inherited from the object class or type class. We can override these methods to implement specific operations.

20.1 Making objects easier to read when printed

Printing the object with print() will display __str__()the content of the function. When running the instance directly, the printed object will display __repr__()the content of the function. Therefore, through the implementation __str__()and __repr__()these two methods, the object printing can be more in line with human reading. for example

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
​
    def __str__(self):  # print()时调用
        return 'Student object (name=%s, age=%d)' % (self.name, self.age)
​
    __repr__ = __str__  

​
print(Student("Jim", 20))  # 打印__str__函数的内容,Student object (name=Jim, age=20)

20.2 Making class objects support iteration

We know that all container types support for ... in ... for iterative loops. The for statement actually does two things. The first thing is to get an iterator, i.e. the __iter__()function is called. The second thing is the process of looping, calling __next__()functions in a loop. In fact, a custom class, as long as these two methods are implemented, the object of the class can also be iterated by the for loop.

For example, the Fibonacci sequence, implemented with a class:

class Fib:
    def __init__(self):
        self.a, self.b = 0, 1  # 初始化两个计数器a,bdef __iter__(self):
        return self  # 返回一个迭代对象,实例本身就是迭代对象,故返回自己def __next__(self):  # for循环时就是调用这个方法获取下一个值
        self.a, self.b = self.b, self.a + self.b  # 计算下一个值
        if self.a > 10000:  # 退出循环的条件
            raise StopIteration()
        return self.a  # 返回下一个值
​
​
for i in Fib():
    if i > 20: 
        break
    print(i)

20.3 Making objects callable

The functions, built-in functions and classes that we usually define are all callable objects. The intuitive feeling is that we can add a pair of parentheses after them, but if we can apply a pair of parentheses () to an object, this object It can be called a callable object, and the function callable() can be used to judge whether the object is a callable object.

callable(0)      # 函数返回 False
def add(a, b):
    return a + b
callable(add)    # 函数返回 True

If the __call__method , then the instance object will also become a callable object. That is, the instance can be followed by parentheses, and the result of the call is __call__the content of the method. See an example:

class Student:
    def __init__(self, name):
        self.name = name
​
    def __call__(self):
        print('My name is %s.' % self.name)
​
​
s = Student('Michael')
s()  # 实例变成了Callable的了,输出My name is Michael

What is the practical use of this? Let's look at an example, using __getattr__and __call__, to achieve dynamic call, dynamically generate url string.

class Chain:def __init__(self, path=''):
        self._path = path
​
    def __getattr__(self, path):
         """调用不存在的属性时,会执行这个方法,方法效果是将path用/拼接起来,返回一个实例"""
        return Chain('%s/%s' % (self._path, path))def __call__(self, path):
        """当实例被调用时,会执行这个方法,方法效果是实例里面的参数也用/拼接起来,返回一个实例"""
        return Chain('%s/%s' % (self._path, path))def __str__(self):
        return self._path
​
    __repr__ = __str__
​
​
if __name__ == '__main__':
    print(Chain().status.user.timeline.list)  # 每一个"."就是一次调用__getattr__方法
    print(Chain().users('michael').repos) # Chain().users根据__getattr__的作用会返回一个实例,加上()后回到用__call__方法

20.4 Manually create an instance object

__new__The method is responsible for creating an instance object. The method is automatically called by the Python interpreter when the object is created. It is a class method. __new__After the method returns an instance, the Python interpreter will continue to automatically call the __init__method to initialize the instance. If __new__the method does not return a value, or does not return an instance, the Python interpreter will not automatically call the __init__method. __new__The method is mainly when inheriting a class (such as int, str, tuple), to provide programmers with an opportunity to customize the instantiation process of these classes. There is also the realization of custom metaclass metaclass.

__new__A typical application is to create a singleton pattern.

The principle of the singleton mode is to add a singleton determination bit flag to the class attribute, and use this flag to determine whether the class has been instantiated. If the class has been instantiated, the instantiated object is returned.

class Singleton:
    # 重写父类的__new__方法,__new__是个类方法,第一个参数是cls,必须有返回值
    def __new__(cls, *args, **kwargs):  # 自定义类实例化对象的过程
        # __new__生成的对象放入cls的_instance属性中, 如果cls不存在_instance
        if not hasattr(cls, "_instance"):
            cls._instance = super().__new__(cls, *args, **kwargs)  # 调用父类__new__创建实例
        # 如果cls存在_instance,直接返回,不要生成新的对象
        return cls._instance
​
​
class MyClass(Singleton):
    pass
​
​
s1 = MyClass()
s2 = MyClass()
s3 = MyClass("s3")
s4 = MyClass("s4")
print(id(s1), id(s2), id(s3), id(s4))

Classes that inherit from Singleton __new__will be singletons unless they are overridden.

20.5 Customizing two object comparison logic

The method is triggered when it is determined whether two objects are equal __eq__. In this method you can define rules for equality of two objects. There are also __lt__and __gt__methods, which define the rules for comparing the size of two objects. E.g:

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
​
    def __eq__(self, other):  # 定义内置方法,自定义两个对象相等的逻辑
        return self.__dict__ == other.__dict__  # 两对象空间的属性值都相等,两个对象被认为相等。def __lt__(self, other):
        return self.age < other.age
​
​
if __name__ == '__main__':
    s1 = Student("李四", 20)
    s2 = Student("李四", 20)
    print(s2 == s1)  # True
    print(s2 is s1)  # False
    s3 = Student("王五", 19)
    print(s1 > s3)  # True

Guess you like

Origin blog.csdn.net/liuchunming033/article/details/107934981