没有多少人知道这个特性,但是Python的函数(和方法)可以有属性。见:

>>> def foo(x):
...     pass
...     
>>> foo.score = 10
>>> dir(foo)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name', 'score']
>>> foo.score
10
>>> foo.score += 1
>>> foo.score
11

在Python中,这个特性可能的用途和滥用是什么?我所知道的一个很好的用法是PLY使用docstring将语法规则与方法关联起来。但是自定义属性呢?有充分的理由使用它们吗?


当前回答

你可以用JavaScript的方式做对象…这没有任何意义,但它是有效的;)

>>> def FakeObject():
...   def test():
...     print "foo"
...   FakeObject.test = test
...   return FakeObject
>>> x = FakeObject()
>>> x.test()
foo

其他回答

你可以用JavaScript的方式做对象…这没有任何意义,但它是有效的;)

>>> def FakeObject():
...   def test():
...     print "foo"
...   FakeObject.test = test
...   return FakeObject
>>> x = FakeObject()
>>> x.test()
foo

我通常使用函数属性作为注释的存储。假设我想用c#的风格编写(表明某个方法应该是web服务接口的一部分)

class Foo(WebService):
    @webmethod
    def bar(self, arg1, arg2):
         ...

然后我就可以定义

def webmethod(func):
    func.is_webmethod = True
    return func

然后,当一个webservice调用到达时,我查找方法,检查底层函数是否有is_webmethod属性(实际值无关紧要),如果方法不存在或不打算通过web调用,则拒绝服务。

函数属性可用于编写轻量级闭包,将代码和相关数据包装在一起:

#!/usr/bin/env python

SW_DELTA = 0
SW_MARK  = 1
SW_BASE  = 2

def stopwatch():
   import time

   def _sw( action = SW_DELTA ):

      if action == SW_DELTA:
         return time.time() - _sw._time

      elif action == SW_MARK:
         _sw._time = time.time()
         return _sw._time

      elif action == SW_BASE:
         return _sw._time

      else:
         raise NotImplementedError

   _sw._time = time.time() # time of creation

   return _sw

# test code
sw=stopwatch()
sw2=stopwatch()
import os
os.system("sleep 1")
print sw() # defaults to "SW_DELTA"
sw( SW_MARK )
os.system("sleep 2")
print sw()
print sw2()

1.00934004784

2.00644397736

3.01593494415

我用它们作为一个函数的静态变量。例如,给定以下C代码:

int fn(int i)
{
    static f = 1;
    f += i;
    return f;
}

我可以在Python中类似地实现该函数:

def fn(i):
    fn.f += i
    return fn.f
fn.f = 1

这肯定会落入“滥用”的范畴。

我总是假设这是可能的唯一原因是有一个逻辑的地方来放置文档字符串或其他类似的东西。我知道如果我把它用于任何生产代码,它会让大多数阅读它的人感到困惑。