Python Read-only Class Properties
Solution 1:
The most obvious way might be to alter the class object after the fact:
classVector3(object):
# ...
Vector3.zero =Vector3(0, 0, 0)
The main problem with this is that there's then only one zero object, and if it's mutable you can cause accidental damage all over the place. It may be easier (and feel less hacky) to use a dynamic descriptor that creates a zero vector every time it's accessed (this is done by creating a ClassProperty class):
classClassProperty(property):
def__get__(self, cls, owner):
return self.fget.__get__(None, owner)()
classVector3(object):
@ClassProperty @classmethoddefzero(cls):
return cls(0, 0, 0)
I consider none of these really "pythonic", though. Consider the other mathematical types in Python: ints, floats, and complex numbers. None of these have a "zero" class attribute, or a zero constructor, instead they return zero when called with no arguments. So perhaps it might be best to do like so:
classVector3(object):def__init__(self, x=0, y=0, z=0):
self.x = x
self.y = y
self.z = z
This is less like Unity3D and more like Python, if you know what I mean.
Solution 2:
Use a metaclass
classMetaVector3(type):
@propertydefzero(cls):
return cls(0,0,0)
classVector3(object):
__metaclass__ = MetaVector3
def__init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
>>> v = Vector3.zero
>>> v.x, v.y, v.z
(0, 0, 0)
Solution 3:
Use a descriptor:
classZero(object):def__get__(self, instance, owner):
return owner(0, 0, 0)
def__set__(self, instance, value):
#could raise an exception here or somethiing#this gets called if the user attempts to overwrite the property
pass
classVector3(object):
zero = Zero()
def__init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def__repr__(self):
return str(self.__dict__)
Should do what you want:
>>> v = Vector3(1, 2, 3)
>>> v
{'y': 2, 'x': 1, 'z': 3}
>>> v.zero
{'y': 0, 'x': 0, 'z': 0}
>>> v.zero = 'foo'>>> v.zero
{'y': 0, 'x': 0, 'z': 0}
Solution 4:
What you're imagining is possible, but not necessary in this case. Just wait until after your class is defined to assign the attribute
classVector3(object):
...
Vector3.zero =Vector3(0, 0, 0)
or make it a module level constant.
There is a good chance you want simply to use a shape (3,)
numpy array instead of writing this class, for any practical purposes.
Solution 5:
That's a really interesting question, the workaround I would go with is to do a classmethod as a "getter" for the zero object:
classVector3(object):
__zero = Nonedef__init__(self, x,y,z):
self.x = x
self.y = y
self.z = z
@classmethoddefzero(cls):
ifnot cls.__zero:
cls.__zero = Vector3(0,0,0)
return cls.__zero
myzerovec = Vector3.zero()
Post a Comment for "Python Read-only Class Properties"