首页 > 解决方案 > 私有方法与计算的实例变量

问题描述

我已经有这个问题很长时间了,并且我已经看到两种方式都在实施。我想看看我什么时候会选择其中一个。

class Dog(object):

    def __init__(self, color, breed, data=None):
        self.color = color
        self.breed = breed
        self.data = data or {}

    def print_owners(self):
        owners = self._owners()

        for owner in owners:
            print(owner)

    def _owners(self):
        return self.data.get('previous_owners', [])

或者,

class Dog(object):
    def __init__(self, color, breed, data=None):
        self.color = color
        self.breed = breed
        self.data = data or {}
        self._owners = self.data.get('previous_owners', [])

    def print_owners(self):
        for owner in self._owners:
            print(owner)
data = {
    'dob': '05/05/2019',
    'previous_owners': ['Miguel Francisco','Juan Paulo', 'Ofelia']
}

pepito = Dog('black', 'chihuahua', data)
pepito.print_owners()

两种方式都有效,但我想看看我会选择其中一种的用例和原因。

我在 Ruby on Rails 上做了 2 年,我看到第一种方式被更频繁地实现。然后,我搬到了另一家使用 Python 的公司,并且更经常地实施第二种方式。我不喜欢该__init__方法被过度填充,但同时,我不喜欢方法的过度创建会产生某种类似反模式的行为。

标签: python

解决方案


如果您将代码的最后一位更改为:

data = {
    'dob': '05/05/2019',
    'previous_owners': ['Miguel Francisco','Juan Paulo', 'Ofelia']
}

pepito = Dog('black', 'chihuahua', data)
data['previous_owners'] = ['who', 'are', 'these', 'people']
pepito.print_owners()

在第一个实现中,单词、'who'和被打印出来。'are''these''people'

在第二个实现中,名称'Miguel Francisco''Juan Paulo''Ofelia'打印出来。

不同之处在于第二个实现在初始化时设置属性self._owners,这意味着data['previous_owners']指向的列表与该实例相关联,即使您稍后删除或修改data['previous_owners']指向的内容。另一方面,第一个实现必须检索 每次调用该方法data['previous_owners']时指向_owners的值,这意味着调用print_owners可能会导致不同的结果,具体取决于您是否修改了与 关联的值data['previous_owners']

哪种实现是“最好的”取决于您的特定用例:您是希望在初始化时设置该属性(第二个实现),还是随着代码的进行动态修改它(第一个实现)?

另请注意,在第一个实现中,_owners是一个伪装成方法的属性,因此对于 Pythonic 代码,您真正想要的是@property那里的装饰器:

 class Dog(object):

    def __init__(self, color, breed, data=None):
        self.color = color
        self.breed = breed
        self.data = data or {}

    def print_owners(self):
        for owner in self._owners:
            print(owner)

    @property
    def _owners(self):
        return self.data.get('previous_owners', [])

推荐阅读