Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python3/Django中正确使用元类_Django_Python 3.x - Fatal编程技术网

在Python3/Django中正确使用元类

在Python3/Django中正确使用元类,django,python-3.x,Django,Python 3.x,我一直在看参考文献和例子,但仍然不能完全正确地理解这一点 Django提供了许多使用元类作为工厂系统的一部分的示例,工厂系统创建了各种方法,等等,具体到传入的值。这个想法很清楚。但它的真正工作原理有点神秘 Django的典型代码(直接来自Django“入门”教程)如下所示: from django.db import models class Question(models.Model): question_text = models.CharField(max_length=200)

我一直在看参考文献和例子,但仍然不能完全正确地理解这一点

Django提供了许多使用元类作为工厂系统的一部分的示例,工厂系统创建了各种方法,等等,具体到传入的值。这个想法很清楚。但它的真正工作原理有点神秘

Django的典型代码(直接来自Django“入门”教程)如下所示:

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
现在,稍后将有这些类的实际实例,例如:

q1 = Question(question_text='my question', pub_date='01-01-2017')
然而,对于所有的世界来说,在类定义中,问题文本和发布数据看起来像是类范围内的对象(即,由该类的所有实例共享,如q1、q2等)

要做到这一点并保持隔离,更传统的方法是在每个类前面都有一个“self”,这样类def看起来像:

class Question(models.Model):
    self.question_text = models.CharField(max_length=200)
    self.pub_date = models.DateTimeField('date published')
我甚至试着查看Django的源代码。事实上,models.Model是一个在其上面有一个元类的类,每当一个基于models.Model的新类被声明时,它就会被调用。但代码相当神秘

这里有什么惯用的说法吗?我假定类中声明的变量不应该在实例之间共享。也许,我认为,在上面声明变量(以及它们的类型,如果你愿意的话)只是一种将它们推入内部属性dict的方法,元类做了一些魔术,使事情发生,从而导致看起来更符合逻辑的结果

但是,不知何故,随着代码的运行,一个人创建了另一个实例,如:

q2 = Question(question_text='my next question', pub_date='01-02-2017')
如果引用q1.question_text或q2.pub_date,则演示代码可以正常工作,这样它们就好像类声明中声明的变量确实有一个“self.”挂起

如果好奇的话,这里是Django源代码(模型位于第383行及其上方的元类):

字段表示DB模式中的列,是类级别的,但值是实例级别的

假设您有一个整数字段:

class WithInt(models.Model):
    fld = models.IntegerField()
这意味着:

type(WithInt.fld) # IntegerField
inst = WithInt.objects.get(1)
type(inst.fld) # int
字段表示DB模式中的列,是类级别的,但值是实例级别的

假设您有一个整数字段:

class WithInt(models.Model):
    fld = models.IntegerField()
这意味着:

type(WithInt.fld) # IntegerField
inst = WithInt.objects.get(1)
type(inst.fld) # int

那么,以下两件事是真的?(1) 类范围的var fld保存的不是数据库值,而是数据库字段的描述,具体取决于models.IntegerField是/是什么(例如,它可能只是一个类型描述符,但也可能指向数据库表和字段,或其他);(2)WithInt类的实例有一个私有字段(self.fld),它是一个整数?我假设如果所有这些都是真的,元类会做一些肮脏的工作,将self.xxx属性放入正确的dicts/结构中?这是正确的。meta类在幕后完成了所有这些。谢谢-这不容易理解,因为所有这些都是在幕后进行的。那么,以下两件事是真的吗?(1) 类范围的var fld保存的不是数据库值,而是数据库字段的描述,具体取决于models.IntegerField是/是什么(例如,它可能只是一个类型描述符,但也可能指向数据库表和字段,或其他);(2)WithInt类的实例有一个私有字段(self.fld),它是一个整数?我假设如果所有这些都是真的,元类会做一些肮脏的工作,将self.xxx属性放入正确的dicts/结构中?这是正确的。meta类在幕后完成了所有这些。谢谢——这些都是在幕后进行的,不容易理解。