我正在寫一些支持代碼來加快通過RequestFactory調用Django視圖(在其他地方聲明的函數)。我將大多數測試屬性直接存儲在類上,而不是其實例上。最簡單的方法來「存儲」一個類沒有綁定它的功能?
我需要做的一件事是在課堂上存儲我感興趣的功能,以便稍後可以調用它(使用檢查爲其提供正確的參數)。
這裏是我的總的意圖:
def to_test(var1, var2, var3):
"this function has nothing to do with MyTest"
assert isinstance(var1, basestring), "not an instance"
class MyTest(unittest.TestCase):
#only using this attribute to store the function to
#test, not to bind that function
func_under_test = to_test
def test_with_abc(self):
self.func_under_test("a","b", "c")
def test_with_def(self):
self.func_under_test("d","e", "f")
但只要我一個函數分配給它綁定到類的類。
99%的時間很好。只是不在這裏,因爲它被調用時會得到錯誤的參數。相反,在每個班級,我重新申報了,這樣我就可以將該功能分配給它,而不是直接放在班級上。即使是元類也無濟於事。
一些示例代碼
我想是FunctionStore1/2的語法。我實際上最接近的是FunctionStore3/4/6,但它們要求您記住每次粘貼_
聲明時複製&。沒什麼大不了,只是哈克。
def regular_function(*args, **kwds):
print (" regular_function(%s)" % (locals()))
def regular_function2(*args, **kwds):
print (" regular_function2(%s)" % (locals()))
class FunctionStore1(object):
"this fails, expecting an instance"
func_to_check = regular_function
class FunctionStore2(object):
"ditto"
func_to_check = regular_function2
class FunctionStore3Works(object):
"this works"
def _(): pass
_.func_to_check = regular_function
class FunctionStore4Works(object):
"""this too, but I have to redeclare the `_` each time
can I use MetaClass?
"""
def _(): pass
_.func_to_check = regular_function2
class BaseTsupporter(object):
"this doesnt help..."
def _(): pass
class FunctionStore5(BaseTsupporter):
"because there is no `_` here"
try:
_.func_to_check = regular_function
except Exception, e:
print ("\nno `_` on FunctionStore5:e:%s" % (e))
class FunctionStore6Works(object):
"trying a dict"
_ = dict(func_to_check=regular_function)
class MyMeta(type):
def __new__(meta, name, bases, dct):
res = super(MyMeta, meta).__new__(meta, name, bases, dct)
#this works...
res._ = dict()
return res
def __init__(cls, name, bases, dct):
super(MyMeta, cls).__init__(name, bases, dct)
try:
class FunctionStore7Meta(object):
"using meta"
__metaclass__ = MyMeta
try:
_.update(func_to_check=regular_function)
except Exception, e:
print ("\nno `_` dict on FunctionStore7:e:%s" % (e))
except Exception, e:
print ("\nno luck creating FunctionStore7 class :(exception:\n %s" % (e))
#never mind the locals() + globals() hack, that's because this code is actually in a function to
#allow SO's indenting...
li_to_call = [(k,v) for k, v in (locals().items() + globals().items()) if k.startswith("FunctionStore")]
li_to_call.sort()
for name, cls_ in li_to_call:
print ("\n calling %s" % (name))
try:
if getattr(cls_, "func_to_check", None):
cls_.func_to_check(name)
elif hasattr(cls_, "_") and hasattr(cls_._, "func_to_check"):
cls_._.func_to_check(name)
elif hasattr(cls_, "_") and isinstance(cls_._, dict) and cls_._.get("func_to_check"):
cls_._["func_to_check"](name)
else:
print (" %s: no func_to_check" % (name))
if "Meta" in name:
print(" even if %s does have a `_`, now:%s" % (name, cls_._))
except Exception, e:
print (" %s: exception:%s" % (name, e))
輸出:
no `_` on FunctionStore5:e:name '_' is not defined
no `_` dict on FunctionStore7:e:name '_' is not defined
calling FunctionStore1
FunctionStore1: exception:unbound method regular_function() must be called with FunctionStore1 instance as first argument (got str instance instead)
calling FunctionStore2
FunctionStore2: exception:unbound method regular_function2() must be called with FunctionStore2 instance as first argument (got str instance instead)
calling FunctionStore3Works
regular_function({'args': ('FunctionStore3Works',), 'kwds': {}})
calling FunctionStore4Works
regular_function2({'args': ('FunctionStore4Works',), 'kwds': {}})
calling FunctionStore5
FunctionStore5: no func_to_check
calling FunctionStore6Works
regular_function({'args': ('FunctionStore6Works',), 'kwds': {}})
calling FunctionStore7Meta
FunctionStore7Meta: no func_to_check
even if FunctionStore7Meta does have a `_`, now:{}
是否有原因需要將該函數存儲在類中而不是實例上?另外,這只是Python 2中的一個問題,因爲在Python 3中,未綁定的方法不再需要第一個參數作爲類的一個實例。 – Blckknght
嗯,因爲這個類有點像在Django中看到的所有* Meta *和* Model *類。它存儲測試屬性,如數據庫調用,登錄憑據,URL和函數調用。這些屬性對於類是固定的,並且在實例上設置它們會起作用,但也只是引入樣板代碼。這是Python 2,儘管print()。 –