Mana yang lebih baik dalam python, del atau delattr?


180

Ini mungkin konyol, tetapi sudah mengganggu bagian belakang otak saya untuk sementara waktu.

Python memberi kita dua cara bawaan untuk menghapus atribut dari objek, kata perintah del dan fungsi bawaan delattr . Saya lebih suka delattr karena menurut saya ini sedikit lebih eksplisit:

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

Tapi saya bertanya-tanya apakah mungkin ada perbedaan di antara mereka.

Jawaban:


265

Yang pertama lebih efisien daripada yang kedua. del foo.barkompilasi ke dua instruksi bytecode:

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

sedangkan delattr(foo, "bar")dibutuhkan lima:

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

Ini diterjemahkan menjadi yang pertama berjalan sedikit lebih cepat (tapi itu bukan perbedaan besar - .15 μs pada mesin saya).

Seperti yang telah dikatakan orang lain, Anda harus benar-benar hanya menggunakan formulir kedua ketika atribut yang Anda hapus ditentukan secara dinamis.

[Diedit untuk menampilkan instruksi bytecode yang dihasilkan di dalam suatu fungsi, tempat kompiler dapat menggunakan LOAD_FASTdan LOAD_GLOBAL]


6
Alat apa yang Anda gunakan untuk menghasilkan ini?
Triptych

33
The dismodul. Anda dapat menjalankannya dari baris perintah menggunakan python -m disdan mengetik beberapa kode, atau membongkar suatu fungsi dengan dis.dis().
Miles

15
Optimalisasi prematur adalah akar dari semua kejahatan. ;-) Tapi ya, Anda benar, tentu saja.
Lennart Regebro

26
..jadi apakah cinta uang itu adalah pengoptimalan prematur?
John Fouhy

5
Optimalisasi prematur adalah bagian dari kecintaan terhadap uang, karena itu berarti Anda mencoba untuk menghabiskan lebih sedikit pada kekuatan pemrosesan :)
Rob Grant

41
  • del lebih eksplisit dan efisien;
  • delattr memungkinkan penghapusan atribut dinamis.

Perhatikan contoh-contoh berikut:

for name in ATTRIBUTES:
    delattr(obj, name)

atau:

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)

Anda tidak dapat melakukannya dengan del .


2
Anda dapat melakukan yang kedua dengan del. del self.__dict__[name], dengan asumsi tentu saja tidak ada bisnis lucu yang terjadi dengan kelas meta
smac89

17

Tidak diragukan lagi yang pertama. Dalam pandangan saya ini seperti menanyakan apakah foo.barlebih baik daripada getattr(foo, "bar"), dan saya tidak berpikir ada orang yang menanyakan pertanyaan itu :)


3
Saya yakin ada setidaknya satu orang di luar sana yang lebih suka getattr (foo, "bar") daripada foo.bar. Memang, saya tidak akan setuju dengan mereka. Tetapi satu orang itu masih cukup untuk membuatnya tidak diragukan lagi sebagai yang pertama.
Jason Baker

3
@Jason Maka tidak ada yang "tidak diragukan lagi lebih baik" dari apa pun oleh interpretasi Anda terhadap frasa. Saya pikir ini adalah penggunaan wajar "tidak diragukan lagi".
Phob

26
getattr lebih disukai ketika ada kemungkinan bahwa properti tidak ada dan Anda ingin menetapkan nilai default tanpa harus menulis blok coba / kecuali. yaitu. gettattr (foo, "bar", None)
Marc Gibbons

2
@MarcGibbons: Tunggu, itu masalahnya? Saya selalu menggunakan polanya if hasattr(obj, 'var') and obj.var == ...... Saya hanya bisa mengurangi ini, if getattr(obj, 'var', None) == ...dalam banyak kasus! Agak lebih pendek dan lebih mudah dibaca, saya pikir.
ArtOfWarfare

@ ArtOfWarfare hasattrsebenarnya menelepongetattr
cheniel

14

Ini benar-benar masalah preferensi, tetapi yang pertama mungkin lebih disukai. Saya hanya akan menggunakan yang kedua jika Anda tidak tahu nama atribut yang Anda hapus sebelumnya.


5

Sama seperti getattr dan setattr, delattr hanya boleh digunakan ketika nama atribut tidak dikenal.

Dalam hal itu, ini kira-kira setara dengan beberapa fitur python yang digunakan untuk mengakses fungsi bawaan pada tingkat yang lebih rendah dari yang biasanya Anda miliki, seperti __import__bukannya importdan operator.addbukannya+


3

Tidak yakin tentang cara kerja bagian dalam, tetapi dari penggunaan kembali kode dan jangan menjadi rekan kerja yang brengsek, gunakan del. Ini lebih jelas dan dipahami oleh orang-orang yang datang dari bahasa lain juga.


1

Jika menurut Anda delattrlebih eksplisit, mengapa tidak digunakan getattrsepanjang waktu object.attr?

Adapun di bawah tenda ... tebakanmu sama baiknya dengan tebakanku. Jika tidak jauh lebih baik.


1

Ini adalah pertanyaan lama, tetapi saya ingin memasukkan 2 sen saya.

Padahal, del foo.barlebih elegan, kadang-kadang Anda butuhkan delattr(foo, "bar"). Katakanlah, jika Anda memiliki antarmuka baris perintah interaktif yang memungkinkan pengguna untuk secara dinamis menghapus anggota di objek dengan mengetikkan namanya , maka Anda tidak punya pilihan selain menggunakan formulir yang terakhir.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.