合同:函數將函數作爲參數並返回函數[即已修改(或相同)版本的函數]。例如,通過函數,這裏是square
。裝修工合同
@floatify
def square(n):
return n*n
是裝飾者是否只返回傳遞函數的裝飾版本,但沒有別的?
合同:函數將函數作爲參數並返回函數[即已修改(或相同)版本的函數]。例如,通過函數,這裏是square
。裝修工合同
@floatify
def square(n):
return n*n
是裝飾者是否只返回傳遞函數的裝飾版本,但沒有別的?
它應該只返回一個函數,但沒有阻止你返回任何你想要的東西。
>>> def d(x):
... return "hello"
...
>>> @d
... def f():
... return "world"
...
>>> f
'hello'
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>>
我不明白,但我喜歡。我需要閱讀裝飾器... – ratskin
@ratskin包括上面的裝飾器的功能是一樣的後面添加'function = decorator(function)'。 –
沒有任何東西阻止我返回任何東西,這是一種錯誤運用裝飾者思想的簡單方法。可能你應該刪除那個短語,在你的答案 – overexchange
裝飾函數應該返回一個函數,因爲它返回的任何東西都會被綁定到原始函數的名字上。所以如果返回的對象不是一個函數(或者其他一些可調用的,比如一個類的構造函數或者可調用的類實例),那就相當混亂。
通常返回的函數應該有一個與原始函數兼容的函數簽名,但我想如果返回的函數也需要額外的參數,那也沒關係。另外,返回函數的返回類型應該與原始函數的返回類型兼容。
裝飾函數有點像原始函數的子類,所以遵循Liskov substitution principle是有意義的。
裝飾功能可能有副作用:例如,它可以修改一些全局。這可能是有用的,例如用於記錄目的; OTOH,功能通常應避免有副作用。
FWIW,一些標準函數裝飾器返回非函數可調參數,最常見的可能是@classmethod
。
裝飾者沒有什麼特別的神奇。由於賈裏德Goguen在評論中提到,
@decorator
def some_function(args):
#etc
是相同的
def some_function(args):
#etc
some_function = decorator(some_function)
第二種形式是長一點,但功能更強大,因爲你可以選擇返回的功能結合到一個不同的名稱, 如果你想。如果不是完全不可能使用@
語法,那麼使用較長語法可以輕鬆完成的一些事情可能很困難。
[這裏](https://stackoverflow.com/a/34558606/2482744)是一個裝飾器的例子,它以非常有用的方式返回非函數。 –
@Alex ???那些是功能......我錯過了什麼? –
@JaredGoguen lambdas是實際的裝飾器,而'skip [除了]'是產生裝飾器的函數。所以裝飾的功能可以替換爲None。 –
裝飾可以作爲
代碼在您的查詢是功能裝飾,即取代裝飾福(square
)與wrapper
。wrapper
執行以下操作:
f(n)
float
到result
並返回。def floatify(f):
def wrapper(n):
result = f(n)
return float(result)
return wrapper
功能裝飾的合同:
的替換功能通常榮譽的裝飾功能的合同:
的替換功能應該從裝飾功能
@functools.wraps(f)
最常見的情況是返回一個新的函數(一個包裝器),它使用傳遞函數,它不是傳遞函數的修改版本。 –
@AlexHall修改過的函數我的意思是,無論如何,這個函數使用傳遞的函數。 – overexchange
好的,我只是想澄清一下,因爲有時裝飾器可能會簡單地設置傳入函數的屬性,然後將其返回,這是我認爲您的修改版本的含義。 –