【问题标题】:Python setters do not apply to instantiation?Python setter 不适用于实例化?
【发布时间】:2022-06-10 18:26:06
【问题描述】:

我正在尝试制作一个程序,允许您对某些用户定义的分子进行各种形式的化学分析。到目前为止,我已经定义了一个具有关联坐标属性的 Molecule 对象。当用户将坐标属性设置为某个描述分子的列表时,我将其设置为生成某种 Atom 对象。但是,当我在分子对象实例化后重置它时,坐标属性仅对应于原子对象列表。当我在对象实例化时传递坐标列表时,该属性保持为字符串列表(与输入相同),并且不对应于对应原子对象的列表。对应的代码是,

periodic_table = {
    'H': {'Z': 1.008, 'nelec': 1},
    'C': {'Z': 12.011, 'nelec': 6},
    'N': {'Z': 14.007, 'nelec': 7},
    'O': {'Z': 15.999, 'nelec': 8},
    'S': {'Z': 32.06, 'nelec': 16},
    'Br': {'Z': 79.904, 'nelec': 35},
    'I': {'Z': 126.90, 'nelec': 53}
}




class Atom:

    def __init__(self, label: str, vector: list):
        self.__label = label
        self.vector = vector
        self.__lookup_info()


    def __lookup_info(self):
        atom_info = periodic_table[self.__label]
        self.__Z = atom_info['Z']
        self.__nelec = atom_info['nelec']

    @property
    def label(self):
        return self.__label

    @label.setter
    def label(self, value):
        if type(value) != str:
            raise Exception("Atomic labels must be a string")
        else:
            value = value.upper()
            self.__label = value
            self.__lookup_info()
            # lookup info and set z/nelec

    @property
    def Z(self):
        return self.__Z

    @property
    def nelec(self):
        return self.__nelec


class Molecule(object):

    def __init__(self, coordinates=None):
        self.__coordinates = coordinates
        self.nelec = None
        self.Z = None
        self.natom = None

    @property
    def coordinates(self):
        return self.__coordinates

    @coordinates.setter
    def coordinates(self, coords: list):
        depth = lambda l: isinstance(l, list) and max(map(depth, l)) + 1
        if depth(coords) != 2:
            raise Exception("Coordinates must be provided as a nested list of depth 2")
        else:
            atom_list = []
            for atom_coord in coords:
                print("Test")
                atom_coord = self.__check_coord(atom_coord)
                atom_label, atom_vec = atom_coord[0], atom_coord[1:]
                atom_list.append(Atom(atom_label, atom_vec))
            self.__coordinates = atom_list

    @staticmethod
    def __check_coord(coord):
        isnumber = lambda x: (type(x) == float or type(x) == int)
        if type(coord[0]) != str:
            raise Exception("First element must a string for an atomic label")
        if len(list(filter(isnumber, coord))) != 3 and len(coord) != 4:
            raise Exception("Each coordinate must be a list of length 4 with 1 string and 3 numbers")
        coord[0] = coord[0].upper()
        return coord


产生以下输出,

>>> mol = Molecule([['H', 0, 1, 1], ['O', -1, 0, 0], ['H', -1, 0, 1]])
>>> mol.coordinates
    [['H', 0, 1, 1], ['O', -1, 0, 0], ['H', -1, 0, 1]]
>>> mol2 = Molecule()
>>> mol2.coordinates =[['H', 0, 1, 1], ['O', -1, 0, 0], ['H', -1, 0, 1]]
    Test
>>> mol2.coordinates
    [<__main__.Atom object at 0x10c62c850>, <__main__.Atom object at 0x10c62c640>, <__main__.Atom object at 0x10c62c910>]

如何实现在对象的 init 上传递列表或在之后设置协调属性时将坐标设置为原子对象列表的行为?

【问题讨论】:

  • 使用ìsinstance进行类型检查
  • "Python 设置器不适用于实例化?"他们会这样做,但是您不会在 __init__ 的任何地方使用任何设置器,实际上,您似乎有意通过直接设置底层属性而不使用属性来避免它们。
  • 所以我们很清楚:问题是为什么 __init__ 方法在它说 self.__coordinates = coordinates 的地方不使用属性 coordinates 来设置值,但是mol2.coordinates = ... 的外部代码呢?可能是因为self.__coordinates 的代码没有使用属性的名称,即coordinates,而不是__coordinates
  • 另外:None 实际上是分子坐标的有效值吗?如果不是,在构造函数中将该参数设为可选的预期目标是什么?

标签: python python-3.x object oop instance


【解决方案1】:

当你做self.__coordinates = coordinates你直接设置__coordinates,你不调用setter

Molecule.__init__() 应该类似于

def __init__(self, coordinates=None):
    if coordinates is not None:
        self.coordinates = coordinates
    self.nelec = None
    self.Z = None
    self.natom = None

同样适用于您直接设置“内部”属性的任何其他情况

作为旁注,可能是您want to use single leading underscore,意思是“内部使用”,而不是双前导下划线。还有其他我会重构的东西,例如lambda函数的使用,你提出的一般Exception

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-23
    • 2014-07-19
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多