在Python中将函数视为对象

在Python中将函数视为对象,python,Python,我不确定标题是否与我将要问的问题相匹配,但如果您知道一个更好的标题,可以帮助大家,请随时更新 假设我们有以下定义: >>> def helloFunction(): name = "Hello World" 因此,当我输入以下代码时,返回一个空字典 >>> helloFunction.__dict__ {} 我不确定这是否应该是这样,但让我们继续。有趣的是,我可以做到以下几点: >>> helloFunction.hell

我不确定标题是否与我将要问的问题相匹配,但如果您知道一个更好的标题,可以帮助大家,请随时更新

假设我们有以下定义:

>>> def helloFunction():
        name = "Hello World"
因此,当我输入以下代码时,返回一个空字典

>>> helloFunction.__dict__
{}
我不确定这是否应该是这样,但让我们继续。有趣的是,我可以做到以下几点:

>>> helloFunction.hello = "world"
>>> helloFunction.__dict__
{'hello': 'world'}
当我输入下面的代码时,它告诉我helloFunction实际上是一个函数

>>> type(helloFunction)
<type 'function'>

所以看来
函数
确实是一种类类型?

部分引自学习Python(Mark Lutz):

像Python中的其他东西一样,函数只是对象;他们是 在程序执行时显式记录在内存中。事实上 除了调用之外,函数还允许附加任意属性 记录信息供以后使用

在语言中添加了“函数属性”。如果你想了解所有的官方理由,你可以阅读这篇文章。现实情况可以归结为引言中的这句话:

func_doc具有 有趣的特性是函数中有特殊的语法(和 方法)用于隐式设置属性的定义这个 便利性被一次又一次地利用,超载 具有附加语义的文档字符串。

我的。人们使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;提供一个真正的地方来这样做似乎更为自然

至于一些更具体的问题:

函数是对象吗

哦,是的。函数是python中的一级对象。您可以随意将对它们的引用作为参数传递给其他函数。如果他们不是一流的,我不能这样做:

def increment(x):
    return x+1

map(increment,[1,2,3]) # python2 `map`, for brevity
Out[3]: [2, 3, 4]
我在哪里需要这种功能

你通常不会。不经常。但是,当您想要存储有关函数的元数据时,它可能很有用

>>> type(helloFunction)
<type 'function'>
假设我想用一个装饰器包装一个函数,该装饰器记录调用它的次数。这很容易,因为我们可以将这些信息塞进函数的
\uuu dict\uuu

def count_calls(func):
    def _inner(*args, **kwargs):
        before = getattr(func,'times_called',0)
        func.times_called = before + 1
        print('func has now been called {} times'.format(func.times_called))
        return func(*args,**kwargs)
    return _inner

@count_calls
def add(x,y):
    return x+y

add(3,4)
func has now been called 1 times
Out[7]: 7

add(2,3)
func has now been called 2 times
Out[8]: 5

函数是一个对象,与Python中的大多数对象一样,它有一个字典。我在野外看到的一个使用示例是web框架,它用于指示要访问web的方法:

import cherrypy
class HelloWorld(object):
    def index(self):
        return "Hello World!"
    index.exposed = True
当访问路径时,调度器可以检查相应的处理程序方法是否将其
exposed
属性设置为
True
,并对其作出响应,从而允许在控制器上安全地定义可访问和私有方法

我见过的另一个用法是一个计算函数调用次数的装饰器:

def call_counter(fn):
    fn.count = 0
    def _fn(*args, **kwargs):
        fn.count += 1
        return fn(*arg, **kwargs)
    return _fn

Python中的函数被视为一级对象,这意味着它们是对象。事实上,如果
x.\uu调用\uu
方法存在,那么
x()
是一个合法的调用。
def call_counter(fn):
    fn.count = 0
    def _fn(*args, **kwargs):
        fn.count += 1
        return fn(*arg, **kwargs)
    return _fn