当前位置:  开发笔记 > 编程语言 > 正文

Python函数属性 - 使用和滥用

如何解决《Python函数属性-使用和滥用》经验,为你挑选了5个好方法。

没有多少人知道这个功能,但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将语法规则与方法相关联.但是自定义属性呢?有充分的理由使用它们吗?



1> Martin v. Lö..:

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

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

然后我可以定义

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

然后,当webservice调用到达时,我查找方法,检查底层函数是否具有is_webmethod属性(实际值是不相关的),如果方法不存在或者不打算通过Web调用,则拒绝服务.


我正想着做到这一点.然后我停了下来."这是一个坏主意吗?" 我想知道.然后,我徘徊到SO.经过一些笨拙的事后,我发现了这个问题/答案.还不确定这是不是一个好主意.
这绝对是所有答案的功能属性的最合理使用(截至2012年11月).大多数(如果不是全部)其他答案使用函数属性作为全局变量的替代; 但是,它们并没有摆脱全局状态,这正是全局变量的问题.这是不同的,因为一旦设置了值,它就不会改变; 它是不变的.这样做的一个好结果是,您不会遇到全局变量固有的同步问题.是的,您可以提供自己的同步,但重点是:它不会自动安全.
你认为这有不足之处吗?例如,如果两个库尝试编写相同的ad-hoc属性会怎么样?

2> mipadi..:

我已经将它们用作函数的静态变量.例如,给出以下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

这绝对会落入频谱的"滥用"端.


这是一个非常糟糕的理由来推测这个答案,这是在C和Python之间进行类比,而不是提倡编写这个特定函数的最佳方法.
-1,这将使用python中的生成器实现.
@RobertRossney但是如果生成器是可行的方法,那么这是对函数属性的不良使用.如果是这样,那么这是一种滥用.不知道是否要对滥用行为进行投票,因为问题也是如此:P

3> defnull..:

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

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


+1滥用此功能的一个很好的例子,这是问题所要求的事情之一.

4> Robert Rossn..:

我谨慎使用它们,但它们可以非常方便:

def log(msg):
   log.logfile.write(msg)

现在我可以log在整个模块中使用,只需通过设置重定向输出log.logfile.有很多其他方法可以实现这一点,但这个轻量级,简单易用.虽然我第一次做它时闻起来很有趣,但我开始相信它比拥有全局logfile变量更好闻.


重新闻:虽然这并没有摆脱全局日志文件.它只是在另一个全局的日志功能中将其松散.
@allyourcode:但如果你必须在同一个模块中为不同的函数提供一堆全局日志文件,它可以帮助避免名称冲突.

5> Kevin Little..:

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

#!/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


为什么在我们有课时方便推送功能?让我们不要忘记类可以模拟一个函数.
@bgbg是正确的,尽管此示例与睡眠无关。
推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有