从对象获取属性的 Pythonic 方法是什么?

时间:2021-05-12 16:43:00

标签: python class architecture attributes

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

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

因为它可能有助于某人回答,请参阅下面的 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”,但据我所知,如果您想重命名某些内容,这可能会导致代码长期中断。

1 个答案:

答案 0 :(得分:3)

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

  • Python 的类型不是很多——事实上,它几乎没有类型
  • 在编写 Python 代码时考虑 C++ 通常很有用

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

然而,这是 Python,所以我们可以利用第 1 点:Python 的类型并不多。

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

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

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