我是装饰师的想法的新手(并且仍然试图绕过他们),但我认为我遇到了一个非常适合他们的问题.我希望在数学库中包含所有函数的类.更具体地说,我的班级有两个成员,x和flag.当flag为true时,我想要调用原始数学函数.当flag为false时,我想返回None.
作为我在这里要求的框架是这个类:
import math
class num(object):
def __init__(self, x, flag):
self.x = x
self.flag = flag
def __float__(self):
return float(self.x)
Run Code Online (Sandbox Code Playgroud)
结果,这很好:
a = num(3, True)
print math.sqrt(a)
Run Code Online (Sandbox Code Playgroud)
然而,这应该(在我完美的世界),返回无:
b = num(4, False)
print math.sqrt(b)
Run Code Online (Sandbox Code Playgroud)
有关如何应用于整个函数库的任何建议或提示?
虽然您不需要@decorator语法,但您可以使用装饰器.
以下代码将您从math模块列出的每个函数导入当前模块的命名空间,并将其包装在定义的装饰器中.它应该给你基本的想法.
from functools import wraps
def check_flag(func):
@wraps(func)
def _exec(x, *args, **kw):
if getattr(x, 'flag', False):
return None
return func(x, *args, **kw)
return _exec
import sys, math
_module = sys.modules[__name__]
for func in ('exp', 'log', 'sqrt'):
setattr(_module, func, check_flag(getattr(math, func)))
Run Code Online (Sandbox Code Playgroud)
您可以自动化math模块中定义的函数列表,正如Alex演示的那样,但我认为明确地包含您感兴趣使用的函数是一种更好的方法.
这是一般的想法......:
>>> class num(object):
... def __init__(self, x, flag):
... self.x = x
... self.flag = flag
... def __float__(self):
... return float(self.x)
... from functools import wraps
>>> def wrapper(f):
... @wraps(f)
... def wrapped(*a):
... if not all(getattr(x, 'flag', True) for x in a):
... return None
... return f(*(getattr(x, 'x', x) for x in a))
... return wrapped
...
>>> import inspect
>>> import math
>>> for n, v in inspect.getmembers(math, inspect.isroutine):
... setattr(math, n, wrapper(v))
...
>>> a = num(3, True)
>>> print math.sqrt(a)
1.73205080757
>>> b = num(4, False)
>>> print math.sqrt(b)
None
Run Code Online (Sandbox Code Playgroud)
请注意,此包装器还涵盖非一元函数math(None如果任何参数具有a,则返回False .flag)并允许其混合调用(其中一些args是实例,num其他是实际浮点数).
适用于任何"包装特定模块中的所有函数"任务的关键部分是使用模块inspect获取模块中函数的所有名称和值(内置与否)math,以及对包装器的显式调用(相同的语义)作为装饰器语法)将该名称设置为math模块中的包装值.
| 归档时间: |
|
| 查看次数: |
891 次 |
| 最近记录: |