【问题标题】:python function that changes itself to list将自身更改为列表的python函数
【发布时间】:2013-10-21 08:33:20
【问题描述】:

所以我正在研究一个有趣的化学项目,我有一个函数可以从文本文件中初始化一个列表。我想做的是让函数用列表替换自己。所以这是我的第一次尝试,随机会或不会起作用,我不知道为什么:

def periodicTable():
    global periodicTable
    tableAtoms = open('/Users/username/Dropbox/Python/Chem Project/atoms.csv','r')
    listAtoms = tableAtoms.readlines()
    tableAtoms.close()
    del listAtoms[0]
    atoms = []
    for atom in listAtoms:
        atom = atom.split(',')
        atoms.append(Atom(*atom))
    periodicTable = atoms

它以这种方式被调用:

def findAtomBySymbol(symbol):
    try:
        periodicTable()
    except:
        pass
    for atom in periodicTable:
        if atom.symbol == symbol:
            return atom
    return None

有没有办法让它工作?

【问题讨论】:

  • 不要让函数用列表替换自己。使用列表和函数是不同的——如何调用列表或切片函数? - 并且尝试以不同的方式处理这种情况是混乱的,正如使用代码所示。此外,“随机”不是一个好的错误描述 - 不吞下所有异常可能会提供更好的失败指示。
  • 您可能对"memoization functions" 感兴趣,尽管我自己会这样做:periodicTable = loadPeriodicTable()(比如在程序开始时),因为这里没有明显的缓存或记忆需求。
  • @user2864740 是的,我想过这样做,但我真的很喜欢探索 python 的复杂性,这让这里的一些用户很烦恼。
  • 然后查看显示的各种记忆/缓存答案之一。然而,使用记忆/缓存相同的名称总是绑定到一个函数。因此,它总是像函数一样使用 - for atom in periodicTable() -(带有函数调用和),不同之处在于后续调用返回缓存的数据,而无需从文件中重新加载。

标签: python list function


【解决方案1】:

不要那样做。正确的做法是使用装饰器来确保函数只执行一次并缓存返回值:

def cachedfunction(f):
    cache = []
    def deco(*args, **kwargs):
        if cache:
            return cache[0]
        result = f(*args, **kwargs)
        cache.append(result)
        return result
    return deco

@cachedfunction
def periodicTable():
    #etc

也就是说,没有什么可以阻止您在调用函数后替换它本身,因此您的方法通常应该有效。我认为它没有的原因是因为在您将结果分配给periodicTable 之前引发了异常,因此它永远不会被替换。尝试移除 try/except 块或将毯子 except 替换为 except TypeError 看看究竟会发生什么。

【讨论】:

  • 不错。更多的前期工作,但与可变默认值的混淆更少。 :)
  • @EthanFurman 是的,这具有可重用并保留原始函数签名的优点。如果它只是一个小的一次性脚本,您的解决方案可能更可取......
  • 吹毛求疵:它只保留原始签名,因为没有一个;如果有的话,保存起来会复杂得多。如果您想查看血腥细节,请查看Michele Simianoto's Decorator module
  • @EthanFurman 是的,当您考虑自省时,这是另一回事。我的意思是当你用错误的签名调用它时你仍然会得到一个TypeError,我通常认为这已经足够好了。
【解决方案2】:

这是非常糟糕的做法。

最好让你的函数记住它是否已经加载了表:

def periodicTable(_table=[]):
    if _table:
        return _table
    tableAtoms = open('/Users/username/Dropbox/Python/Chem Project/atoms.csv','r')
    listAtoms = tableAtoms.readlines()
    tableAtoms.close()
    del listAtoms[0]
    atoms = []
    for atom in listAtoms:
        atom = atom.split(',')
        atoms.append(Atom(*atom))
    _table[:] = atoms

前两行检查表是否已经加载,如果有则直接返回。

【讨论】:

  • 这行不通。最后对_table 的赋值不会超出函数范围。相反,需要修改列表(最初由 _table 命名)。
  • @user2864740 是对的,应该是_table.extend(atoms)_table[:] = atoms - 您不能更改默认参数的引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 2020-12-07
  • 1970-01-01
  • 2020-01-24
相关资源
最近更新 更多