1

我创建了一个 Atom 对象,如下所示:

class Atom(object):
    def __init__(self, symbol, x, y, z)
        self.symbol = symbol
        self.position = (x, y, z)

和一个Selection包含由某些标准选择的原子的类:

class Selection(object):
    def __init__(self, a_system, atom_list=[]):
        for atom in a_system:
            atom_list.append(atom)
        self.atom_list = atom_list

    def by_symbol(self, symbol):
        r_list = []
        for atom in self.atom_list:
            if atom.symbol is symbol:
                r_list.append(atom)
        self.atom_list = r_list

    def by_zrange(self, zmin, zmax):
        r_list = []
        for atom in self.atom_list:
            pos = atom.position[2]
            if pos > zmin and pos < zmax:
                r_list.append(atom)
        self.atom_list = r_list

如您所见,我可以说例如:

# my_system is a list of atoms objects
group = Selection(my_system)

然后说:

group.by_symbol('H')

我将在对象中group包含所有氢原子。然后,如果我这样做:

group.by_zrange(1, 2)

我将在对象group中包含 z 坐标在 1 和 2 之间的所有氢原子。

我有其他选择标准,但总的来说它们具有相同的结构,要知道:

r_list = []
for atom in self.atom_list:
    # Some criteria here
        r_list.append(atom)
self.atom_list = r_list

所以问题是:我能做些什么来避免为每个选择标准编写上述结构吗?

如果您知道有一种更简单的方法可以实现我的目的,我会很高兴听到它。

4

2 回答 2

1

您可能会使用内置的filter()函数,它会自动为您执行循环,并且可以说更优雅:

def by_symbol(self, symbol):
    res = filter(lambda atom: atom.symbol == symbol, self.atom_list)
    self.atom_list.extend(res)

如果您需要更复杂的过滤,您可能需要编写一个嵌套函数并传递它而不是lambda. 它应该是一个单参数函数并返回True正确的结果。

于 2013-11-02T00:46:21.140 回答
1

这是一个如何使用内置filter()函数的工作示例。

下面的代码还包括对您的类的一些其他增强以及对这个想法的一些修饰。特别注意by_symbol()andby_zrange()方法以 which 结尾,return self这使得打印结果以及将它们链接在一起变得更容易,如示例用法中所示。

from collections import namedtuple

Point = namedtuple('Point', 'x, y, z')

class Atom(object):
    def __init__(self, symbol, x, y, z):
        self.symbol = symbol
        self.position = Point(x, y, z)

    def __repr__(self):
        return '{name}({sym!r}, {pos.x}, {pos.y}, {pos.z})'.format(
            name=self.__class__.__name__, sym=self.symbol, pos=self.position)

class Selection(object):
    def __init__(self, a_system, atom_list=None):
        if atom_list is None:
            atom_list = []
        for atom in a_system:
            atom_list.append(atom)
        self.atom_list = atom_list

    def __repr__(self):
        return '{name}({atoms})'.format(
            name=self.__class__.__name__, atoms=self.atom_list)

    def _filter(self, func):
        return filter(func, self.atom_list)

    def by_symbol(self, symbol):
        self.atom_list = self._filter(lambda a: a.symbol == symbol)
        return self

    def by_zrange(self, zmin, zmax):
        def zrange(a):
            return zmin <= a.position.z <= zmax
        self.atom_list = self._filter(zrange)
        return self

使用示例:

my_system = [Atom('H', 0, 1, 2),
             Atom('N', 3, 4, 5),
             Atom('C', 6, 7, 8),
             Atom('H', 9, 10, 11),]

group = Selection(my_system)
print group
print group.by_symbol('H')
print group.by_zrange(1, 2)
print
group = Selection(my_system)
print group.by_symbol('H').by_zrange(1, 2)

输出:

Selection([Atom('H', 0, 1, 2), Atom('N', 3, 4, 5), Atom('C', 6, 7, 8),
           Atom('H', 9, 10, 11)])
Selection([Atom('H', 0, 1, 2), Atom('H', 9, 10, 11)])
Selection([Atom('H', 0, 1, 2)])

Selection([Atom('H', 0, 1, 2)])
于 2013-11-02T03:25:42.953 回答