关于django:Python超级方法:类名未定义

Python super method: class name not defined

本问题已经有最佳答案,请猛点这里访问。

我在另一个类中定义了一个类,就像这样。基本上,我试图重写db.model中的save方法——实际上只是django.db.models.Model。但是当我运行这段代码时,我看到了一个NameError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class GameCenterDB:
    class GameCenterDBConfig:
        class Config:
            db_for_read ="game_center_db.slave"
            db_for_write ="default"

    class PublisherTab(GameCenterDBConfig, db.Model):
        publisher_id = db.PositiveIntegerField(primary_key=True)
        name = db.CharField(max_length=100)
        create_time = db.PositiveIntegerField()
        update_time = db.PositiveIntegerField()

        class Meta:
            db_table = u'publisher_tab'

        def save(self, *args, **kwargs):
            curr_time = int(time.time())
            if not self.create_time:
                self.create_time = curr_time
            self.update_time = curr_time
            # See the line below, this triggers an error
            # NameError: global name 'PublisherTab' is not defined
            super(PublisherTab, self).save(*args, **kwargs)

据我了解,当它在GameCenterDB中时,我应该能够直接使用PublisherTab,对吗?

1
NameError: global name 'PublisherTab' is not defined

这样改变save方法可以解决这个错误。但我就是不明白为什么。

1
2
3
4
5
6
def save(self, *args, **kwargs):
     curr_time = int(time.time())
     if not self.create_time:
         self.create_time = curr_time
     self.update_time = curr_time
     super(GameCenterDB.PublisherTab, self).save(*args, **kwargs)

而且,似乎class PublisherTab(GameCenterDBConfig, db.Model):的解释没有任何错误,混音器工作正常。为什么可以毫无问题地使用GameCenterDBConfig


"根据我的理解,当它在GameCenterDB中时,我应该能够直接使用PublisherTab,对吗?"

错了。python要求使用class或variable(通常是self)前缀对类成员进行完全限定。对于类中声明的任何成员变量都是这样的。例如。:

1
2
3
4
5
6
7
8
class Foo:
    class Bar:
        quux = 1
    def f(self):
        print"Foo.Bar.quux: %d" % Foo.Bar.quux
        print"self.Bar.quux: %d" % self.Bar.quux
foo = Foo()
foo.f()

现在考虑这个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# scope is top-level module
class Foo:
   # scope is Foo
    class Bar:
        # scope is Foo.Bar
        quux = 1
    # scope is Foo
    Bar.quux = 2 # [A]
    try:
        print"x: %d" % x
    except NameError:
        print"x gave an error because it is outside scope"
    def f(self):
        # scope is Foo when we are defining but not when we are running!
        try:
            print"Bar.quux: %d" % Bar.quux
        except NameError:
            print"Bar.quux gave us an error because it is outside scope"
        print"Foo.Bar.quux: %d" % Foo.Bar.quux
        print"self.Bar.quux: %d" % self.Bar.quux
        print"x is in scope: %d" % x
# scope is top-level module again
x = 456
foo = Foo()
foo.f()

我在[A]添加了代码。程序现在打印"2"而不是"1"。

为什么不需要在[a]上限定bar.quux,但在f()中是这样做的?

因为当运行[A]时,脚本在类foo的范围内。

但是当运行foo.f()时,脚本就在模块的作用域内,因为这就是您从中调用它的地方。这就是为什么您需要在方法定义中显式声明self,而foo.f()Foo.f(foo)的语法糖。

这是Python最不讨人喜欢的部分之一。这很难理解。


你想这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
class GameCenterDB(object):
    class GameCenterDBConfig(object):
        class Config(object):
            pass

    class PublisherTab(GameCenterDB.GameCenterDBConfig, db.Model):
        pass

        class Meta:
            pass

        def save(self, *args, **kwargs):
            super(GameCenterDB.PublisherTab, self).save(*args, **kwargs)

您需要从全局范围引用这些类名。