【问题标题】:Python assign function to dict valuePython将函数分配给dict值
【发布时间】:2010-12-22 10:01:53
【问题描述】:

我正在尝试编写一个基于字典值打开文件的脚本。对于每个键/值,它会根据该值的名称打开一个文件,并将该文件分配给该值的名称(我认为这里出错了)。到目前为止,它使用正确的名称为我打开了文件,这样就可以了。但是,我认为我分配 open(file) 函数的名称是错误的,因为我的函数的其余部分不再打开文件,而且我无法关闭它们。 我的脚本示例:

filelist=[]
codeconv={"agt":"r1p1d", "aga":"r2p1d"}
for value in codeconv.values():
    value=open("c:\Biochemistry\Pythonscripts\Splittest\split"+value+".txt", 'w')
    filelist.append(value)

"Here I do something with the files"

for f in filelist:
    f.close()

所以问题是,如何将 open(file) 函数分配给正确的名称? (这里以 r1p1d 和 r2p1d 为例)我以后如何再次调用它们?

我现在得到的错误是: AttributeError:'str'object 没有属性'close' 在 f.close() 行上。

编辑:它现在可以按照我的意愿工作,使用以下代码:(为了清楚起见,我现在还包括了“我在这里做某事”部分)

result=open("C:\\Biochemistry\\Pythonscripts\\Illuminaresults.txt", "r")
filelist=[]

codeconv={"agt":"r1p1d", "aga":"r2p1d"}        
opened_files={}
for key, value in codeconv.items():
    filename="c:\Biochemistry\Pythonscripts\Splittest\split"+value+".txt"
    file=open(filename, 'w')
    opened_files.update({key: file})

for line in result:
    if line[0]==">":
        lastline=line
    if line[0:3] in codeconv and len(line)==64:
        f=opened_files[line[0:3]]
        f.write(lastline+line)
    else: continue 

for f in opened_files.values():
    f.close()

result.close()

虽然当我尝试编写脚本的下一部分时,我现在遇到了另一个问题,但这可能是另一个问题,因为它给出了一个与这部分无关的 Windowserror。感谢大家的帮助!

【问题讨论】:

  • filelist 声明在哪里?
  • filelist 在此之前声明,我的脚本中只有 filelist=[]
  • 不要使用file 作为变量。它会隐藏一个内置类型。

标签: python function dictionary


【解决方案1】:

如果我理解你的话,你想从字典中动态创建一些变量,以便你可以将它们分配给打开的文件,是吗???!!!!!!

我会建议使用像这样的另一本字典:

codeconv={"agt":"r1p1d", "aga":"r2p1d"}
opened_files = {}

for key, value in codeconv.items():
    file_name = "c:\Biochemistry\Pythonscripts\Splittest\split%s.txt" % value
    file=open(file_name, 'w')
    opened_files.update({key: file})

您现在可以像这样从字典中访问您打开的文件:

f = opened_files['agt'] 
f.read()
....

你后面的代码是这样的:

for f in opened_files.values():
    f.close()

【讨论】:

  • 你理解的没错。在“我在这里做某事”中,我想根据第一个字典中的键访问我的文件。你有 f=opened_files['r1p1d'] ,可以在那里做 f=opened_files[codeconv['agt']] 吗?
  • @Max:是的,当然,我已经编辑了我的答案,现在我使用字典键而不是值。
  • 如果我这样做,那么:codeconv={"agt":"r1p1d", "aga":"r2p1d"} #expand to all tags opens_files={} for value in codeconv.values( ): filename="c:\Biochemistry\Pythonscripts\Splittest\split"+value+".txt" file=open(filename, 'w') opens_files.update({value: file})for f in opens_files.values() : f.close() 它仍然没有正确关闭文件。哦,我如何使 cmets 中的代码不那么难看:S
  • @Max:你是什么意思:它仍然没有正确关闭文件?文件已关闭,不!而且我不认为这丑陋:) 甚至 python 命名空间都被实现为字典,所以我们只是在这里做同样的事情,而不是在我们刚刚在此处创建命名空间的全局或本地命名空间中创建变量;如果你不喜欢这种方式,希望这能给你一个更好的主意:)
  • 我并不是说代码本身很丑,我只是说这里的 cmets 中的格式很丑,因为你不能插入空格 ;-) 我的意思是它们没有正确关闭,因为如果我稍后尝试重新打开它们,我会收到错误“WindowsError:[Error32] 该进程无法访问该文件,因为它正在被另一个进程使用”...
【解决方案2】:

我会提醒不要在第一个循环中重复使用“值”,以清楚起见和将来可能引入的错误。

但是,您发布的代码实际上是有效的,因此显然还有其他一些我们无法在此处诊断的情况。您需要做的是在尝试关闭其中的文件句柄之前检查filelist 的内容。这可能会让你找到答案。

【讨论】:

  • 这正是我的问题,但我的措辞可能不正确。我不想重用“值”,我希望将实际值(r1p1d、r2p1d 等)用作分配给打开函数的名称,而不是“值”。
  • 这之后文件列表的内容是:[, ]
  • @Max 在这种情况下,AttributeError 与您发布的代码无关。对于您想做的事情,您可能应该将它们作为d[value] = open(value, 'w') 存储在字典中。
【解决方案3】:

也许您想将元组附加到filelist,以便名称与文件对象相关联

codeconv={"agt":"r1p1d", "aga":"r2p1d"}
for value in codeconv.values():
    f=open("c:\Biochemistry\Pythonscripts\Splittest\split"+value+".txt", 'w')
    filelist.append((value, f))

"Here I do something with the files"

for name, f in filelist:
    f.close()

【讨论】:

    【解决方案4】:

    我在您的代码中看不到问题,也许不是粘贴的部分? (在filelist 或片段中)。

    但无论如何,我会重写它以避免将相同的变量value 用于两个不同的事物:

    filelist = []
    codeconv={"agt":"r1p1d", "aga":"r2p1d"}
    for file_id in codeconv.values():
        f = open("c:\Biochemistry\Pythonscripts\Splittest\split"+file_id+".txt", 'w')
        filelist.append(f)
    
    "Here I do something with the files"
    
    for f in filelist:
        if isinstance(f, str):
            print "WARNING: Expected file handle, got string:", f
        else:
            f.close()
    

    (我还添加了一些故障排除代码)

    【讨论】:

    • 这可能适用于打开和关闭它们,但这不允许我稍后调用文件来写入它们,只有最后一个作为 f 一直被重用,不是吗?
    • 您仍然可以访问filelist 中的文件(您不想在这些循环之外使用value 或file_id 或f(在我的版本中))跨度>
    【解决方案5】:

    文件已打开 - 您的 filelist 对象包含打开的文件对象,您可以迭代(例如,使用 for line_of_text in filelist[0]:)或调用其他函数(请参阅 dir(file) 了解其他成员)。

    您可以通过分配一个 lambda 并稍后调用它来延迟打开文件,例如:

    for value in codeconv.values():
        value2 = lambda: open(complete_filename)
        filelist.append(value2)
    
    my_file_object = filelist[0]()
    

    您可能更喜欢将这些存储在字典中:

    for value in codeconv.itervalues():
        filedict[value] = lambda: open(complete_filename)
    
    my_file_object = filedict["r1p1d"]()
    

    或者如果您真的想要创建新变量(我强烈建议不要这样做,但既然你问了):

    for value in codeconv.itervalues():
        globals()[value] = open(complete_filename)
        # or
        #globals()[value] = lambda: open(complete_filename)
        # if you prefer
    

    最后,您按原样关闭文件(如果您使用字典,则将 filedict.itervalues() 替换为 filelist)。


    (显然,您需要将上面示例中的 complete_filename 替换为您计算实际文件名的方式。我不应该这么说,但我经常因为忽略这些细节而被刺痛。)

    【讨论】:

      【解决方案6】:

      您不是在分配函数,而是在分配返回值。在这种情况下,它显然是一个字符串而不是一个文件对象,这有点令人惊讶。您是否对“我在这里做某事”部分中的文件列表做任何事情?

      [编辑] 好的,听起来你想要一个键/文件对象之间的字典(带有示例用法)。

      codeconv={"agt":"r1p1d", "aga":"r2p1d"}
      filedict = {key, open("c:\Biochemistry\Pythonscripts\Splittest\split"+value+".txt", 'w')
                  for key, value in codeconv.iteritems()}
      
      #Here I do something with the files
      filedict["agt"].write("foo")
      filedict["aga"].write("bar")
      
      for f in filedict.values():
          f.close()
      

      【讨论】:

      • 不,这就是我对文件列表所做的一切。在“我在这里做某事”部分,我试图对打开的文件做一些事情,这就是为什么它们需要不同的名称而不是每次都被覆盖为“值”。
      猜你喜欢
      • 1970-01-01
      • 2023-03-14
      • 2017-09-08
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 1970-01-01
      • 2011-07-05
      • 1970-01-01
      相关资源
      最近更新 更多