Dekoratory w pythonie - jak dziala przekazywanie argumentow?

0

Witam, mam pytanie. W ponizszym kawalku kodu ktory znalazlem na stronie:

 
def smart_divide(func):
	def inner(a, b):
		print "division of", a, "and", b
		if b == 0
			print "division by 0 error"
			return
		return func(a, b)
	return inner

@smart_divide
def divide(a, b):
	return a / b
divide(5, 2)

nie rozumiem jak parametry 5 i 2 sa przekazane do funkcji inner. Jesli dobrze rozumiem te anotacje, to powyzsza jest tylko skrotem dla:

divide = smart_divide(divide(5, 2))

Funkcja smart_divide przyjmuje jako argument funkcje, i zwraca obiekt ktory jest funkcja inner. Inner z kolei skads bierze parametry przekzane do funkcji zewnetrznej (???), a nastepnie zwraca wynik wywolania parametru funkcji zewnetrznej?
Moglby ktos po kolei opisac co sie dzieje w kazdym kroku? Dzieki wielkie.

2

Dekorator to nic innego jak funkcja zwracająca funkcję. Spójrz.

def foo(a, b):			# jakaś tam funkcja
	return a + b
	
f = foo					# po prawej stronie wyrażenie zwracające funkcję.
print(f(1, 2))			# wywołujemy zwróconą funkcję.

Przykład dość prosty. Mamy funkcję, przypisujemy ją do zmiennej i wołamy.

def decorator(f):
	def wrap(a, b):				# robimy dokładnie to samo, definiujemy funkcję zwracająca zwykła wartość.
		print('we wrapperze')
		return f(a, b)
	return wrap					# dekorator zwraca funkcję o tej samej sygnaturze jak tą, którą dekorujemy.

@decorator
def foo(a, b):
	return a +b
	
print(foo(1, 2))				# Nie wołamy funkcji `foo` tak naprawdę, tylko wrap z argumentami.
								# Wrap natomiast woła w środku funkcje dekorowaną (foo)
0

Dzieki za odpowiedz, ale nadal mam watpliwosci. Skoro foo to tak naprawde wrap zwrocony przez decorator, to dzieki mechanizmowi clojure mamy nadal dostep do argumentu przekazanego do decorator (czyli do foo)?
Ten kawalek z anotacja:

@decorator
def foo(a, b):
	return a +b

to odpowiednik:

foo = decorator(foo(a, b))

tak?

0

Dokładnie, zapis z adnotacją to po prostu uproszczona forma.

0

Jeśli dobrze rozumiem.

def decorator(f): <- Tutaj definiujemy naszego decoratora do którego się będziemy odwoływać w dalszych częściach?
def wrap(a, b): # robimy dokładnie to samo, definiujemy funkcję zwracająca zwykła wartość. <- tutaj jest zdefiniowana główna część tej funkcji
print('we wrapperze')
return f(a, b)
return wrap # dekorator zwraca funkcję o tej samej sygnaturze jak tą, którą dekorujemy. <-darujcie ale dopiero zaczynam i nie do końca rozumiem o co chodzi z sygnaturą?

@decorator
def foo(a, b): <- tutaj tworzymy nową metodę z argumentami z naszego decoratora?
return a +b

print(foo(1, 2)) # Nie wołamy funkcji foo tak naprawdę, tylko wrap z argumentami.
# Wrap natomiast woła w środku funkcje dekorowaną (foo)

Korzystam z książki "Python dla każdego"
jest to tam opisane jako

dekorator —możesz sobie to wyobrazić jako dekorowanie czy też
modyfikowanie funkcji lub metody

0
uczeSiePythona napisał(a):

[...]Jesli dobrze rozumiem te anotacje, to powyzsza jest tylko skrotem dla:

divide = smart_divide(divide(5, 2))

Krótko -- źle rozumiesz. Raczej:

divide = smart_divide(divide)
divide(5, 2)

1 użytkowników online, w tym zalogowanych: 0, gości: 1