Coding style 使用属性pythonical限制属性访问

Coding style 使用属性pythonical限制属性访问,coding-style,attributes,python,Coding Style,Attributes,Python,我试图编写一个简短的类来表示存储在远程服务器上的对象。我希望在本地设置对象的属性而不在远程服务器上设置它们通常是个坏主意;这将意味着本地对象不再代表远程对象,甚至不知道这一事实 我计划使用下面这样的代码来处理这个问题。如果你想设置item.name,它可以让你射中自己的脚,但假设用户是明智的,不会这样做 class Item(object): def __init__(self): self.name = get_item_name() def set_name

我试图编写一个简短的类来表示存储在远程服务器上的对象。我希望在本地设置对象的属性而不在远程服务器上设置它们通常是个坏主意;这将意味着本地对象不再代表远程对象,甚至不知道这一事实

我计划使用下面这样的代码来处理这个问题。如果你想设置
item.name
,它可以让你射中自己的脚,但假设用户是明智的,不会这样做

class Item(object):
    def __init__(self):
        self.name = get_item_name()

    def set_name(self, name):
        try:
            set_item_name(name)
        except:
            handle_error()
            raise
        else:
            self.name = name
然而,我最近遇到了
@属性
装饰器,它让我写下以下内容:

class Item(object):
    def __init__(self):
        self._name = get_item_name()

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        try:
            set_item_name(value)
        except:
            handle_error()
            raise
        else:
            self._name = value
这样做的优点是仍然允许使用
item.name
访问属性,但也可以处理
item.name=blah
赋值


然而,尽管第二段代码提供了(在我看来)更好的行为,但它在属性设置中隐藏了函数调用,并且考虑到Zen的“显式优于隐式”以及Python类不应该对用户隐藏东西的一般思想,这是否会使第二块代码不那么像Python?

用OO语言编写代码就是为了隐藏东西。当您编写一个方法
doSomethingComplex()
时,您基本上是在应用程序的语言中创建了一个新词,它对必须使用该方法的开发人员隐藏了一些复杂的操作

虽然显式通常比隐式好,但这并不意味着总是这样。在您的情况下,问题不在于在setter中隐藏方法调用,而在于隐藏网络。当您试图向方法的用户隐藏真实的物理网络时,您需要确保正确处理以下情况:

  • 遥远的一面突然消失了
  • 网络丢弃数据包(本地端超时)
  • 远程端抛出异常(您必须以某种方式将其发送到本地代码,但在本地可能没有意义)
  • 远程端成功地处理了呼叫,但网络放弃了应答(因此您确实成功了,但您不知道)
  • 不管你怎么努力,这种隐藏的复杂性都会泄露出去。作为一个简单的例子,使用此代码的开发人员必须处理网络异常和超时(与任何其他方法相反)

    因此,这里的中断不是调用setter中的方法,而是引入一个全新的契约

    什么是更好的解决方案?明确网络呼叫。这对代码用户来说意味着更明显的努力,但他们总是知道自己面对的是什么(而不是奇怪为什么这个setter的行为如此奇怪)

    建议的实现:使用命令模式修改这些对象的状态。该命令需要修改对象的ID(因此不必保留本地副本)、要更改的字段和新值

    当远程端回复“成功”时更新本地缓存副本。如果远程端返回错误,请删除缓存的副本,以便再次获取它

    这将创建更多的代码,但这段代码将非常简单和明显。当您试图隐藏远程端时,代码会更少,但会更加复杂和模糊


    注:永远不要认为人们在很长的一段时间内是明智的。

    尝试:除了:提高之外的东西是完全多余的。你可以完全不用它。如果在set_item_name中引发异常,它将永远不会到达
    self.\u name=value
    行。@Martijn:这就是试图发布最小代码:)而不是转储整个内容所得到的结果。真实的东西在那里有更令人兴奋的错误处理;我只是想说清楚,这里不仅仅是一个简单的函数调用。@me_,你能解释一下为什么你说“…它在属性设置中隐藏函数调用…”?检查这个主题:这是一个关于Python中属性以及为什么和如何正确使用它们的很好的讨论。@BasicWolf:我的意思是,当有人编写
    item.name=blah
    时,他们所做的看起来像是一个简单的属性集,但在封面下隐藏着一个函数调用。我将很快查看该链接…