2015-01-12 25 views
7

Çağrılan zamanların sayısını koruyan bir işlev oluşturmaya çalışıyorum ve bilgilerin işlevin içinde kalmasını istiyorum. ben şöyle bir sarmalayıcı oluşturma çalıştı:Bir işlevin bir özniteliğini kendi gövdesi içinde değiştirin.

def keep_count(f): 
    f.count = 0 
    @functools.wraps(f) 
    def wrapped_f(*args, **kwargs): 
     f(*args, **kwargs) 
     f.count += 1 
    return wrapped_f 

@keep_count 
def test_f(*args, **kwargs): 
    print(args, kwargs) 

Ben o iş düşündüm ama 'function' object has no attribute 'count' diyerek bir AttributeError aldık.

Zaten sorunu anladım: O dekoratör (keep_count dekoratör iç tanımlanır) wrapped_f için eşit benim test_f setleri çünkü, ben artık test_f atıfta beri kullanılan orijinal f sayısını, artan ediyorum yeni işleve.

Bunu çok fazla korsanlık yapmadan yapmanın bir yolu var mı?

+2

Neden bir sınıf kullanmıyorsunuz? Bu, sınıfın ne anlama geldiğidir - –

+0

@AdamSmith işlevlerini çalıştırmak için durumsal bir bağlam oluşturma Python işlevleri nesne olduklarından, durumu da koruyamazlar mı? – wegry

+0

@wegry yapabilirler. İki tahtayı birbirine yapıştırmak için bir çift kerpeten kullanabilirsiniz :) –

cevap

9

Özniteliği f yerine wrapped_f olarak ayarlayın. Bu fonksiyon tanımlama sonrası ilk count ayarlamak için gerektirir, ama bu hiç önemli değil: En dekore fonksiyonu ile Ardından

def keep_count(f): 
    @functools.wraps(f) 
    def wrapped_f(*args, **kwargs): 
     f(*args, **kwargs) 
     wrapped_f.count += 1 
    wrapped_f.count = 0 
    return wrapped_f 

: wrapped_fkeep_count içinde yerel bir değişken olduğu için

>>> test_f() 
() {} 
>>> test_f.count 
1 
>>> test_f() 
() {} 
>>> test_f.count 
2 

Bu çalışır. wrapped_f gövdesi, wrapped_f'a bir başvuru içerdiğinden, wrapped_f'un kendisine erişmesine izin veren bir kapatma alır.

+0

Vay, her zaman kendi içinde bir işlev kullanamayacağımı düşünmüştüm ... Sonra tekrar hatırladığım kadarıyla yinelemeli fonksiyonlar kullanıyorum, bunu neden yapamadığımı göremiyorum Oo Sadece bir çeşit yanlış anlaşılma yaşadım. Cevabınız için teşekkürler, sanırım eski şeylerde her gün yeni bir şeyler öğreniyorsunuz! :) –

+2

@MarkusMeskanen: Daha fazla veya daha az şey yapabilirsin, ama buna dikkat etmelisin, çünkü isim aramaları farklı zamanlarda gerçekleşiyor. – BrenBarn

+0

Ah evet, teşekkürler ... :) Kazı yapmaya devam edeceğim, elimden geldiğince kabul edeceğim. –

İlgili konular