目录
生成器对象的三种创建方式
classmethod和staticmethod
__class__属性
python创建一个类会依次去调用哪些方法
__new__和__init__实现单例模式的饿汉式和懒汉式
select_related
和 prefetch_related
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
classmethod
和staticmethod
都是Python类中定义方法的装饰器,classmethod
和staticmethod
都是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