簡體   English   中英

Python設計 - 初始化,設置和獲取類屬性

[英]Python design - initializing, setting, and getting class attributes

我有一個類,其中方法首先需要驗證屬性是否存在,否則調用函數來計算它。 然后,確保該屬性不是None ,它會對它執行一些操作。 我可以看到兩種略有不同的設計選擇:

class myclass():
    def __init__(self):
        self.attr = None

    def compute_attribute(self):
        self.attr = 1

    def print_attribute(self):
        if self.attr is None:
            self.compute_attribute()
        print self.attr

class myclass2():
    def __init__(self):
        pass

    def compute_attribute(self):
        self.attr = 1
        return self.attr

    def print_attribute(self):
        try:
            attr = self.attr
        except AttributeError:
            attr = self.compute_attribute()
        if attr is not None:
            print attr

在第一個設計中,我需要確保所有類屬性都提前設置為None ,這可能會變得冗長,但也會澄清對象的結構。

第二種選擇似乎是更廣泛使用的選擇。 然而,對於我的目的(與信息理論相關的科學計算)使用try except塊到處都可能有點過分,因為這個類並沒有真正與其他類交互,它只需要數據並計算一堆東西。

首先,您可以使用hasattr檢查對象是否具有屬性,如果屬性存在,則返回True

hasattr(object, attribute) # will return True if the object has the attribute

其次,您可以在Python中自定義屬性訪問,您可以在此處閱讀更多相關信息: https//docs.python.org/2/reference/datamodel.html#customizing-attribute-access

基本上,您重寫__getattr__方法來實現這一點,所以類似於:

class myclass2():def init (self):pass

def compute_attr(self):
    self.attr = 1
    return self.attr

def print_attribute(self):
    print self.attr

def __getattr__(self, name):
    if hasattr(self, name) and getattr(self, name)!=None:
        return getattr(self, name):
    else:
        compute_method="compute_"+name; 
        if hasattr(self, compute_method):
            return getattr(self, compute_method)()

確保你只使用getattr來訪問__getattr__的屬性,否則你最終會得到無限遞歸

基於jonrsharpe鏈接的答案 ,我提供了第三個設計選擇。 這里的想法是, MyClass的客戶端或MyClass本身的代碼根本不需要特殊的條件邏輯。 相反,裝飾器應用於執行屬性(假設成本高昂)計算的函數,然后存儲該結果。

這意味着昂貴的計算是懶惰地完成的(僅當客戶端試圖訪問該屬性時)並且只執行一次。

def lazyprop(fn):
    attr_name = '_lazy_' + fn.__name__

    @property
    def _lazyprop(self):
        if not hasattr(self, attr_name):
            setattr(self, attr_name, fn(self))
        return getattr(self, attr_name)

    return _lazyprop


class MyClass(object):
    @lazyprop
    def attr(self):
        print('Generating attr')
        return 1

    def __repr__(self):
        return str(self.attr)


if __name__ == '__main__':
    o = MyClass()
    print(o.__dict__, end='\n\n')
    print(o, end='\n\n')
    print(o.__dict__, end='\n\n')
    print(o)

產量

{}

Generating attr
1

{'_lazy_attr': 1}

1

編輯

Cyclone對OP背景的回答應用:

class lazy_property(object):
    '''
    meant to be used for lazy evaluation of an object attribute.
    property should represent non-mutable data, as it replaces itself.
    '''

    def __init__(self, fget):
        self.fget = fget
        self.func_name = fget.__name__

    def __get__(self, obj, cls):
        if obj is None:
            return None
        value = self.fget(obj)
        setattr(obj, self.func_name, value)
        return value


class MyClass(object):
    @lazy_property
    def attr(self):
        print('Generating attr')
        return 1

    def __repr__(self):
        return str(self.attr)


if __name__ == '__main__':
    o = MyClass()
    print(o.__dict__, end='\n\n')
    print(o, end='\n\n')
    print(o.__dict__, end='\n\n')
    print(o)

輸出與上面相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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