在python中,函数是第一类对象。可以调用一个类。所以你可以用类替换一个函数。但是你能使一个函数表现得像一个类吗?你能在函数中添加和删除属性或调用内部函数(然后调用方法)吗?
我通过代码检查找到了一种方法。
import inspect
class AddOne(object):
"""class definition"""
def __init__(self, num):
self.num = num
def getResult(self):
"""
class method
"""
def addOneFunc(num):
"inner function"
return num + 1
return addOneFunc(self.num);
if __name__ == '__main__':
two = AddOne(1);
two_src = '\n'.join([line[4:] for line in inspect.getsource(AddOne.getResult).split('\n')])
one_src = '\n'.join([line[4:] for line in two_src.split('\n')
if line[:4] == ' ' and line[4:8] == ' ' or line[4:8] == 'def '])
one_co = compile(one_src, '<string>', 'exec')
exec one_co
print addOneFunc(5)
print addOneFunc.__doc__
但是有没有办法以更直接的方式访问类中定义的局部变量和函数?
修改
问题是如何访问python的内部结构以获得更好的理解。当然,我不会在正常编程中这样做。当我们在python中讨论私有变量时出现了这个问题。我认为这是违背语言哲学的。所以有人想出了上面的例子。目前看来他是对的。如果没有inspect模块,则无法访问函数内部的函数,从而将此函数设置为私有。有了co_varnames,我们非常接近,因为我们已经拥有了该函数的名称。但名称空间字典在哪里保存名称。如果您尝试使用
getResult.__dict__
它是空的。我喜欢的是来自python的答案,如
function addOneFunc at <0xXXXXXXXXX>
答案 0 :(得分:3)
您可以将函数视为仅实现__call__
的类的实例,即
def foo(bar):
return bar
大致相当于
class Foo(object):
def __call__(self, bar):
return bar
foo = Foo()
函数实例具有__dict__
属性,因此您可以自由地向它们添加新属性。
例如,可以使用向函数添加属性来实现memoization装饰器,它会缓存以前对函数的调用:
def memo(f):
@functools.wraps(f)
def func(*args):
if args not in func.cache: # access attribute
func.cache[args] = f(*args)
return func.cache[args]
func.cache = {} # add attribute
return func
请注意,此属性也可以在内部函数中访问,但在 函数之后才能定义 。
你可以这样做:
>>> def foo(baz):
def multiply(x, n):
return x * n
return multiply(foo.bar(baz), foo.n)
>>> def bar(baz):
return baz
>>> foo.bar = bar
>>> foo.n = 2
>>> foo('baz')
'bazbaz'
>>> foo.bar = len
>>> foo('baz')
6
(虽然可能没人会感谢你!)
但请注意,multiply
未成为foo
的属性,无法从函数外部访问:
>>> foo.multiply(1, 2)
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
foo.multiply(1, 2)
AttributeError: 'function' object has no attribute 'multiply'
另一个问题是正好你正在尝试做什么:
>>> import inspect
>>> import new
>>> class AddOne(object):
"""Class definition."""
def __init__(self, num):
self.num = num
def getResult(self):
"""Class method."""
def addOneFunc(num):
"inner function"
return num + 1
return addOneFunc(self.num)
>>> two = AddOne(1)
>>> for c in two.getResult.func_code.co_consts:
if inspect.iscode(c):
print new.function(c, globals())
<function addOneFunc at 0x0321E930>
答案 1 :(得分:2)
不确定以下是否是您正在考虑的问题,但您可以这样做:
>>> def f(x):
... print(x)
...
>>> f.a = 1
>>> f.a
1
>>> f(54)
54
>>> f.a = f
>>> f
<function f at 0x7fb03579b320>
>>> f.a
<function f at 0x7fb03579b320>
>>> f.a(2)
2
因此,您可以为函数指定属性,这些属性可以是变量或函数(请注意,为简单起见,选择了f.a = f
;当然,您可以将f.a
指定给任何函数。)
如果你想访问函数内部的局部变量,我认为它更难,你可能确实需要恢复内省。以下示例使用func_code
属性:
>>> def f(x):
... a = 1
... return x * a
...
>>> f.func_code.co_nlocals
2
>>> f.func_code.co_varnames
('x', 'a')
>>> f.func_code.co_consts
(None, 1)