gpt4 book ai didi

Python 自省(introspection) : Automatic wrapping of methods

转载 作者:行者123 更新时间:2023-11-28 21:28:38 28 4
gpt4 key购买 nike

A 类型的对象以及是否有一种方法可以通过编程方式包装类对象?

给定

class A(object):
def __init__(self):
## ..

def f0(self, a):
## ...

def f1(self, a, b):
## ..

我想要另一个包装 A 的类,例如

class B(object):
def __init__(self):
self.a = A()

def f0(self,a):
try:
a.f0(a)
except (Exception),ex:
## ...

def f1(self, a, b):
try:
a.f1(a,b)
except (Exception),ex:
## ...

有没有办法通过反射/检查类 A 来创建 B.f0 & B.f1

最佳答案

如果你想通过调用预定义类 A 上的函数来创建类 B,你可以简单地执行 B = wrap_class(A) 带有如下所示的函数 wrap_class:

import copy

def wrap_class(cls):
'Wraps a class so that exceptions in its methods are caught.'
# The copy is necessary so that mutable class attributes are not
# shared between the old class cls and the new class:
new_cls = copy.deepcopy(cls)
# vars() is used instead of dir() so that the attributes of base classes
# are not modified, but one might want to use dir() instead:
for (attr_name, value) in vars(cls).items():
if isinstance(value, types.FunctionType):
setattr(new_cls, attr_name, func_wrapper(value))
return new_cls

B = wrap_class(A)

正如 Jürgen 所指出的,这会创建一个类的副本;但是,只有在您真的想保留原始类 A 时才需要这样做(如原始问题中所建议的那样)。如果你不关心 A,你可以简单地用一个不执行任何复制的包装器来装饰它,就像这样:

def wrap_class(cls):
'Wraps a class so that exceptions in its methods are caught.'
# vars() is used instead of dir() so that the attributes of base classes
# are not modified, but one might want to use dir() instead:
for (attr_name, value) in vars(cls).items():
if isinstance(value, types.FunctionType):
setattr(cls, attr_name, func_wrapper(value))
return cls

@wrap_class
class A(object):
… # Original A class, with methods that are not wrapped with exception catching

装饰类 A 捕获异常。

元类版本比较重,但原理类似:

import types

def func_wrapper(f):

'Returns a version of function f that prints an error message if an exception is raised.'

def wrapped_f(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception, ex:
print "Function", f, "raised", ex

return wrapped_f

class ExceptionCatcher(type):

'Metaclass that wraps methods with func_wrapper().'

def __new__(meta, cname, bases, cdict):
# cdict contains the attributes of class cname:
for (attr_name, value) in cdict.items():
if isinstance(value, types.FunctionType): # Various attribute types can be wrapped differently
cdict[attr_name] = func_wrapper(value)
return super(meta, ExceptionCatcher).__new__(meta, cname, bases, cdict)

class B(object):

__metaclass__ = ExceptionCatcher # ExceptionCatcher will be used for creating class A

class_attr = 42 # Will not be wrapped

def __init__(self):
pass

def f0(self, a):
return a*10

def f1(self, a, b):
1/0 # Raises a division by zero exception!

# Test:
b = B()
print b.f0(3.14)
print b.class_attr
print b.f1(2, 3)

这打印:

31.4
42
Function <function f1 at 0x107812d70> raised integer division or modulo by zero
None

你想做的实际上通常是由一个元类完成的,元类是一个类,其实例是一个类:这是一种基于其解析的 Python 代码动态构建 B 类的方法(类 A 的代码,在问题中)。有关这方面的更多信息,请参阅 Chris 的 Wiki(在 part 1parts 2-4 中)对元类的简短描述。

关于Python 自省(introspection) : Automatic wrapping of methods,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7589208/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com