背景: 比方說,我們有打開一個頻繁使用的數據庫連接的功能,東西基本上像下面,但額外的花俏:在Python中,通用函數/對象加倍裝飾器是否可行?
也許有時候,我們要打開兩種連接方式,沿着線:
read_connection = myspecialconnect()
write_connection = myspecialconnect()
多麼痛苦 - 我有兩次輸入我的密碼,當所有我想要的是一次同樣的事情。當然,有很多方法可以修改這個例子以避免這種情況 - 例如,可以添加一個參數,如myspecialconnect(multi=True)
返回兩個連接而不是一個,或者myspecialconnect(copies=9)
,如果您想要變得瘋狂,請使用相應的代碼使這一切發生在這一個函數中。但是,這種特殊情況促使我想知道更普遍的應用。
問題:如果我希望能夠從任意函數獲得此功能(返回多個我們想要的副本),該怎麼辦?嗯 - 這可能會很棘手。
首先,只是爲了確認它不工作,我嘗試這樣做:
def doubled(function):
def Wrapper(*args, **kwargs):
return (function(*args, **kwargs),function(*args, **kwargs))
return Wrapper
沒關係的,無需用戶輸入的功能;否則,你仍然必須坐在那裏,並連續輸入兩次完全相同的東西。這是很容易解決,但現在你也許能看到這是怎麼回事:
def doubled(function):
def Wrapper(*args, **kwargs):
result = function(*args, **kwargs)
return (result, result)
return Wrapper
這個版本需要用戶輸入只有一次,但它返回相同的參考兩次,使得它無非是不必要的更錯綜複雜的做法foo = bar = object()
。 「啊哈!」我說,「也許我應該看看copy
模塊。」這是我做的,只是我不太知道它是如何工作尚未...
>>> import copy
>>> a = (i for i in [1,2])
>>> a
<generator object <genexpr> at 0x03FB0878>
>>> copy.copy(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\WinPython-32bit-2.7.5.1\python-2.7.5\lib\copy.py", line 96, in copy
return _reconstruct(x, rv, 0)
File "C:\WinPython-32bit-2.7.5.1\python-2.7.5\lib\copy.py", line 329, in _reconstruct
y = callable(*args)
File "C:\WinPython-32bit-2.7.5.1\python-2.7.5\lib\copy_reg.py", line 93, in __newobj__
return cls.__new__(cls, *args)
TypeError: object.__new__(generator) is not safe, use generator.__new__()
>>> copy.deepcopy(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\WinPython-32bit-2.7.5.1\python-2.7.5\lib\copy.py", line 190, in deepcopy
y = _reconstruct(x, rv, 1, memo)
File "C:\WinPython-32bit-2.7.5.1\python-2.7.5\lib\copy.py", line 329, in _reconstruct
y = callable(*args)
File "C:\WinPython-32bit-2.7.5.1\python-2.7.5\lib\copy_reg.py", line 93, in __newobj__
return cls.__new__(cls, *args)
TypeError: object.__new__(generator) is not safe, use generator.__new__()
當然,現在我已經在這花了約儘可能多的時間,我可以證明有可能(或更多)小問題,這意味着我非常好奇。這是否可以通過返回任意實例副本的方式來完成,而不會變成一個被迫以各自特殊方式顯式處理數十個案例的怪物?
你想要一個實際的副本,或者你想要一個完整的新實例嗎? – Blaine
理想的'@ doubled'裝飾器的功能是使得'a,b = doubled(getSomething)()'分別等價於'a = getSomething()'和'b = getSomething()'。這意味着新的實例。 – Air