【问题标题】:What is the Pythonic way of getting attributes from objects?从对象获取属性的 Pythonic 方式是什么?
【发布时间】:2021-08-03 01:27:05
【问题描述】:

我有一个代表 Atom 的类,它有两组坐标,其中一组是笛卡尔坐标,我想遵循最佳架构实践从类中获取该信息。

之前我创建了多个类方法来获取不同类型的属性,但我觉得这不是 Python 的,并且不必要地使我的代码混乱,但是我不确定通常的解决方案是什么。

由于它可能有助于某人回答,请参阅下面的 Atom 类:

class Atom():

    def __init__(self, element, x_coord, y_coord, z_coord):
        '''
        Instantiate new atom object.
        '''
        #Check information is correct
        if not isinstance(element, str):
            raise ValueError('Element must be a string.')
        if not isinstance(x_coord, int) and not isinstance(x_coord, float):
            raise ValueError('All coordinates must be numeric, x is not.')
        if not isinstance(y_coord, int) and not isinstance(y_coord, float):
            raise ValueError('All coordinates must be numeric, y is not.')
        if not isinstance(z_coord, int) and not isinstance(z_coord, float):
            raise ValueError('All coordinates must be numeric, z is not.')
        self.coordinates = np.array([x_coord, y_coord, z_coord]).astype(float)
        self.cartesian = None
        self.element = element

    def __repr__(self):
        '''
        Atom representation.
        '''
        x, y, z = list(self.coordinates)
        return f"Atom('{self.element}', {x}, {y}, {z})"

    def __copy__(self):
        x, y, z = [float(x) for x in list(self.coordinates)]
        return Atom(self.element, x, y, z)

    def set_cartesian(self, vector_space):
        '''
        Set the cartesian coordinates of the atom, based on a vector space -
        generally that of a unitcell. Requires column vectors.
        '''
        self.cartesian = vector_space @ self.coordinates.T

我希望使用单一方法来处理所有属性,以保持类整洁。我知道我可以只使用“class.attribute”,但据我了解,如果您想重命名某些内容,这可能会导致代码长期中断。

【问题讨论】:

  • 我不明白你的意思。无论你在某处使用什么,如果你重命名它并且不更新引用,就会破坏它。
  • 我猜这是编写一个封装属性的方法的想法,无论您重命名属性是什么,它都不会改变。但是,我可能想多了,您通常会使用“class.attribute”来获取属性访问权限吗?
  • 如果您需要使用过去某个时候创建​​的类,但希望属性具有不同的名称,请不要更改现有类,请编写一个适配器并按原样使用原始类。
  • 谢谢,这真的很有帮助。所以你会建议一般使用“class.attribute”,然后在必要时使用适配器?

标签: python class architecture attributes


【解决方案1】:

有几种方法可以解决这个问题。需要记住的几点:

  • Python 没有大量类型化——事实上,它几乎没有类型化
  • 在编写 Python 代码时考虑 C++ 的角度通常很有用

现在,在我看来,您想要一个方法来返回大多数(如果不是全部)Atom 的属性。如果我要在 C++ 中解决这个问题,我很可能会创建一个 struct 数据类型来使用并使用 Atom.GetAttributes() 之类的东西来返回该结构类型的变量。

但是,这是 Python,所以我们可以利用第 1 点:Python 的类型不重。

因此,您可以简单地让 Atom.GetAttrbutes() 返回包含所有属性的列表、元组或数组(您甚至可以将包含笛卡尔坐标的数组嵌套在包含其他属性的列表中)

但是,当您说让多个方法获取不同的属性数据“不是 Pythonic”时,我不确定您的意思。我将把你的注意力转移到第 2 点:在编写 python 代码时,用 C++ 来思考通常很有用。

在 C++ 中,具有多个方法(称为 成员函数)绝对是您处理返回属性(称为 成员变量)的方式,所以这是一种非常好的方法python中的东西也是如此。这是因为有几个不同的函数返回不同的属性会使你的程序运行更快。为什么?因为如果您采用上述方法(将您的属性作为列表、元组或数组返回)并以 only 方式访问您的属性,您将遇到这样的情况,例如,您只能想要一个原子的元素,但现在你必须得到所有的数据(更慢,因为 python 必须找到它们并将它们放在一个列表中)并且它们从数据中取出元素(更慢,因为显而易见的原因。)现在,这并不意味着您不应该有一个方法来一次返回所有属性(在某些情况下这也很有用),但您也应该有方法来单独访问您的属性。它只是很好的编程,并不特定于 C++ 或任何其他语言。

【讨论】:

  • 你觉得原帖中的cmets怎么样?可以直接用“class.attribute”或“object.attribute”样式访问C++中的属性吗?
  • 你绝对可以,但是直接访问属性通常被认为是不好的编程习惯。同样,这来自 C++,其中成员变量和函数被定义为公共和私有。这篇文章比我能解释得更好:softwareengineering.stackexchange.com/questions/143736/…
猜你喜欢
  • 2022-01-07
  • 1970-01-01
  • 2013-02-23
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-05
  • 1970-01-01
相关资源
最近更新 更多