在Python中定义未更改的公共变量是一种好做法吗?

在Python中定义未更改的公共变量是一种好做法吗?,python,design-patterns,properties,attributes,setter,Python,Design Patterns,Properties,Attributes,Setter,假设我们有一个类,在创建后的某个点上,需要为该类分配一个值: class ProcStatus: def __init__(self, name): self.name = name self._status_code = None def set_status_code(self, value): self._status_code = value def print_proc_status(self): # Som

假设我们有一个类,在创建后的某个点上,需要为该类分配一个值:

class ProcStatus:
    def __init__(self, name):
        self.name = name
        self._status_code = None

    def set_status_code(self, value):
        self._status_code = value

    def print_proc_status(self):  # Some function that does something with the status code
        print(f'{self.name} returned code {self._status_code}')


status = ProcStatus('ls')
# Some code in between
status.set_status_code(1)
status.print_proc_status()
使用这种设计,接口清楚地表明调用方可以(并且被鼓励)显式地设置状态代码。但是,更具python风格的方法是使用一个属性:

class ProcStatus:
    def __init__(self, name):
        self.name = name
        self.status_code = None

    def print_proc_status(self):  # Some function that does something with the status code
        print(f'{self.name} returned code {self.status_code}')


status = ProcStatus('ls')
# Some code in between
status.status_code = 1
status.print_proc_status()

第二个是更好的设计吗?尽管看起来有点误导,因为类中从未更新过
status\u code
?或者,将属性setter和getter分配给私有字段是正确的方法吗?

为变量设置setter和getter的效用是,它们可以对字段的用户集值强制执行一些约束或维护类不变量-换句话说,它们允许您“清理”否则可能是任意值

要实现两个世界的最佳效果(您的示例#1和#2),最具python风格的方法是使用
@property
装饰器,它看起来像:

类状态:
定义初始化(self,name):
self.name=名称
自我状态代码=无
@财产
def状态_代码(自身):
打印(“获取”)
返回自我状态代码
@属性设置器
def状态_代码(自身、值):
打印(“设置”)
#可能应用约束,请检查“值”是否有效
自身状态代码=值

现在你有了setter和getter的额外好处,还有status.status\u code=1或打印(status.status\u code)

的美感。我想,这最终取决于你的情况。有两种情况:


#1-不使用getter/setter(首选) 就使用getter/setter(Java风格)和属性而言,属性始终是首选的,因为它更像python方式。每当用户需要
状态\u code
来获得一个值时,他们可以通过简单的赋值操作来覆盖属性的值:

status.status_code = 1
重要的是用户了解您的类是如何工作的,以及哪些字段对什么重要。如果功能需要
status\u code
,则应向用户请求将其作为参数,或在文档中告知用户该功能取决于先前设置的
status\u code


#2-何时使用getter/setter 您希望使用getter/setter类型场景的唯一原因是,您希望格式化通过访问属性创建的输出,并检查分配给它的值(
\u status\u code
)。因此,基本上,当您不希望用户直接与变量交互时。这可以用pythonic的方法来完成,我认为Skrino的答案在这里发挥了作用


就将其称为“私有”变量而言,python实际上没有这些变量。关于这件事,我们谈了很久。但是在这些情况下,当您想让用户能够使用一些约束来更改变量的值时,使用带有“private”变量的getter/setter是一个好主意。

status\u code
设置为public属性可以让调用方更清楚地设置其值。不要为setter方法操心,除非您想约束可以为其分配的值。属性的好处在于,如果需要,可以使用属性替换公共属性,而无需更改接口。如果不需要检查
status\u code
的有效性,这仍然是正确的方法吗?因为在这种情况下,让setter和getter只设置并获取私有属性似乎是多余的,实现者必须达到一个很好的平衡。一方面,您是对的,将属性样板添加到简单(即无约束)字段是冗长的。但另一方面,它明确传达了该字段为公共字段并由类用户交互的意图,而没有样板文件,用户必须阅读文档(如果存在),以选择相关的类字段,或者从实现中推断它是面向用户的。此外,请注意,变量名的下划线后缀约定会立即传达这样的信息:该字段不会被类用户交互,并且不应该以任何方式在类的对象上访问(例如,
status.status\u code\u=1
发出非法访问的尖叫),一般来说,对于它提供的方法来说,最重要的是这些方法解释了它们在文档中所做的事情。文档是非常重要的,你不应该表现得好像它是一个缺点。变量是否需要更改取决于它的使用时间,而不是是否存在更改它的方法。