简体   繁体   English

python中的函数可以像类一样表现吗?

[英]Can a function in python behave like a class?

In python a function is a first class object. 在python中,函数是第一类对象。 A class can be called. 可以调用一个类。 So you can replace a function with a class. 因此,您可以将函数替换为类。 But can you make a function behave like a class? 但是,您可以使函数的行为像类吗? Can you add and remove attributes or call inner functions( then called methods) in a function? 您可以在函数中添加和删除属性或调用内部函数(然后称为方法)吗?

I found a way to do this via code inspection. 我找到了一种通过代码检查来做到这一点的方法。

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__

But is there a way to access the local variables and functions defined in a class in a more direct way? 但是,有没有一种方法可以更直接地访问在类中定义的局部变量和函数呢?

EDIT 编辑

The question is about how to access the inner structure of python to get a better understanding. 问题是关于如何访问python的内部结构以获得更好的理解。 Of course I wouldn't do this in normal programming. 当然,在常规编程中我不会这样做。 The question arose when we had a discussion about private variables in python. 当我们讨论python中的私有变量时,出现了问题。 My opinion was this to be against the philosophy of the language. 我认为这与语言哲学背道而驰。 So someone came up with the example above. 因此有人提出了上面的示例。 At the moment it seems he is right. 目前看来他是对的。 You cannot access the function inside a function without the inspect module, rendering this function private. 没有检查模块,就无法访​​问函数内部的函数,从而使该函数私有。 With co_varnames we are awfully close because we already have the name of the function. 使用co_varnames,我们已经非常接近了,因为我们已经有了函数的名称。 But where is the namespace dictionary to hold the name. 但是存放名称的名称空间字典在哪里。 If you try to use 如果您尝试使用

getResult.__dict__

it is empty. 它是空的。 What I like to have is an answer from python like 我想要的是python这样的答案

function addOneFunc at <0xXXXXXXXXX>

You can consider a function to be an instance of a class that only implements __call__ , ie 您可以将函数视为仅实现__call__的类的实例,即

def foo(bar):
    return bar

is roughly equivalent to 大致相当于

class Foo(object):

    def __call__(self, bar):
        return bar

foo = Foo()

Function instances have a __dict__ attribute, so you can freely add new attributes to them. 函数实例具有__dict__属性,因此您可以自由地向它们添加新属性。


Adding an attribute to a function can be used, for example, to implement a memoization decorator, which caches previous calls to a function: 例如,可以将一个属性添加到一个函数中,以实现一个记忆修饰器,该记忆器会缓存先前对该函数的调用:

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

Note that this attribute can also be accessed inside the function, although it can't be defined until after the function. 请注意,此属性也可以函数内部访问,尽管要等到函数之后才能定义。


You could therefore do something like: 因此,您可以执行以下操作:

>>> 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

(although it's possible that nobody would thank you for it!) (尽管没有人会为此而感激您!)

Note, however, that multiply , which was not made an attribute of foo , is not accessible from outside the function: 但是请注意,不能从函数外部访问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'

The other question addresses exactly what you're trying to do: 另一个问题正是要解决的问题:

>>> 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>

Not sure if the following is what you're thinking about, but you can do this: 不知道以下是您在考虑什么,但是您可以执行以下操作:

>>> 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

So you can assign attributes to a function, and those attributes can be variables or functions (note that fa = f was chosen for simplicity; you can assign fa to any function of course). 因此,您可以将属性分配给函数,并且这些属性可以是变量或函数(请注意,为简单起见,选择了fa = f ;您当然可以将fa分配给任何函数)。

If you want to access the local variables inside the function, I think then it's more difficult, and you may indeed need to revert to introspection. 如果您想访问该函数内部的局部变量,那么我认为这会更加困难,并且您确实可能需要恢复自省。 The example below uses the func_code attribute: 下面的示例使用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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM