0

我在开发类似于 Django _get_queryset(klass)方法的东西时遇到问题。当提供 QuerySet 或 mongoengine 文档时,我正在尝试提取 QuerySet。我试过以下逻辑:

from mongoengine.base import BaseDocument
from mongoengine.queryset import QuerySet

def _get_queryset(klass):
    if isinstance(klass, QuerySet):
        return klass
    if isinstance(klass, BaseDocument):
        return klass.objects
    else:
        raise ValueError

对于给定的文档,例如:

class Monkey(mongoengine.Document):
    name = mongoengine.StringField(unique=True)

如果我将以下内容传递给pythonis_instance()

>>> isinstance(db.Monkey.objects, QuerySet)
True

但是(似乎)令人惊讶的是,

>>> isinstance(Monkey, BaseDocument)
False

>>> isinstance(Monkey(), BaseDocument)
True

isinstance()呈现类时不实例化它吗?在 Django 中,一个大致等效的调用起作用:

>>> isinstance(Monkey, ModelBase)
True

为什么Monkey在 Django 中在这里实例化,但在上面的 mongoengine 版本中却没有?

4

2 回答 2

3

在 python 中,类是对象。特别是它们是以下实例type

>>> class MyClass(object): pass
... 
>>> isinstance(MyClass, type)
True

此外,由于object是最基本的类型,它们也是以下实例object

>>> isinstance(MyClass, object)
True

所以,你得到的结果是正确的。类的实例与类本身不同。如果要检查一个类是否是子类,有issubclass函数:

>>> issubclass(MyClass, object)
True

在 Django 中工作的事实isinstance(Monkey, ModelBase)是因为在 djangoModelBase中不是一个类而是一个元类:

# from django source-code
class ModelBase(type):
    """
    Metaclass for all models.
    """

这意味着模型类是其元类的实例(在这种情况下ModelBase)。

于 2013-03-10T12:50:57.453 回答
1

在 Python 中,类本身就是对象。默认情况下,类是类型的type(即它是type类的实例),但可以使用元类覆盖该默认值。使用元类将导致该类成为元类的实例(应该扩展type)。

这意味着如果您Monkey使用 metaclass定义一个类ModelBase,那么 Python 将创建一个ModelBase名为 的对象Monkey。该Monkey对象是一个类,因此您可以实例化类型为 的对象Monkey

于 2013-03-10T13:01:21.480 回答