[英]python read-only class properties
有没有办法在Python中制作只读类属性? 例如 在Unity3d中,您可以执行以下操作:
transform.position = Vector3.zero
Vector3.zero返回Vector3类的实例,其中x,y和z为0。这基本上与以下内容相同:
transform.position = Vector3(0, 0, 0)
我尝试做这样的事情:
class Vector3(object):
zero = Vector3(0, 0, 0)
...
但是我收到一个未定义的变量错误,因为尚未定义该类。 那么,如何创建不需要该类实例的只读类属性?
最明显的方法可能是在事实发生之后更改类对象:
class Vector3(object):
# ...
Vector3.zero = Vector3(0, 0, 0)
这样做的主要问题是只有一个零物体,如果它是可变的,则可能在整个地方造成意外损坏。 使用动态描述符在每次访问它时都会创建零矢量可能会更容易(但也不会感到麻烦 )(通过创建ClassProperty类来完成):
class ClassProperty(property):
def __get__(self, cls, owner):
return self.fget.__get__(None, owner)()
class Vector3(object):
@ClassProperty
@classmethod
def zero(cls):
return cls(0, 0, 0)
不过,我认为这些都不是真正的“ pythonic”。 考虑Python中的其他数学类型:整数,浮点数和复数。 这些都不具有“零”类属性或零构造函数,而是在不带参数调用时返回零。 因此,也许最好这样做:
class Vector3(object):
def __init__(self, x=0, y=0, z=0):
self.x = x
self.y = y
self.z = z
如果您知道我的意思,那么这不太像Unity3D,而更像Python。
使用元类
class MetaVector3(type):
@property
def zero(cls):
return cls(0,0,0)
class Vector3(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)
使用描述符 :
class Zero(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
class Vector3(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__)
应该做你想做的:
>>> 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}
您正在想象的是可能的,但在这种情况下不是必须的。 只需等到定义了类之后再分配属性
class Vector3(object):
...
Vector3.zero = Vector3(0, 0, 0)
或使其成为模块级别常量。
出于任何实际目的,您很有可能只是使用shape (3,)
numpy数组而不是编写此类。
这是一个非常有趣的问题,我要解决的方法是将类方法作为零对象的“获取器”:
class Vector3(object):
__zero = None
def __init__(self, x,y,z):
self.x = x
self.y = y
self.z = z
@classmethod
def zero(cls):
if not cls.__zero:
cls.__zero = Vector3(0,0,0)
return cls.__zero
myzerovec = Vector3.zero()
class ClassProperty(property):
def __get__(self, cls, owner):
return self.fget.__get__(None, owner)()
class Vector3(object):
_zero = None
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
@ClassProperty
@classmethod
def zero(cls):
if cls._zero is None:
cls._zero = cls(0,0,0)
return cls._zero
至于只读部分, 这是一个很好的资源。
template = property(lambda self: self.__template)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.