Python Web Development SkillsX

Table of contents

Three ways to create generator objects

classmethod和staticmethod

__class__ attribute

Which methods will be called in turn when python creates a class

__new__ and __init__ realize the hungry and lazy style of the singleton mode


 

  select_related and  prefetch_related are two query optimization methods provided by Django ORM to reduce the number of database queries and improve performance.

  select_related The method is used to obtain the associated foreign key object at one time when querying. It can avoid querying the database multiple times to obtain associated objects, thereby reducing the number of database accesses. Works for queries on one-to-one and many-to-one relationships. Methods as below:

# 获取单个对象并关联查询外键对象
obj = MyModel.objects.select_related('related_field').get(id=1)

# 获取多个对象并关联查询外键对象
objs = MyModel.objects.select_related('related_field')

# 在连续的关联字段上进行关联查询
objs = MyModel.objects.select_related('related_field__another_related_field')

   prefetch_related The method is used to obtain the associated many-to-many or one-to- many object collection at one time when querying. This avoids querying the database multiple times to obtain a collection of associated objects, thereby reducing the number of database accesses. The method of use is as follows:

# 获取单个对象并关联查询多对多关系的对象集合
obj = MyModel.objects.prefetch_related('many_to_many_field').get(id=1)

# 获取多个对象并关联查询多对多关系的对象集合
objs = MyModel.objects.prefetch_related('many_to_many_field')

# 在连续的关联字段上进行关联查询
objs = MyModel.objects.prefetch_related('related_field__another_related_field')

        Note: Both select_related the and  prefetch_related methods need to be used on queries, not on objects. In addition, these two methods are not suitable for all situations, which method to use depends on your data model and query requirements. In some cases, it may be desirable to use a combination of these two methods to maximize query performance.

        There is also a Subquery subquery, a Coalesce function that assigns a default value to annotate, and uses OuterRef to call the external ID of the parent query. For example, for a table A, table A has a foreign key B, and table B has a foreign key C, and C needs to be counted, then this is You can use:

query_set.annotate(
    result_count=Coalesce(
        Subquery(
            A.filter(B__C=OuterRef('pk'), enabled=True).values("A").annotate.count=Count('pk')).values('count')
    ), 0)
)
# 最后就是query_set多带了个result_count字段值处理,就是count就是子查询列表的数,再由value取出

Three ways to create generator objects

        A generator is a special kind of iterator that allows you to generate values ​​on demand during iteration

(1) Generator functionyield A function defined with keywords. When this function is called, a generator object is returned. next()A function or  loop can be used to for iterate over the values ​​in a generator.

def simple_generator():
    yield "Hello"
    yield "World"

gen = simple_generator()
for value in gen:
    print(value)

(2) Generator expressions : Similar to list comprehensions, but use parentheses ()instead of square brackets []. A generator expression returns a generator object, not a list. This is very useful when dealing with large amounts of data as it saves memory.

numbers = range(10)
square_gen = (x ** 2 for x in numbers)

for square in square_gen:
    print(square)

(3) Using itertoolsmodules : Python itertoolsmodules provide many generator functions that can be used to create various complex generators. For example, itertools.count()a function can create a generator of an infinitely increasing sequence.

import itertools

counter = itertools.count(1)  # 从1开始的无限递增序列

for i in range(5):
    print(next(counter))

        Note: Generators save memory because they generate values ​​on-demand as they iterate, rather than all values ​​at once. This means that at any given point in time, the generator only needs to store in memory the currently generated value, not the entire sequence. This is very useful when dealing with large amounts of data or infinite sequences, as it can significantly reduce memory usage.

classmethod和staticmethod

        classmethodand staticmethodare both decorators for methods defined in Python classes, classmethodand staticmethodare both decorators for methods defined in Python classes.

classmethod

  • classmethodPass the class itself as the first argument, usually namedcls .
  • Class attributes can be accessed and modified within class methods .
  • Class methods can be overridden by subclasses, so if a subclass defines a class method with the same name, the subclass will use its own implementation.
class MyClass:
    _count = 0

    @classmethod  # 装饰器
    def increment_count(cls):  # cls代表类本身
        cls._count += 1  # 可访问类属性

    @classmethod
    def get_count(cls):
        return cls._count

MyClass.increment_count()   # 类本身访问
print(MyClass.get_count())  # 输出:1

staticmethod

  • staticmethodDoes not accept a special first argument, meaning it cannot access class properties and methods .
  • Static methods cannot be overridden by subclasses , meaning subclasses cannot provide their own implementations.
  • Often used to implement utility functionality associated with a class, but without requiring access to the class's properties or methods .
class MyClass:
    @staticmethod
    def add(a, b):
        return a + b

result = MyClass.add(1, 2)
print(result)  # 输出:3

classmethodThe class itself is passed as a parameter, and class properties can be accessed and modified; it can also be overridden by subclasses. staticmethodDoes not accept a special first argument, and cannot access class properties and methods; it is typically used to implement class-related utility functions.

__class__ attribute

        Represents the attributes of the class itself

class MyClass:
    def __new__(cls, *args, **kwargs):
        # 创建一个新的实例
        instance = super().__new__(cls)
        # 可以在这里对实例进行一些初始化操作
        return instance

    def __init__(self):
        print("Initializing the instance")
        cls = self.__class__  # 通常建议用class,提高可维护性和可读性,因为类名可能不固定
        print("Instance belongs to", cls)
        cls = MyClass  
        print("Instance belongs to", cls)

Which methods will be called in turn when python creates a class

__new__Method : __new__A method is responsible for creating an instance of a class . It's a static method whose first parameter is the class itself, usually named cls. __new__Methods usually call __new__methods of the parent class to create an instance and return this instance.

_init__Method : __init__A method is responsible for initializing an instance of a class . It's an instance method whose first argument is the instance itself, usually named self. __init__The method is called automatically after the instance is created . Instance properties can be initialized and assigned.

class MyClass:
    def __new__(cls, *args, **kwargs):
        print("Creating an instance of", cls)
        instance = super().__new__(cls)
        return instance

    def __init__(self, value):
        print("Initializing the instance")
        self.value = value

# 创建MyClass的实例
my_instance = MyClass(42)
print("Instance value:", my_instance.value)

__new__ and __init__ realize the hungry and lazy style of the singleton mode

Hungry Chinese style :

Instances are created when the class is loaded . This means that the instance always exists whether it is needed or not. The advantage of the hungry Chinese style is that the instance is created thread-safely, because the instance is created when the class is loaded, and the class loading is thread-safe . The downside is that resources are wasted if the instance is not needed or.

class Singleton2:
    __instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)  # 创建类的时候就被创建可返回实例
        return cls._instance

    def __init__(self):
        pass

    @classmethod
    def get_instance(cls):  # 类方法
        return cls.__instance  # 直接返回


# 使用Singleton
singleton1 = Singleton()
singleton2 = Singleton()
print(singleton1 is singleton2)  # 输出:True

Lazy style :

Instances are created on first use . This means that instances are only created when needed, saving resources . The disadvantage of the lazy style is that in a multi-threaded environment, you need to pay attention to thread safety issues .

class Singleton1:
    __instance = None

    @classmethod
    def get_instance(cls):
        if cls.__instance is None:
            __instance = Singleton1()  # 调用获取实例时才去创建
        return cls.__instance


# 使用Singleton
singleton1 = Singleton1()
singleton2 = Singleton1()
print(singleton1 is singleton2)  # 输出:True

To ensure thread safety, you can use locks or double-check locking mechanisms ( the lazy PLUS version ).

import threading

class Singleton:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self):
        pass

# 使用Singleton
singleton1 = Singleton()
singleton2 = Singleton()
print(singleton1 is singleton2)  # 输出:True

Guess you like

Origin blog.csdn.net/lxd_max/article/details/132415263