簡體   English   中英

python只讀類屬性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM