Messing around with the typical Point class example when learning Python, I noticed that for some reason I can't have a class level (static variable) of the same type as that of the class. E.g.
class Point:
ORIGIN = Point() # doesn't work
def __init__(self, x=0, y=0):
self.x = x
self.y = y
while the same works in 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;
}
}
The question is: is there any way of achieving the same in Python. Right now I am relying on module level variables and I'm not liking that solution. Also, is there any reason why it can't be done in the body of the class?
You can't create an instance of a class, until that class is actually created, which is after the class body is evaluated (note: it's executed like normal Python code).
The same goes for your Java example: ClassLoader creates the Point
class and then executes the code from static
fields.
A rough equivalent of a class loader in Python is the metaclass, so you could do something like this:
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__")
Of course this will have some other consequences, like: all subclasses of Point
will have an ORIGIN
attribute of their own. So you probably just want to do it like others shown :)