与类类型相同的类变量

18 投票
4 回答
6233 浏览
提问于 2025-04-16 08:08

在学习Python的时候,我在玩一个典型的点(Point)类的例子时,发现有个问题:我不能在类里面定义一个和类类型相同的类变量(静态变量)。比如:

class Point:

  ORIGIN = Point() # doesn't work

  def __init__(self, x=0, y=0):
    self.x = x
    self.y = y

而在Java中,这样做是可以的:

class Point {
    private static final Point ORIGIN = new Point(0, 0);
    
    private int x;
    private int y;
    
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

我的问题是:有没有办法在Python中做到这一点?现在我只能依赖模块级别的变量,但我不太喜欢这个解决方案。另外,为什么在类里面就不能这样做呢?

4 个回答

9

事后再给它赋值:

class Point:
  def __init__(self, x=0, y=0):
    self.x = x
    self.y = y


Point.ORIGIN = Point()
16

在编程中,有时候我们会遇到一些问题,尤其是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,不知道该怎么解决。比如,有人可能在使用一个特定的功能时,发现它没有按照预期工作。这种情况很常见,尤其是对于刚开始学习编程的人来说。

解决这类问题的第一步是要仔细阅读错误信息。错误信息通常会告诉你哪里出了问题,虽然有时候它们可能听起来很复杂,但其实可以从中找到线索。接下来,可以尝试在网上搜索这个错误,看看其他人是怎么解决的。

另外,查看官方文档也是个好主意。文档里面通常会有详细的说明和示例,帮助你更好地理解如何使用这个工具或库。如果还是找不到解决办法,可以考虑在编程社区发帖求助,描述你的问题和你尝试过的解决方法,通常会有人愿意帮助你。

总之,遇到问题时不要慌张,慢慢分析,寻找解决方案,编程的过程就是不断学习和解决问题的过程。

class Point(object):
  pass

Point.ORIGIN = Point()
5

在你能创建一个类的实例之前,得先确保这个类已经被创建。这个过程是在类的内容被评估后进行的(注意:这就像正常的Python代码一样被执行)。

你提到的Java例子也是一样的:类加载器会创建Point类,然后执行static字段中的代码。

在Python中,跟类加载器相似的东西是元类,所以你可以这样做:

def class_with_static(name, bases, body):
    static_block = body.pop("__static__", None)
    klass = type(name, bases, body)
    if static_block:
        static_block(klass)
    return klass

class Point(object):
    __metaclass__ = class_with_static

    def __static__(cls):
        cls.ORIGIN = cls()

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

assert isinstance(Point.ORIGIN, Point)
assert Point.ORIGIN.x == Point.ORIGIN.y == 0
assert not hasattr(Point, "__static__")

当然,这样做会带来一些其他的后果,比如:所有Point的子类都会有自己的ORIGIN属性。所以你可能还是想像其他人那样做比较好 :)

撰写回答