Python Web开发技巧X

目录

生成器对象的三种创建方式

classmethod和staticmethod

__class__属性

python创建一个类会依次去调用哪些方法

__new__和__init__实现单例模式的饿汉式和懒汉式


 

  select_related 和 prefetch_related 是 Django ORM 提供的两个查询优化方法,用于减少数据库查询的数量和提高性能。

  select_related 方法用于在查询时一次性获取相关联的外键对象。可避免多次查询数据库获取关联对象,从而减少数据库访问次数。适用于一对一和多对一关系的查询。方法如下:

# 获取单个对象并关联查询外键对象
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 方法用于在查询时一次性获取相关联的多对多或者一对多的对象集合。这样可以避免多次查询数据库来获取关联对象集合,从而减少数据库访问次数。使用方法如下:

# 获取单个对象并关联查询多对多关系的对象集合
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')

        注意:select_related 和 prefetch_related 方法都需在查询时使用,而不是在对象上使用。另外,这两个方法并不适用于所有情况,具体使用哪个方法取决于你的数据模型和查询需求。在某些情况下,可能需要结合使用这两个方法来最大程度地优化查询性能。

        还有 Subquery 子查询,给 annotate 赋默认值的 Coalesce 函数,用 OuterRef 调用父查询外部ID,例如给一个表A,表A有外键B,表B有外键C,需要计数C,那么这是就可以用:

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取出

生成器对象的三种创建方式

        生成器(Generator)是一种特殊的迭代器,允许你在迭代过程中按需生成值

(1)生成器函数:用 yield 关键字定义的函数。调用该函数时,会返回一生成器对象。可用next()函数或 for 循环迭代生成器中的值。

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

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

(2)生成器表达式:类似于列表推导式,但是使用圆括号()而不是方括号[]。生成器表达式会返回一个生成器对象,而不是一个列表。这在处理大量数据时非常有用,因为它可以节省内存。

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

for square in square_gen:
    print(square)

(3)使用itertools模块:Python的itertools模块提供了许多生成器函数,可用于创建各种复杂的生成器。例如,itertools.count()函数可以创建一个无限递增序列的生成器。

import itertools

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

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

        注:生成器能节省内存,因为它们在迭代过程中按需生成值,而不是一次性生成所有值。这意味着在任何给定时间点,生成器只需要在内存中存储当前生成的值,而不是整个序列。这在处理大量数据或无限序列时非常有用,因为它可以显著降低内存使用。

classmethod和staticmethod

        classmethodstaticmethod都是Python类中定义方法的装饰器,classmethodstaticmethod都是Python类中定义方法的装饰器。

classmethod

  • classmethod类本身作为第一个参数传递,通常命名为cls
  • 可在类方法中访问和修改类属性
  • 类方法可以被子类覆盖,这如果子类定义了具有相同名称的类方法,则子类将用自己的实现。
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

  • staticmethod不接受特殊的第一个参数,意味着它不能访问类属性和方法
  • 静态方法不能被子类覆盖,意味着子类不能提供自己的实现。
  • 常用于实现与类相关的实用程序功能,但不需要访问类的属性或方法
class MyClass:
    @staticmethod
    def add(a, b):
        return a + b

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

classmethod将类本身作为参数传递,并可以访问和修改类属性;它还可以被子类覆盖。staticmethod不接受特殊的第一个参数,不能访问类属性和方法;它通常用于实现与类相关的实用程序功能。

__class__属性

        代表类本身的属性

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)

python创建一个类会依次去调用哪些方法

__new__方法__new__方法负责创建类的实例。它是一个静态方法,第一个参数是类本身,通常命名为cls__new__方法通常会调用父类的__new__方法来创建实例,并返回这个实例。

_init__方法__init__方法负责初始化类的实例。它是一个实例方法,第一个参数是实例本身,通常命名为self。在实例创建后,__init__方法会自动被调用。可对实例属性进行初始化和赋值。

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__和__init__实现单例模式的饿汉式和懒汉式

饿汉式

实例在类加载时就被创建。这意味着实例始终存在,无论是否需要。饿汉式的优点是实例创建时线程安全,因为实例是在类加载时创建的,而类加载是线程安全的。缺点是如果实例不需要或很少使用,会浪费资源

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

懒汉式

实例在第一次使用时创建。意味着实例只在需要时创建,可节省资源。懒汉式的缺点是在多线程环境下,需要注意线程安全问题

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

确保线程安全,可以使用锁或双重检查锁定机制(懒汉式的PLUS版本)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值