2014-12-07 21 views
36
def make_bold(fn): 
    return lambda : "<b>" + fn() + "</b>" 

def make_italic(fn): 
    return lambda : "<i>" + fn() + "</i>" 

@make_bold 
@make_italic 
def hello(): 
    return "hello world" 

helloHTML = hello() 

Çıktı: "<b><i>hello world</i></b>"Dekoratör yürütme sırası

Kabaca dekoratörler hakkında anlamamız ve en örneklerde bunun biriyle nasıl çalıştığını.

Bu örnekte, bunlardan 2 tane var. Çıktıdan, @make_italic ilk önce, daha sonra @make_bold yürütülür gibi görünüyor.

Bu, süslü işlevler için önce işlevi ilk önce çalıştıracak ve sonra diğer dekoratörler için yukarı doğru hareket edeceği anlamına mı geliyor? @make_italic gibi ilk önce @make_bold, tersi yerine.

Bu, çoğu programlama langında yukarıdan aşağıya yaklaşımın normundan farklı olduğu anlamına mı geliyor? Sadece bu dekoratör davası için mi? Yoksa yanılıyor muyum?

+2

evet anlıyorum sonraki –

cevap

58

Dekoratörler onlar dekorasyon vardır işlevini sarmak . Yani make_bold, hello işlevini dekore eden make_italic dekoratörünün sonucunu süsledi.

@decorator sözdizimi gerçekten sözdizimsel bir şekildedir; Aşağıdaki:

@decorator 
def decorated_function(): 
    # ... 

gerçekten olarak yürütülür:

def decorated_function(): 
    # ... 
decorated_function = decorator(decorated_function) 

decorator() döndü ne olursa olsun orijinal decorated_function nesneyi değiştirerek. dışa işlemek

İstifleme dekoratörler tekrarlar.

Yani örnek:

def hello(): 
    return "hello world" 
hello = make_bold(make_italic(hello)) 

şimdi, sen make_bold() tarafından döndürülen nesne aradığınız hello() diyoruz

, gerçekten:

@make_bold 
@make_italic 
def hello(): 
    return "hello world" 

için genişletilebilir. make_bold() orijinal hello() çağıran bir lambda make_italic() dönüş değeri olan sarılmış fonksiyonu make_bold, çağıran bir lambda döndü. Genişleyen tüm bu çağrılar elde edersiniz:

hello() = lambda : "<b>" + fn() + "</b>" # where fn() -> 
    lambda : "<i>" + fn() + "</i>" # where fn() -> 
     return "hello world" 

böylece çıkış olur:

"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>" 
+0

sonucu geçen aşağıdan yukarıya başlar. Ancak bu, bu durumda 2 sarmalayıcı olduğunda, IDE otomatik olarak ilk sargının sonucunu algılayacak ve sarılacak anlamına mı geliyor? Çünkü @make_bold #make_bold = make_bold (merhaba) ' ' @make_italiC#make_italic = make_italic (merhaba) 'diye düşündüm. Buna dayanarak, ilk sonucu sarmalayacağından emin değilim. Ya da bu 2 sarmalayıcı için IDE, paylaştığımın yerine bahsettiğin gibi make_bold (make_italic (hello)) 'i kullanacak? – Newbie

+0

@Newbie: IDE'niz burada hiçbir şey yapmıyor; * Python * bu sarma yapar.Son örneğimde, make_bold() 'ın' make'me ('make' (make) (make_italic (hello)) 'eşdeğeri olan 'make_italic()' ın çıktılarını sardığını gösterdim. –

+0

Bu kodun bir sürümünü lambda kullanmadan sağlayabilir misiniz? .format denedim ama işe yaramadı. Ve bu örnekte neden lambda kullanılır? Ben lambda ve bu örnekte nasıl çalıştığını anlamaya çalışıyorum ama hala problem yaşıyorum. Bu lambda, def fonksiyonlarının normlarına göre çok kolay bir şekilde geçirilebilen bir çizgi fonksiyonu gibi mi? – Newbie