在Python中惰性地定义函数
这与其说是一个实际问题,不如说是一个理论问题。在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
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
可能有一个更干净的解决方案,使用元类,但我不确定我是否能够快速启动它。在任何情况下,我们所做的事情在语法上看起来都像是懒惰的、即时的成员函数生成
我有两个问题:
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_名称会更明智。不知道是什么让我忽视了这个解决方案。关于这个主题,“从一个裸名称引用动态创建一个函数”正是我想要做的!这绝对是有道理的,因为这是不可能的。这是一次学术活动。我想我最感兴趣的是,当我们调用同一模块中定义的裸名称时,在引擎盖下会发生什么。