繁体   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