在__init__中设置用户类的默认/空属性

问题描述

我有不错的编程水平,并从这里的社区中获得了很多价值。然而,我从来没有在编程方面有过太多的学术指导,也没有在真正有经验的程序员旁边工作过。因此,我有时会纠结于‘最佳实践’。

我找不到更好的地方来回答这个问题,尽管可能会有讨厌这类问题的煽动者,但我还是把它贴了出来。如果这让你心烦了,我很抱歉。我只是想学,不是惹你生气。

问题:

当我创建新类时,我是否应该在__init__中设置所有实例属性,即使它们是None并且实际上后来在类方法中赋值?

MyClassresults属性见下例:

class MyClass:
    def __init__(self,df):
          self.df = df
          self.results = None

    def results(df_results):
         #Imagine some calculations here or something
         self.results = df_results

我在其他项目中发现,当类属性只出现在类方法中时,它们可能会被隐藏,并且有很多问题。

那么,对于经验丰富的专业程序员来说,这方面的标准实践是什么?您是否要在__init__中定义所有实例属性以提高可读性?

如果任何人有任何关于我在哪里可以找到这样的原则的材料的链接,那么请将它们放在答案中,我将不胜感激。我知道PEP-8,我已经在上面的问题上搜索了几次,都没有找到任何人涉及到这个问题。

谢谢

安迪


解决方案

经过大量的研究和与有经验的程序员的讨论,请看下面我认为是这个问题最具毕达式的解决方案。我首先添加了更新的代码,然后添加了说明:

class MyClass:
    def __init__(self,df):
          self.df = df
          self._results = None

    @property
    def results(self):
        if self._results is None:
            raise Exception('df_client is None')
        return self._results

    def generate_results(self, df_results):
         #Imagine some calculations here or something
         self._results = df_results

描述我了解、更改的内容及其原因:

  1. 所有类属性都应包含在__init__(初始化器)方法中。这是为了确保可读性和辅助调试。

  2. 第一个问题是您不能在Python中创建私有属性。所有内容都是公共的,因此可以访问任何部分初始化的属性(例如将结果设置为None)。表示私有属性的惯例是在前面放置一个前导下划线,因此在本例中,我将其更改为self.resultsself._results

    请记住,这只是一种约定,仍然可以直接访问。但是,这是一种处理伪私有属性的高深学派方法。

  3. 第二个问题是部分初始化的属性设置为None。由于它被设置为None,正如@jferard下面解释的那样,我们现在已经丢失了快速失败提示,并添加了一层用于调试代码的混淆。

    为了解决这个问题,我们添加了一个getter方法。这可以在上面视为具有上述@property修饰符的函数results()

    这是一个在调用时检查self._results是否为None的函数。如果是,它将引发异常(故障安全提示),否则将返回对象。@property修饰符将调用样式从函数更改为属性,因此用户在MyClass实例上使用的所有内容都是.results,就像任何其他属性一样。

    (我将设置结果的方法的名称更改为generate_results()以避免混淆,并为getter方法释放.results)

  4. 如果类中有其他方法需要使用self._results,但只有在正确分配的情况下才需要使用,则可以使用self.results,这样就可以如上所述地烘焙故障安全提示。

我还建议阅读@jferard对这个问题的回答。他深入探讨了这些问题和一些解决方案。我添加我的答案的原因是,我认为在许多情况下,以上就是您所需要的全部(以及毕多德式的方法)。

相关文章