我有一个实例化一堆类的类。我不希望这些类中的每一个都被装饰(出于测试目的),所以我用包装器将它们包装在主类中,而包装器又包装了所有方法。当我创建该类的多个实例时,它的函数已经被包装,因为我使用未实例化的对象来准备它。有没有一种好方法可以避免每次都重新包装它们?
简化示例:
UserResource.py:
class UserResource(object):
def test(self):
pass
resource.py:
def resource_wrapper(resource_class):
def decorate(cls):
for attr in cls.__dict__:
if callable(getattr(cls, attr)) and not attr.startswith('_'):
setattr(cls, attr, _function_wrapper(getattr(cls, attr)))
return cls
return decorate(resource_class)
def _function_wrapper(fn):
from functools import wraps
@wraps(fn)
def wrapper(*args, **kwargs):
self = args[0]
arg = kwargs.pop('test', False)
print arg # See output further down
return fn(*args, **kwargs)
return wrapper
tl; dr 一堆未实例化的类,用包装所有函数的包装器包装。函数每次运行时都会被包装。
当我运行时,我看到以下行为:
r1 = resource_wrapper(UserResource)()
r1.test(test=True)
# True
r2 = resource_wrapper(UserResource)()
r2.test(test=True)
# True
# False
r3 = resource_wrapper(UserResource)()
r3.test(test=True)
# True
# False
# False
有没有办法只包装一次而不是每次?
答案 0 :(得分:0)
您应该看一下实现模板模式。这将为您提供标题中的共性,以及您可以仅在派生中实现的变体。
我无法从您的问题中提取更多信息,但也许策略模式可以提供解决方案。
/**
* An abstract class that is common to several games in
* which players play against the others, but only one is
* playing at a given time.
*/
abstract class Game {
/* Hook methods. Concrete implementation may differ in each subclass*/
protected int playersCount;
abstract void initializeGame();
abstract void makePlay(int player);
abstract boolean endOfGame();
abstract void printWinner();
/* A template method : */
public final void playOneGame(int playersCount) {
this.playersCount = playersCount;
initializeGame();
int j = 0;
while (!endOfGame()) {
makePlay(j);
j = (j + 1) % playersCount;
}
printWinner();
}
}
//Now we can extend this class in order
//to implement actual games:
class Monopoly extends Game {
/* Implementation of necessary concrete methods */
void initializeGame() {
// Initialize players
// Initialize money
}
void makePlay(int player) {
// Process one turn of player
}
boolean endOfGame() {
// Return true if game is over
// according to Monopoly rules
}
void printWinner() {
// Display who won
}
/* Specific declarations for the Monopoly game. */
// ...
}
class Chess extends Game {
/* Implementation of necessary concrete methods */
void initializeGame() {
// Initialize players
// Put the pieces on the board
}
void makePlay(int player) {
// Process a turn for the player
}
boolean endOfGame() {
// Return true if in Checkmate or
// Stalemate has been reached
}
void printWinner() {
// Display the winning player
}
/* Specific declarations for the chess game. */
// ...
}
答案 1 :(得分:0)
我通过改变操作实例化对象而不是类本身来修复它。
我的resource_wrappers如果更改为for attr in dir(cls):
,我将cls
传递给_function_wrapper,并将其作为self
使用。
为清楚起见,这是示例代码的最终结果:
<强> UserResource.py:强>
class UserResource(object):
def test(self):
pass
<强> resource.py:强>
def resource_wrapper(resource_class):
def decorate(cls):
for attr in dir(cls):
if callable(getattr(cls, attr)) and not attr.startswith('_'):
setattr(cls, attr, _function_wrapper(cls, getattr(cls, attr)))
return cls
return decorate(resource_class)
def _function_wrapper(cls, fn):
from functools import wraps
@wraps(fn)
def wrapper(*args, **kwargs):
self = cls
arg = kwargs.pop('test', False)
print arg # See output further down
return fn(*args, **kwargs)
return wrapper
<强>用法:强>
r1 = resource_wrapper(UserResource())
r1.test(test=True)
# True