Python中相同类型的类变量

时间:2010-12-06 18:45:46

标签: python oop

在学习Python时,通过典型的Point类示例,我注意到由于某种原因,我不能拥有与类相同类型的类级别(静态变量)。 E.g。

class Point:

  ORIGIN = Point() # doesn't work

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

虽然在Java中也是如此:

class Point {

  public static void main(final String[] args) { }

  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 个答案:

答案 0 :(得分:11)

class Point(object):
  pass

Point.ORIGIN = Point()

答案 1 :(得分:6)

事后分配:

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


Point.ORIGIN = Point()

答案 2 :(得分:4)

在实际创建该类之前,您无法创建类的实例,这是在评估类主体之后(注意:它的执行方式与普通的Python代码一样)。

您的Java示例也是如此:ClassLoader创建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属性。所以你可能只想像其他人那样做:)

答案 3 :(得分:2)

你可以用类装饰器做到这一点,虽然我不确定它的名字是多少。方法如下:

def add_class_var(name, *args, **kwrds):
    def decorator(cls):
        setattr(cls, name, cls(*args, **kwrds))
        return cls
    return decorator

@add_class_var('ORIGIN')
class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

print Point.ORIGIN, Point.ORIGIN.x, Point.ORIGIN.y
# <__main__.Point instance at 0x00B5B418> 0 0

虽然在上面的代码中没有使用,但您也可以通过装饰器间接地将参数传递给类的__init__()构造函数。