Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中惰性地定义函数_Python_Monkeypatching_Inspect - Fatal编程技术网

在Python中惰性地定义函数

在Python中惰性地定义函数,python,monkeypatching,inspect,Python,Monkeypatching,Inspect,这与其说是一个实际问题,不如说是一个理论问题。在Python中,我们可以做一件非常丑陋的事情: import inspect import re class A(object): def __init__(self, *args, **kwargs): super(A, self).__init__(*args, **kwargs) self._name_cache = {} # Still want to be able to do proper lookups

这与其说是一个实际问题,不如说是一个理论问题。在Python中,我们可以做一件非常丑陋的事情:

import inspect
import re


class A(object):
  def __init__(self, *args, **kwargs):
    super(A, self).__init__(*args, **kwargs)
    self._name_cache = {}
    # Still want to be able to do proper lookups.
    self._old_get = self.__getattr__

  def __getattr__(self, n, *args, **kwargs):
    # Gets the name of the most local reference.
    frame = inspect.currentframe().f_back
    tmp = frame.f_locals.items() + frame.f_globals.items()
    for k, var in tmp.items():
      if isinstance(var, self.__class__):
        if var is self:
          name = k
          break
        else:
         assert 'Life' == 'Bad'
    patt = re.compile(r'^add_(\d+)$')
    if patt.search(n):
      # Add to the cached functions and return new "attribute."
      if n not in self._name_cache:
          exec('def %s(n):\n  return %s + n' % (n, patt.sub(r'\1', n)))
          exec('%s._name_cache["%s"] = %s' % (name, n, n))
          exec('print "Is it there? %s"' % str(n in self._name_cache))
        return self._name_cache[n]
      else:
        return self._old_get(n, *args, **kwargs)


a = A()
print a.add_2(3)  # Prints 5
可能有一个更干净的解决方案,使用元类,但我不确定我是否能够快速启动它。在任何情况下,我们所做的事情在语法上看起来都像是懒惰的、即时的成员函数生成

我有两个问题:

  • 我现在想知道是否有一种方法可以在全球范围内做到这一点。我只需要monkey patch
    inspect.current_frame().f_globals
    get()
    方法,但它的属性是只读的。是否有一个解释程序可写函数来管理顶级
    def
    ed函数的查找

  • 使用
    inspect
    模块还可以做哪些堕落的事情


  • 你能解释一下你到底想做什么吗?你是说你想要一个像
    blah()
    这样的裸名称引用来动态创建一个函数吗?这可能是不可能的。您可以编写一个伪模块对象,这样,如果您执行
    import foo
    ,那么
    foo.bar()
    会执行一些动态操作来获取所调用的函数,但是如果您试图访问同一模块中的一个空名称,那么这将不起作用。另外,我不明白您认为通过使用
    inspect
    实现可以获得什么好处。您可以编写一个普通的
    \uuuu getattr\uuuu
    来动态创建函数。如果某件事情不值得做,就不值得把它做好。感觉您应该在Perl中这样做。哈哈哈,我想我是在使用inspect()来确保用正确的名称定义函数。手动设置func_名称会更明智。不知道是什么让我忽视了这个解决方案。关于这个主题,“从一个裸名称引用动态创建一个函数”正是我想要做的!这绝对是有道理的,因为这是不可能的。这是一次学术活动。我想我最感兴趣的是,当我们调用同一个模块中定义的一个裸名称时,在引擎盖下会发生什么。你能解释一下你实际上想做什么吗?你是说你想要一个像
    blah()
    这样的裸名称引用来动态创建一个函数吗?这可能是不可能的。您可以编写一个伪模块对象,这样,如果您执行
    import foo
    ,那么
    foo.bar()
    会执行一些动态操作来获取所调用的函数,但是如果您试图访问同一模块中的一个空名称,那么这将不起作用。另外,我不明白您认为通过使用
    inspect
    实现可以获得什么好处。您可以编写一个普通的
    \uuuu getattr\uuuu
    来动态创建函数。如果某件事情不值得做,就不值得把它做好。感觉您应该在Perl中这样做。哈哈哈,我想我是在使用inspect()来确保用正确的名称定义函数。手动设置func_名称会更明智。不知道是什么让我忽视了这个解决方案。关于这个主题,“从一个裸名称引用动态创建一个函数”正是我想要做的!这绝对是有道理的,因为这是不可能的。这是一次学术活动。我想我最感兴趣的是,当我们调用同一模块中定义的裸名称时,在引擎盖下会发生什么。