【发布时间】:2018-12-12 04:59:21
【问题描述】:
我正在开发一个 python 项目,该项目需要我将某些对象的某些属性编译到数据集中。我目前使用的代码如下:
class VectorBuilder(object):
SIZE = 5
def __init__(self, player, frame_data):
self.player = player
self.fd = frame_data
def build(self):
self._vector = []
self._add(self.player)
self._add(self.fd.getSomeData())
self._add(self.fd.getSomeOtherData())
char = self.fd.getCharacter()
self._add(char.getCharacterData())
self._add(char.getMoreCharacterData())
assert len(self._vector) == self.SIZE
return self._vector
def _add(self, element):
self._vector.append(element)
但是,此代码有点不干净,因为向数据集添加/删除属性还需要正确调整 SIZE 变量。我什至有SIZE 变量的原因是,在创建数据集本身之前,需要在运行时知道数据集的大小。
我考虑过将用于构建数据集的所有函数的列表保留为字符串(如在attributes = ['getPlayer', 'fd.getSomeData', ...] 中),然后将build 函数定义为:
def build(self):
self._vector = []
for att in attributes:
self._vector.append(getattr(self, att)())
return self._vector
这将使我可以简单地访问大小len(attributes),并且我只需要编辑attributes,但我不知道如何使这种方法与链式函数调用一起使用,例如self.fd.getCharacter().getCharacterData()。
有没有更简洁的方法来完成我想做的事情?
编辑:
一些额外的信息和澄清是必要的。
- 我使用
__是因为我在网上阅读了一些不好的建议(本质上是说我应该对模块私有成员使用_,对类私有成员使用__)。我现在已将它们编辑为_属性。 - getter 是我正在使用的框架的一部分。
- 向量存储为私有类成员,因此我不必将其传递给构造方法,实际上这些方法比简单的
_add更多,还可以做一些其他的事情,例如规范化和bool->int转换在将元素添加到向量之前对其进行处理。 -
SIZE就目前而言,是一个真正的常数。它只在VectorBuilder的第一行被赋予一个值,并且在运行时从不改变。我意识到我没有在主帖中正确地澄清这一点,但新属性永远不会在运行时添加。我所说的调整将在编程时进行。例如,如果我想添加一个新属性,我需要在build函数中添加它,例如:self._add(self.fd.getCharacter().getAction().getActionData().getSpeed()),以及将
SIZE定义更改为SIZE = 6。 - 这些属性被编译成一个简单的 Python 列表(但可能会被一个 numpy 数组替换),然后作为输入向量传递给神经网络。但是,需要首先构建神经网络本身,这发生在任何数据可用之前(即在创建任何输入向量之前)。不过,为了成功构建,神经网络需要知道它将接收的输入向量的大小。这就是为什么
SIZE是必要的,也是assert声明的原因 - 确定我传递给网络的向量实际上是我声称要传递给它的大小。
我知道代码是非 Python 的,这就是我在这里的原因 - 代码有效,只是丑陋。
【问题讨论】:
-
你为什么使用
__属性?为什么要将值存储在列表中,而不是作为普通属性存储,或者至少存储在字典中?为什么你首先想要像getCharacter()这样的吸气剂?为什么当你唯一一次访问向量时,它会存储在任何地方,而是用你立即返回的全新值替换它?assert实际上是为了防止什么?您尝试做的每件事似乎都过于复杂且不符合标准,而且在不知道原因的情况下,很难说其中的某个特定元素是否特别过于复杂 -
按照约定,属性名称全为大写字母,如
SIZE,表示它是一个永远不会更改的常量值,但您提到“调整SIZE变量”。如果您要编写 Python 代码,我强烈建议您阅读(并关注)PEP 8 - Style Guide for Python Code** 建议。最后,正如@abarnert 所说,去掉属性名称上的__前缀,只需一个简单的_来表示某些东西是私有的就足够了。 -
@martineau 我认为这意味着
SIZE应该在类创建时创建(可能是通过一些模块级代码,因为我怀疑他会为此使用元类......但你永远不知道......)然后永远不会改变。如果是这样,它实际上是一个常数。例如,如果他使用普通的__slots__类,他可以编写一个设置cls.SIZE = len(cls.__slots__)的简单装饰器,即使从技术上讲,它是在type调用返回后分配的,你仍然可以称其为常量,对吧? -
我已编辑 OP 以尝试回答上述 cmets 中提出的问题。
标签: python python-3.x dynamic attributes getattr