下面的代码有效(它最终将通过SQL从数据库中提取记录),但我无法理解为什么下面代码中的assert
语句有效。
def build_row(table, cols):
"""Build a class that creates instances of specific rows"""
class DataRow:
"""Generic data row class, specialized by surrounding function"""
def __init__(self, data):
"""Uses data and column names to inject attributes"""
assert len(data)==len(self.cols)
for colname, dat in zip(self.cols, data):
setattr(self, colname, dat)
def __repr__(self):
return "{0}_record({1})".format(self.table, ", ".join(["{0!r}".format(getattr(self, c)) for c in self.cols]))
DataRow.table = table
DataRow.cols = cols.split()
return DataRow
确定'数据'的长度是多少?如何保证与'self.cols'的长度相同?有人请解释一下这种行为吗?
答案 0 :(得分:1)
data
函数返回的类时, build_row()
会得到一个值。
保证与self.cols
的长度相同;也许你永远不会实例化这个类,所以永远不会看到错误。
答案 1 :(得分:1)
如果您将self.cols
和self.table
的引用替换为self.__class__.cols
和self.__class__.table
,这可能对您更有意义。这种混淆是由于通过self
对象访问类属性就好像它们是实例属性一样,以及为什么我不特别喜欢这种编码习惯。在查看__init__
中的代码时,实例属性通常会分配给它们的值,因此立即看到读取 self.cols
的值的语句很不稳定 - 其中哎呀self.cols
初始化了吗?!另一方面,如果您将此断言更改为:
assert len(data)==len(self.__class__.cols)
然后更清楚的是,数据值列表应该与此DataRow实例的已定义列列表的长度相同。类属性cols
在类定义之后立即初始化,在此语句中:
DataRow.cols = cols.split()
在任何实例创建之前很久 - 这就是这个断言有效的原因。
此代码的编写者可能会考虑转换为更新的namedtuple
构造。
答案 2 :(得分:0)
定义DataRow
时,列名称将在变量self.cols
中设置。因此,当您实例化该类时,您应该填充每一列。
这就是为什么你需要两个长度相同的列表。否则你可能没有所有的属性。
它的完成方式是设置一个属性,其中列的名称不是最佳选项,因为如果您有一个名为cols
或table
或甚至{{1}的列},它可能会破坏你的代码。