gpt4 book ai didi

python - 为什么不总是使用 Python 属性?

转载 作者:太空宇宙 更新时间:2023-11-03 21:34:36 24 4
gpt4 key购买 nike

我开始学习 Python 编程,有一段时间从未接触过公共(public)/私有(private)的概念。在了解了 Java 的概念后,我仍然没有看到它有太多用处,并且一直喜欢 Python 的“我们都是同意的成年人”原则。特别是当通常的 get/set 方法向其他单行代码添加如此多的代码行时。最终,在用 C++ 编写大量项目后,我开始了解它的好处,例如允许封装实现细节。它还清楚地表达了何时不应直接设置变量,因为其设置应该有副作用。

当我的Python程序变得足够大时,我经常忘记某个属性是否仅在内部使用,也不知道该属性是否可以安全更改。通常,我最终会更改属性、运行程序、遇到异常、修复相关代码中的错误,然后重复。在Python中,我们可以使用前导下划线伪私有(private)约定和属性函数来获得这些优势,同时仍然允许代码访问它想要的内容。

这里以点类为例。实际上不应该允许直接设置属性“x”和“y”,因为“距离”属性需要随时重新计算(这也可能是一个足够复杂的表达式,每次重新计算都会花费太长时间)。

class Point:
def __init__(self, x, y):
self._x = x
self._y = y
self._distance = (x**2 + y**2) ** (1/2)

@property
def x(self):
return self._x

@property
def y(self):
return self._x

@property
def distance(self):
return self._distance

如果您的属性是只读的,则代码可能会非常简洁。

class Point:
x = property(lambda self: self._x)
y = property(lambda self: self._y)
distance = property(lambda self: self._distance)

def __init__(self, x, y):
self._x = x
self._y = y
self._distance = (x**2 + y**2) ** (1/2)

我确实很喜欢后来的风格,但并没有真正广泛使用它。将大多数“公共(public)”属性设置为属性有什么缺点吗?我只能想到:

  • 可读性?就我个人而言,后一种风格对我来说更具可读性,因为您在不实现该类时关心的任何属性都是清晰且位于顶部的。
  • 其他开发者不清楚吗?在单独项目中使用它时,这不是问题。但这显然遵循Python的规则,应该很容易理解。
  • 效率较低?这是另一层间接,因此这是可能的,但是属性访问通常不是一个非常有限的情况。
  • 编写/设置速度不够快?不必为每个类和可能的添加都严格遵循这种风格,但可以在可靠的实现真正开始形成时添加。
  • 少一点Python风格?有可能,但我觉得 Pythonic 的标准不应该是任意的,而必须与可读性和效率有关。

最佳答案

如果有必要,请将属性设置为只读。默认情况下不要将每个 attr 设置为只读。

使用属性来实现只读属性并没有什么问题。这就是属性成为 Python 一部分的原因之一。另一方面,将大多数属性设为只读也没有什么特别正确的地方。它违背了标准的 Python 习惯用法,并使您的类更难以交互(尤其是在您自己的代码库中)。请记住,Python 中的 C++ private 关键字没有实际的等效项。例如,即使 x 是只读的,也无法阻止用户仅仅执行 self._x = 19 就搬起石头砸自己的脚。

通常,使用前导下划线 _name 约定来标记内部属性与公共(public)属性就足够了:

class Foo:
def __init__(self, bar, baz):
self._mine = bar
self.public = baz

按照设计,Point 类的 xy 属性是只读属性的良好候选者。然而,我想说,灵活地设计你的类并让 distance 成为一种方法更符合 Python 风格:

class Point:
def __init__(self, x, y):
self.x = x
self.y = y

def distance(self):
return (x**2 + y**2) ** (1/2)

或者,如果性能是一个问题,请将 distance 保留为属性,但每当 xy 发生变化时重新计算它:

class Point:
@staticmethod
def _distance(x, y):
return (x**2 + y**2) ** (1/2)

@property
def x(self):
return self._x
@x.setter
def x(self, x):
self._x = x
self._distance = Point._distance(x, self._y)

@property
def y(self):
return self._y
@y.setter
def y(self, y):
self._y = y
self._distance = Point._distance(self._x, y)

distance = property(lambda self: self._distance)

def __init__(self, x, y):
self._x = x
self._y = y
self._distance = Point._distance(x, y)

关于python - 为什么不总是使用 Python 属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53314944/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com