3

我显然在学习如何正确使用类时遇到了一些麻烦。我希望下面的代码循环遍历一组文件(它确实如此),将元素添加到一个集合中(它确实如此),并在它移动到一个新文件时重新开始该集合(它没有)。我破解下面代码的方式,我希望它每次都返回一个空集file.terminals,因为我相信每个集合都是类的新实例的唯一属性SrcFile。显然,我错了。实际发生的是,由第一个文件创建的终端集对于列表中的所有后续文件仍然存在(并被添加到),尽管其他属性(例如file.namefile.seqlength()) 随文件适当更改。有人可以解释为什么它会以这种方式工作以及如何创建我期望的行为吗?预先感谢您对初学者的无知的耐心。

class SrcFile:
   terminals = set([])
   def __init__(self, which):
      self.name = which
   def seqlength(self):
      with open(self.name) as file:
         linecounter = 0
         for line in file:
            linecounter += 1
            if linecounter == 3:
               return int(line.split()[0])
               break

class Record(SrcFile):
   def terminal(self):
      record = self.name
   def terminal(self):
      record = self.name
      return record.split()[0]

for f in files:
   file = SrcFile(f)
   print(file.name, file.seqlength(), file.terminals)

   with open(f) as f:
      recordline = re.compile(r"^([A-Z]{5})\s{3}")
      for line in f:
         if recordline.match(line):
            record = Record(line)
            if record.terminal() in file.terminals:
               pass
            else:
               file.terminals.add(record.terminal())
4

2 回答 2

4

terminals在类声明中定义,而不是在为类__init__的每个新实例执行的函数中定义。

基本上,terminals为整个类初始化,而不是为类的每个实例:

>>> SrcFile.terminals
set([])

注意我跑了SrcFile.terminals, not SrcFile().terminals,这意味着这SrcFile是对类的引用,而不是类的实例。

您将类似的变量放在__init__函数内部以使它们特定于实例:

class SrcFile(object):
  def __init__(self, which):
    self.name = which
    self.terminals = set([])
于 2012-06-19T23:57:38.293 回答
3

通过terminals = set([])在类本身中定义,它在定义类时创建一次,而不是在创建实例时创建。

为避免这种情况,请将其删除并将以下内容添加到您的__init__方法中:

self.terminals = set()
于 2012-06-19T23:55:26.390 回答