Joh*_*ank 3 python class function
在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__
Run Code Online (Sandbox Code Playgroud)
但是有没有办法以更直接的方式访问类中定义的局部变量和函数?
编辑
问题是如何访问python的内部结构以获得更好的理解。当然,我不会在正常编程中这样做。当我们讨论 Python 中的私有变量时,问题就出现了。我的观点是这违背了语言的哲学。所以有人想出了上面的例子。目前看来他是对的。如果没有检查模块,您将无法访问函数内部的函数,从而将此函数设为私有。使用 co_varnames 我们非常接近,因为我们已经有了函数的名称。但是保存名称的命名空间字典在哪里。如果您尝试使用
getResult.__dict__
Run Code Online (Sandbox Code Playgroud)
它是空的。我喜欢的是来自 python 的答案,例如
function addOneFunc at <0xXXXXXXXXX>
Run Code Online (Sandbox Code Playgroud)
您可以将函数视为仅实现 的类的实例__call__,即
def foo(bar):
return bar
Run Code Online (Sandbox Code Playgroud)
大致相当于
class Foo(object):
def __call__(self, bar):
return bar
foo = Foo()
Run Code Online (Sandbox Code Playgroud)
函数实例有一个__dict__属性,因此您可以自由地向它们添加新属性。
例如,可以使用向函数添加属性来实现记忆装饰器,该装饰器缓存先前对函数的调用:
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
Run Code Online (Sandbox Code Playgroud)
请注意,此属性也可以在函数内部访问,尽管它只能在函数之后才能定义。
因此,您可以执行以下操作:
>>> 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
Run Code Online (Sandbox Code Playgroud)
(虽然可能没有人会感谢你!)
但是请注意,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'
Run Code Online (Sandbox Code Playgroud)
另一个问题正是您想要做的:
>>> 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>
Run Code Online (Sandbox Code Playgroud)