我应该使用`__setattr__`,属性还是......?

时间:2016-07-25 17:32:41

标签: python

我有一个包含两个属性file_pathsave_path的对象。除非明确设置save_path,否则我希望它与file_path具有相同的值。

认为执行此操作的方法是使用__setattr__,具体如下:

class Class():
...
    def __setattr__(self, name, value):
        if name == 'file_path':
            self.file_path = value
            self.save_path = value if self.save_path == None else self.save_path
        elif name == 'save_path':
            self.save_path = value

但是这看起来会给我无限循环,因为只要设置了属性就会调用__setattr__。那么,写上述内容并避免这种情况的正确方法是什么?

3 个答案:

答案 0 :(得分:9)

首先,最简单的方法是使用属性:

<div>text</div>

其次,如果您发现自己需要撰写class Class(object): def __init__(self, ...): self._save_path = None ... @property def save_path(self): if self._save_path is None: return self.file_path else: return self._save_path @save_path.setter def save_path(self, val): self._save_path = val ,则应在__setattr__内使用super(Class, self).__setattr__绕过__setattr__并按正常方式设置属性,避免无限递归。

答案 1 :(得分:3)

这看起来很单调。你可以使用属性。三行代码:

>>> class Class:
...     def __init__(self, file_path, save_path=None):
...         self.file_path=file_path
...         self.save_path = save_path or file_path
... 
>>> c = Class('file')
>>> c.file_path
'file'
>>> c.save_path
'file'

>>> c1 = Class('file', 'save')
>>> c1.file_path
'file'
>>> c1.save_path
'save'
>>> 

答案 2 :(得分:1)

使用super

class Class:                                                           
    def __init__(self):                                                
        self.save_path = None                                          
        self.file_path = None                                          

    def __setattr__(self, name, value):                                
        super().__setattr__(name, value)                               
        if name == 'file_path':                                        
            super().__setattr__('save_path', self.save_path or value)  

c = Class()                                                            
c.file_path = 42                                                       
print(c.file_path)                                                     
print(c.save_path)     

请注意,此特定实现存在限制 - 需要首先调用self.save_path,否则它将失败,因为调用{{时尚未设置它1}}发生,它会查找super

我个人可能会使用基于属性的方法。