Gelişmiş Python Programlama-Dekoratör Süper Ayrıntılı Açıklama (Bölüm 1)
Seni dikkatlice gönder ve beni takip etmeyi unutma! !
Metni girin
Tam metin özeti
Dekoratör, python dilinin önemli bir özelliğidir.Nesne yönelimli tasarım veya ilgili kitaplıkların kullanımı olsun, genellikle bununla karşılaşıyoruz, ancak dekoratörlerin giriş ve çıkışları hakkında derinlemesine ayrıntılar sağlayan az sayıda makale var.Sonuç, birçok insanın bildiği Tabii nedenini bilmiyorum, bu yüzden Python dekoratörleri hakkında detaylı bir makale yayınlamayı planlıyorum.Yüksek içerik nedeniyle makale iki bölüme ayrılıyor, ilk bölüm bu yazıda anlatılacak. Çok dikkat! Makale çok uzun, tam metni okumak için yaklaşık 20 dakika.
Tam metin kataloğu
01 Python dekoratörünün doğumunun arka planı
1.1 Basit bir durumdan bahsetmek
1.2 "Dekoratör" olmayan ek işlevler eklemeyi gerçekleştirir
02 Dekoratör nedir
2.1 İki seviyeli dekoratör tanımı
2.2 Dekorasyonun rolü - iki yön
2.3 Dekoratörlerin senaryolarını kullanın
03 Dekoratörün uygulanması
3.1 Dekoratörlerin adım adım uygulanması
3.2 Dekoratörlerin genel "şablonu"
04 Dekoratörlerin sınıflandırmasının uygulanması (sonraki fragman)
Python dekoratörünün ayrıntılı açıklaması (bölüm 1)
01
Python dekoratörünün doğumunun arka planı
01 Dekoratörün doğumunun arka planı
1.1 Basit bir durumdan bahsetmek
Dekoratörün tanımı çok soyut ve farklı makalelerin farklı ifadeleri var ama başlangıçta size bir Python dekoratörünün ne olduğunu söylemeyeceğim, çok ani, küçük bir örnek alalım.
Önce basit bir işlevi tanımlayın:
def myfunc:
print ('Ben işlevimim')
myfunc () #Call işlevi
Sonra, bu fonksiyonun bu fonksiyonu çalıştırmasının ne kadar sürdüğünü görmek istiyorum, o zaman bunu yapabiliriz:
ithalat zamanı
def myfunc:
start = time.clock ()
print ('Ben işlevimim')
end = time.clock ()
print (f 'işlevi zaman alır: {end-start}')
myfunc () #Function çağrısı
Artık amacımıza ulaştık. Ama eğer öyleyse, aynı işlevi diğer bazı işlevler için uygulamaya devam etmek istiyoruz. Öyleyse bu birkaç cümleyi her bir işleve ekliyor muyuz? Elbette olabilir, ancak verimli ve zahmetli değil. Tüm sorunları bir defada çözmenin belli bir yolu varsa, doğal olarak en iyisidir, dolayısıyla "dekoratörler" ortaya çıkmıştır.
Yukarıdaki örnekte, işlevin kendisinin işlevi yalnızca bir cümleyi yazdırmaktır, ancak dönüştürülen işlev yalnızca bu cümleyi yazdırmakla kalmamalı, aynı zamanda işlevi yerine getirmek için gereken süreyi de görüntüleyebilmelidir; bu, bu işleve eklemeye eşdeğerdir. Ekstra özellikler , Bu anahtar kelimeye aslında " Dekoratör "İşleve ekstra özellikler eklemektir.
01 Dekoratörün doğumunun arka planı
1.2 "Dekoratör" olmayan ek işlevler eklemeyi gerçekleştirir
Unutmayın, bir işlev Python'da birinci sınıf bir yurttaştır, bu nedenle bir işlev zamanını yeniden tanımlamayı, işlevim referansını ona iletmeyi ve sonra işlevimi zamanında çağırmayı ve zamanlamayı düşünebiliriz, böylece işlevimde hiçbir değişiklik yapmamış oluruz. Kodun tanımlanması ancak ek fonksiyonların eklenmesinin amacı aşağıdaki gibidir:
ithalat zamanı
def myfunc ():
print ("Ben işlevimim")
def timeit (işlev):
start = time.clock ()
işlev ()
end = time.clock ()
print (f'Fonksiyonu çalıştırmak için geçen süre: {end-start} ')
timeit (işlevim)
Sonuç şu şekildedir:
Ben işlevim
İşlevi yürütmek için geçen süre: 0.0004924657368762765
Yukarıdaki kod mantıksal olarak sorun değil gibi görünüyor ve başarmak istediğimiz şeyi başardı! Ancak, işlevim işlevinin tanımındaki kodu değiştirmemiş olsak da, kodun çağıran kısmını değiştirmiş gibi görünüyoruz. Başlangıçta, bunu şöyle adlandırdık: myfunc (), değişiklikten sonra oldu: timeit (myfunc). Bu durumda, işlevim N yerde çağrılırsa, kodu bu N yerde değiştirmeniz gerekir. Ya da daha aşırı, bir yerde çağrılan kodun değiştirilemeyeceği durumu düşünün, örneğin: bu işlev başkalarının kullanması için verilmiştir.
Aslında, işlevi bir parametre olarak geçirmek zaten Dekoratörün prototipi Ancak yukarıdaki uygulama yeterince iyi değil, aşağıdakiler daha iyi bir uygulama sağlayacaktır.
02
Dekoratör-dekoratör nedir
02 Dekoratör nedir
2.1 Dekoratör iki seviyenin tanımı
Genel olarak, işleve bazı ek işlevler eklemem gerekirse, işlevin kaynak kodunu değiştirmem gerekir, ancak daha önce de belirtildiği gibi, çok zahmetli ve verimsizdir.Dekoratörler özel çözümdür!
Dekoratör tanımı esas olarak İki farklı seviye Göstermek için.
Python'da iki tanım düzeyi vardır:
Birincisi: Tasarım kalıpları kodunun yeniden kullanımı düzeyinden
Dekoratör, en boy gereksinimleri olan senaryolarda sıklıkla kullanılan, iyi bilinen bir tasarım modelidir.Daha klasik uygulamalar, günlükleri eklemeyi, performansı kontrol etmek için zamanlama mantığı eklemeyi ve işlem işlemeyi eklemeyi içerir. Dekoratör, bu tür problemleri çözmek için mükemmel bir tasarımdır, Dekoratörlerle, aynı kodun işleviyle hiçbir ilgisi olmayan çok sayıda işlevi çıkarabilir ve yeniden kullanmaya devam edebiliriz. . Özetle, bir dekoratörün rolü, mevcut bir nesneye ek işlevler eklemektir.
İkincisi: Python'un gramer seviyesinden (Aslında, ikinci tür esasen birinci türdür, ancak dilbilgisi açısından standartlaştırılmıştır)
Kısaca, python dekoratörü, orijinal fonksiyonun fonksiyonunu genişletmek için kullanılan bir fonksiyondur.Bu fonksiyonun özel özelliği, dönüş değerinin de bir fonksiyon olmasıdır.Python dekoratörünü kullanmanın avantajı, orijinal fonksiyonun kodunu değiştirmesine gerek olmamasıdır. İşleve yeni işlevler ekleyin. Bu şekilde, orijinal işlevin işlevini genişletmek istiyorsak, işlevdeki kaynak kodunu değiştirmemize gerek yoktur.
02 Dekoratör nedir
2.2 Dekoratörlerin rolü - iki düzey
Yukarıdaki ifadelerle, en temel iki sonuç çıkarılabilir.Aslında bunlar aynı zamanda dekoratörlerin en temel iki işlevidir:
(1) Aynı kodu çıkarın ve yeniden kullanın
(2) İşleve ek işlevler ekleyin
02 Dekoratör nedir
2.3 Dekoratörlerin senaryolarını kullanın
Dekoratörler her zamanki kodlamamızda daha az tanımlanabilir ve daha sık kullandığımız @staticmethod, @classmethod, @property vb. Gibi başkalarının önceden yazılmış dekoratörlerini daha sık kullanırız. Bunların hepsi diğerleridir. Bir kez yazıldıktan sonra, bunu kendimiz uygulamamıza gerek yoktur.Kodlamada, aşağıdaki durumlarda sıklıkla dekoratörlerle karşılaşacağız.
(1) Önbellek dekoratörü
(2) İzin doğrulama dekoratörü
(3) Zamanlama dekoratörü
(4) Günlük dekoratörü
(5) Rota dekoratörü
(6) İstisna işleme dekoratörü
(7) Dekoratör yeniden deneme hatası
Daha sonra, aslında python dekoratörleriyle ayrılmaz bir şekilde ilişkili olan python-python tanımlayıcısının (tanımlayıcı) gelişmiş gramerinden bahsedeceğim.Ayrıntılar için lütfen aşağıdaki makaleye bakın!
03
Dekoratörün uygulanması
03 Dekoratör uygulaması
3.1 Dekoratörlerin adım adım uygulanması
Yukarıdaki kodun geliştirilmiş sürümüyle ilgili sorunlar ışığında, çözümler bulduk:
N'de çağıran kodu değiştirmek çok zahmetli olduğu için, çağıran kodu değiştirmemenin bir yolunu bulacağız; eğer çağıran kod değiştirilmezse, bu, myfunc () çağrısının timeit (myfunc) çağrısı etkisine sahip olması gerektiği anlamına gelir.
Python'daki her şey bir nesne olduğu için, işlevime timeit atamayı düşünebiliriz,
ithalat zamanı
def myfunc ():
print ("Ben işlevimim")
def timeit (işlev):
start = time.clock ()
işlev ()
end = time.clock ()
print (f'Fonksiyonu çalıştırmak için geçen süre: {end-start} ')
myfunc = timeit #Assign timeit orijinal myfunc'a
işlevim ()
Ama yukarıdaki çağrı Başaramayacak , Aşağıdaki hata görüntülenecektir:
timeit () gerekli 1 konumsal bağımsız değişken eksik: 'işlev'
neden? Bunun nedeni, myfunc'a timeit atandıktan sonra, bu sefer myfunc ve timeit aynı şeyi temsil ediyor, ancak timeit'in bir parametre işlevi var gibi görünmesi ve myfunc () çağrılırken hiçbir parametre aktarılmamasıdır, bu yüzden başarılı olmaz. .
Ancak, yukarıdaki çağrı başarılı olmamasına rağmen, bize önemli bir ipucu verdi, çünkü yukarıdaki kod çözüldü " Çağrı kodunu değiştirin "Sorun, parametrelerin birleşik olmamasıdır, bu yüzden parametreleri birleştirmeye çalışın! Sonra başka bir işlev ekleyin! Ne demek istiyorsun?
Parametreler tek tip olmadığından, timeit () doğrudan ek işlevler eklemezse, myfunc parametre listesiyle tutarlı bir işlev döndürür. Görünüşe göre, ek işlev kodu eklemesi ve sonra zaman içinde bir işlev tanımlaması gerekiyor. Yapılabilir mi? Timeit'in (işlevim) dönüş değerini işlevim'e atayın. Ardından, myfunc () işlevini çağıran kodun hiç değiştirilmesine gerek kalmaz. . Yani, hala işlevim diyoruz (arama kodu değişmedi), ancak ek işlevler eklemenin etkisi de elde edildi!
kod aşağıdaki gibi gösterilir:
ithalat zamanı
#Original function myfunc
def myfunc ():
print ("Ben işlevimim")
# Bir zamanlayıcı tanımlayın
def timeit (işlev):
'' '
Timeit işlevi bir sarmalayıcıyı döndürmekten sorumludur ve sarmalayıcının parametreleri orijinal işlevim ile aynı olmalıdır.
Bu şekilde, myfunc = timeit (myfunc) myfunc'u yürütmek tamamen wrapper ile eşdeğerdir
Sarmalayıcı işlevi, ekstra özellikler eklemekten sorumludur
'' '
def sarmalayıcı ():
start = time.clock ()
işlev ()
end = time.clock ()
print (f'Fonksiyonu çalıştırmak için geçen süre: {end-start} ')
dönüş sarıcı
myfunc = timeit (myfunc) #Bunun önceki "myfunc = timeit" den farklı olduğuna dikkat edin
myfunc () #Bu hala orijinal myfunc () çağrısıyla aynıdır, ancak ek işlevler ekleme etkisine ulaşır
Yukarıdaki işlemin sonucu aşağıdaki gibidir:
Ben işlevim
İşlevi yürütmek için geçen süre: 0.0005973331798019136
sonuç olarak: Yukarıdaki işlev tanımında ve çağrısında, myfunc () çağrımın orijinalden farklı olmadığı görülüyor, ancak ek efektler eklenmiş. Önceki iki sorunu çözer:
(1) İşlevin kaynak kodunu veya işlevi çağıran kodu değiştirmeye gerek yoktur, orijinal myfunc () koduyla tamamen aynıdır, ancak ek işlevler eklenir;
(2) tutarsız timeit ve myfunc parametreleri sorununu çözün, yani başka bir sarmalayıcı katmanı ekleyin;
Bu dekoratör.
Yukarıdaki dekoratör orijinal versiyondur, ancak özel versiyondur " Sözdizimsel şeker "Dekoratörün daha profesyonel ve daha güzel görünmesi için uygulamak. Sadece karakterleri kullanın" @ "Başarmak için. Kod aşağıdaki gibidir:
ithalat zamanı
# Bir zamanlayıcı tanımlayın
def timeit (işlev):
'' '
Timeit işlevi bir sarmalayıcıyı döndürmekten sorumludur ve sarmalayıcının parametreleri orijinal işlevim ile aynı olmalıdır.
Bu şekilde, myfunc = timeit (myfunc) myfunc'u yürütmek tamamen wrapper ile eşdeğerdir
Sarmalayıcı işlevi, ekstra özellikler eklemekten sorumludur
'' '
def sarmalayıcı ():
start = time.clock ()
işlev ()
end = time.clock ()
print (f'Fonksiyonu çalıştırmak için geçen süre: {end-start} ')
dönüş sarıcı
# myfunc = timeit (myfunc) #Bunun önceki "myfunc = timeit" den farklı olduğuna dikkat edin
#Original function myfunc
@timeit
def myfunc ():
print ("Ben işlevimim")
myfunc () #Bu hala orijinal myfunc () çağrısıyla aynıdır, ancak ek işlevler ekleme etkisine ulaşır
Yukarıdaki kodun sonucu hala:
Ben işlevim
İşlevi yürütmek için geçen süre: 0.0004893814003196401
Yukarıdaki örnekte, @timeit, önceki yazım myfunc = timeit (myfunc) ile tamamen eşdeğer olan myfunc fonksiyonunun tanımının üzerine eklenmiştir,
@ İki önemli işlevi vardır ,
ilk: Daha az kod yazma;
ikinci: Bu, kodumuzun daha süslü ve daha yüksek kaliteli görünmesini sağlamaktır.
sonuç olarak
Bu örnekte, fonksiyon girerken ve çıkarken zamanlama gerektirir. Buna a Kesit (Açı) , Bu programlama yöntemine Görünüşe Dayalı Programlama (Görünüşe Yönelik Programlama) . Geleneksel programlama alışkanlıklarının yukarıdan aşağıya yürütme yöntemi ile karşılaştırıldığında, işlev yürütme sürecindeki gibidir. Yatay olarak bir mantık parçası ekle . Belirli bir iş alanında, çok sayıda kod tekrarını azaltabilir. Bakış açısına yönelik programlamada hala epeyce terim var, bu yüzden burada daha fazlasını tanıtmayacağım. İlgileniyorsanız, ilgili bilgileri bulabilirsiniz (gerekirse, daha sonra bakış açısına yönelik programlama üzerine bir dizi makale yazmak için de zaman ayıracağım, bkz. Vaktim var mı!)
03 Dekoratör uygulaması
3.2 Dekoratörlerin genel "şablonu"
Dekoratörün uygulama prensibini netleştirebilmek için, işte dekoratörün açıklaması "Genel şablon "Herkesin anlaması kolaydır! Ancak, bir tasarım modeli olarak, dekoratörün kendisi sabit bir tasarım şablonuna sahip değildir ve sözdizimi nispeten esnektir. Nasıl doğru yazılacağı söylenmez.
Şablon aşağıdaki gibidir:
def dekoratör (işlev):
'' '
İlk katman işlevi, dekoratör adıdır
işlev: parametre, yani dekore edilecek işlev
dönüş: orijinal fonksiyon parametreleriyle tutarlılık sağlamak için dönüş değeri sarmalayıcısı
'' '
def sarmalayıcı (* arg, ** değiştirgeler):
'' '
İç işlev, bu işlev "ekstra özellikler ekleme" görevini yerine getirir
* arg, ** args: Parametreler, dekore edilmesi gereken fonksiyon parametreleriyle tutarlı tutulur. Burada, bunun yerine * arg ve ** args kullanılır
'' '
# İşte ekstra fonksiyon kodu
function () #Orijinal işlevi çalıştır
# İşte ekstra fonksiyon kodu
dönüş sarıcı
Genellikle, yukarıdaki şablona göre "dekoratör" işlevini yazmanız yeterlidir ve hata olmayacaktır.
Önlemler:
(1) Dekoratör genellikle iki işlev katmanından oluşur; dış dekoratör ve iç sarıcı;
(2) Parametreleri orijinal işlevle tutarlı tutmak için birinci katman işlevinin parametre işlevi, yani dekore edilmesi gereken işlev ve dönüş değeri sarmalayıcısı
(3) İç işlev, bu işlev "ekstra özellikler ekleme", * arg, ** args görevini yerine getirir: Parametreler, dekore edilmesi gereken işlev parametreleriyle tutarlı tutulur, burada * arg ve ** args ile değiştirilir.
04
Dekoratörlerin çeşitli süslü uygulamaları
04 Dekoratörlerin çeşitli süslü uygulamaları
4.1 Dekoratörlerin türe göre uygulanması
Dekoratörleri öğrenen herkes Python'u bilir Kapanış "Kapanış" ın ayrıntılı tanımının çeşitli versiyonları vardır, ancak sık sık böyle bir cümle görüyoruz, "Python dekoratörü bir tür kapatmadır veya Python kapatması aslında dekoratördür", bu cümle bir dereceye kadar Yukarıdakiler yanlıştır, ancak bunu söylemekte sorun yoktur (kalbinizdeki ikisinin doğasını anlayın).
Doğa: Python kapanışları, dekoratörlerin gerçek bir alt kümesidir, yani dekoratörler daha geniş bir kavramdır, neden ikisi arasındaki fark ve bağlantıya gelince, bir sonraki makalede ayrıntılı olarak açıklayacağım. Sonraki makale için referans:
Gelişmiş Python Programlama-Dekoratör Ayrıntılı Açıklama (Bölüm 2)
Sadece bu değil, yukarıda uygulanan dekoratörler işlevler içindir.Aslında, Python dekoratörleri "işlevler" veya "sınıflar" olabilir ve dekore edilmiş nesneler "işlevler" veya "sınıflar" da olabilir. Dört eşleştirme durumu vardır:
İşlev dekorasyon işlevi
İşlev dekorasyon sınıfı
Sınıf dekorasyon işlevi
Sınıf dekorasyonu
Her biri ayrıntılı olarak nasıl uygulanır? Aslında tasarım fikirleri birbirine benziyor ama uygulama detayları biraz farklı, detayları öğrenmek istiyorsanız bir dahaki sefere dinleyin! ! !
Bir sonraki uyarı:
Dekoratörler ve kapanışlar arasındaki bağlantı ve fark
Dört tip dekoratörün eşleştirilmesinin gerçekleştirilmesi
····
"Python Röportaj Koleksiyonu" "Python Çekirdek Programlama Üçüncü Sürüm" "Veri Analizi İkinci Sürüm için Python Kullanın"