【问题标题】:How to create cross-module, on-thy-fly variable name in python?如何在 python 中创建跨模块、即时变量名?
【发布时间】:2013-03-14 18:44:03
【问题描述】:

我想做的是创建一个带有类的模块;和一个函数,它是该类的接口;以及此函数中的动态变量名,它指向该类的实例。这个函数和类本身应该在一个单独的模块中,它们的用法应该在不同的python文件中。

我认为,当您查看我的代码时,更容易理解我想要做什么:

这是first.py

class FirstClass:
    def setID(self, _id):
        self.id = _id
    def func(self):
        pass

# An 'interface' for FirstClass
def fst(ID):
    globals()['%s' % ID] = FirstClass(ID)
    return globals()['%s' % ID]

现在,如果我在first.py 中直接调用fst('some_text'),结果几乎就是我梦寐以求的,因为以后,任何时候我写some_text.func(),它都会调用func(),因为some_text 指向 FirstClass 的一个实例。

但是,当second.py 是这样的:

from first import fst

fst('sample_name')
sample_name.func()

那么python给出的答案是这样的:

NameError: name 'sample_name' is not defined.

这有点合理。所以我的问题是:是否有“更漂亮”的方法或完全不同的方法来做到这一点?还是我必须更改代码中的一些小东西才能完成这项工作?

谢谢!

【问题讨论】:

  • 你认为你为什么需要这个?
  • 全球是邪恶的。永远不要使用全局。了解如果外部读者阅读您的程序,他将永远无法理解此变量是如何设置的。永远不要使用魔法,或者很好地记录它。 explicit is better than implicit : Python 之禅
  • @BurhanKhalid:实际上我正在为设计师开发一个小型 GUI 框架,我认为只调用一个函数(例如 rectangle())而不是像 @ 那样创建整个对象会非常好987654334@.
  • @omoone:是的,我知道 Python 之禅,我每天都在使用它,但就我而言,关键是:隐藏它的来源,因为我正在做的是一个小而设计师的有限框架。

标签: python class interface module on-the-fly


【解决方案1】:

不要在函数中将其设置为全局。相反,只需从函数返回新实例并将全局设置为该返回值:

def fst(ID):
    return FirstClass(ID)

然后在second.py:

sample_name = fst('sample_name')

如果在函数内部,则声明 sample_nameglobal

globals() 方法只返回调用它的模块的全局变量。它永远不会返回任何调用函数的全局变量。如果您觉得需要访问这些全局变量,请重新考虑您的代码,您很少需要更改调用函数的全局变量。

如果您绝对确定您需要访问调用者全局变量,您需要开始使用堆栈帧进行破解:

# retrieve caller globals
import sys
caller_globals = sys._getframe(1).f_globals

但是,正如sys._getframe() 的文档所述:

CPython 实现细节:此函数应仅用于内部和专用目的。不保证在 Python 的所有实现中都存在。

【讨论】:

  • 是的,我知道,(顺便说一句:感谢您的快速回复)但是,这实际上是我试图避免的:将“名称”写两次。因为它也可能是一个解决方案:sample_name = FirstClass('sample_name')
  • @PeterVaro:我添加了更多关于如何执行此操作的详细信息。这类似于给你一把枪,它永远瞄准包含你脚的区域,所以如果你扣动扳机并击中所说的肢体,你就会被警告! :-)
  • 你的意思是如果我将我的“接口函数”复制到 second.py 中?因为我也想避免这种情况。这就是我要寻找的:将类及其接口分离到不同的模块,使用此功能的用户永远不应该使用sys 等等。这些用户需要import mymodule,仅此而已。
  • 不,我不是那个意思。 sys._getframe(1) 代码将存在于 first.pycaller_globals 中,然后将指向 second.py 全局变量(如果这是您调用 fst() 的位置)。
  • 我理解你在做什么,但我认为你需要远离这个想法。您已经可以总是为 store 对象提供不同的名称,所以使用 spam = fst('ham')非常好(所以将 ham 接口存储在本地名称 spam ) 例如,在 Python 中。仅通过调用函数来强制将接口对象添加到全局变量的想法是隐含和意外的行为。这违背了 Python 哲学(显式优于隐式)。
猜你喜欢
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
  • 2017-06-02
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
相关资源
最近更新 更多