Python, del veya delattr'da hangisi daha iyi?


181

Bu aptalca olabilir, ama bir süredir beynimin arkasını sallıyor.

Python, nesnelerden nitelikleri silmek için iki yerleşik yol sunar, del komut sözcüğü ve delattr yerleşik işlevi. Ben delattr tercih çünkü biraz daha açık olduğunu düşünüyorum:

del foo.bar
delattr(foo, "bar")

Ama ben aralarında kaput altı farklar olup olmadığını merak ediyorum.

Yanıtlar:


266

Birincisi ikincisinden daha etkilidir. del foo.bariki bayt kod talimatını derler:

  2           0 LOAD_FAST                0 (foo)
              3 DELETE_ATTR              0 (bar)

oysa delattr(foo, "bar")beş tane alır:

  2           0 LOAD_GLOBAL              0 (delattr)
              3 LOAD_FAST                0 (foo)
              6 LOAD_CONST               1 ('bar')
              9 CALL_FUNCTION            2
             12 POP_TOP             

Bu, biraz daha hızlı ilk çalışmaya dönüşür (ancak büyük bir fark değil - makinemde .15 μs).

Diğerlerinin söylediği gibi, ikinci formu yalnızca sildiğiniz özellik dinamik olarak belirlendiğinde kullanmalısınız.

[Derleyicinin kullanabileceği bir işlevin içinde oluşturulan bayt kodu talimatlarını göstermek için düzenlendi LOAD_FASTve LOAD_GLOBAL]


6
Bunu oluşturmak için hangi aracı kullandınız?
Triptik

33
disModülü. python -m disBazı kodları kullanarak ve yazarak komut satırından çalıştırabilir veya ile bir işlevi ayırabilirsiniz dis.dis().
Miles

15
Erken optimizasyon tüm kötülüklerin köküdür. ;-) Ama evet, haklısın elbette.
Lennart Regebro

26
Peki para sevgisinin erken optimizasyon olduğu anlaşılıyor mu?
John Fouhy

5
Erken optimizasyon, para işleme sevgisinin bir alt kümesidir, çünkü işlem gücüne daha az harcama yapmaya çalışıyorsunuz :)
Rob Grant

41
  • del daha açık ve etkilidir;
  • delattr dinamik öznitelik silmeye izin verir.

Aşağıdaki örnekleri düşünün:

for name in ATTRIBUTES:
    delattr(obj, name)

veya:

def _cleanup(self, name):
    """Do cleanup for an attribute"""
    value = getattr(self, name)
    self._pre_cleanup(name, value)
    delattr(self, name)
    self._post_cleanup(name, value)

Bunu del ile yapamazsın .


2
İkincisini del ile yapabilirsiniz. del self.__dict__[name], tabii ki meta sınıfı ile devam eden komik iş yok
smac89

17

Şüphesiz birincisi. Bana göre bu foo.bardaha iyi olup olmadığını sormak gibidir getattr(foo, "bar")ve kimsenin bu soruyu sorduğunu sanmıyorum :)


3
Eminim orada foo.bar yerine getattr (foo, "bar") tercih edecek en az bir kişi var. Kabul ettim, onlarla aynı fikirde değilim. Ancak bu kişi hala tartışmasız birincisi değil.
Jason Baker

3
@ Jason Öyleyse hiçbir şey, ifadeyi yorumlamanızla diğer her şeyden "tartışmasız daha iyi" değildir. Bu "tartışmasız" mükemmel makul bir kullanım olduğunu düşünüyorum.
Phob

26
özelliğin mevcut olmaması ve try / hariç blokları yazmak zorunda kalmadan varsayılan bir değer ayarlamak istediğinizde getattr tercih edilir. yani. gettattr (foo, "bar", Yok)
Marc Gibbons

2
@MarcGibbons: Bekle, bu bir şey mi? Deseni her zaman kullandım if hasattr(obj, 'var') and obj.var == ...... Bunu if getattr(obj, 'var', None) == ...çoğu durumda azaltabilirim ! Biraz daha kısa ve okunması daha kolay.
ArtOfWarfare

@ArtOfWarfare hasattraslında çağırıyorgetattr
cheniel

14

Bu gerçekten bir tercih meselesi, ama ilki muhtemelen tercih edilebilir. İkincisini yalnızca önceden sildiğiniz özelliğin adını bilmiyorsanız kullanırsınız.


5

Tıpkı getattr ve setattr gibi, delattr yalnızca özellik adı bilinmiyorsa kullanılmalıdır.

Bu anlamda, bu gibi mevcut yerleşik daha düşük bir seviyede işlevsellik normalde olması daha erişime kullanıldığını birkaç piton özelliklerine kabaca eşdeğer __import__yerine importve operator.addyerine+


3

İç çalışmalardan emin değilim, ancak kodun yeniden kullanılabilirliği ve bir iş arkadaşı bakış açısı olmayın, del kullanın. Diğer dillerden gelen insanlar da daha açık ve anlaşılır.


1

Eğer delattrdaha açık olduğunu düşünüyorsanız neden neden getattrher zaman kullanmıyorsunuz?object.attr ?

Kaputun altında gelince ... tahmininiz benim kadar iyi. Eğer önemli ölçüde daha iyi değilse.


1

Bu eski bir soru, ama ben 2 sent koymak istiyorum.

Rağmen, del foo.bar daha zarif, bazen ihtiyacınız olacak delattr(foo, "bar"). Diyelim ki, kullanıcının adı yazarak nesnedeki herhangi bir üyeyi dinamik olarak silmesine izin veren etkileşimli bir komut satırı arabiriminiz varsa, ikinci formu kullanmaktan başka seçeneğiniz yoktur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.