Що краще в python, del або delattr?


181

Це може бути нерозумно, але це вже деякий час нанизує задню частину мого мозку.

Python дає нам два вбудовані способи видалення атрибутів з об’єктів, командне слово del та вбудовану функцію delattr . Я віддаю перевагу delattr, тому що я думаю, що це трохи більш чітко:

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

Але мені цікаво, чи можуть бути між ними непомітні відмінності.

Відповіді:


266

Перший є більш ефективним, ніж другий. del foo.barкомпілює дві інструкції щодо байт-коду:

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

тоді як delattr(foo, "bar")займає п'ять:

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

Це означає, що перший працює трохи швидше (але це не величезна різниця - .15 мкс на моїй машині).

Як і інші, сказати, ви повинні реально використовувати другу форму лише тоді, коли атрибут, який ви видаляєте, визначається динамічно.

[Відредаговано для відображення інструкцій байт-коду, сформованих всередині функції, де компілятор може використовувати LOAD_FASTі LOAD_GLOBAL]


6
Який інструмент ви використали для створення цього?
Триптих

33
disМодуль. Ви можете запустити його з командного рядка, використовуючи python -m disі ввівши якийсь код, або розібрати функцію за допомогою dis.dis().
Майлз

15
Передчасна оптимізація - корінь усього зла. ;-) Але так, ви праві, звичайно.
Леннарт Регебро

26
..звідси випливає, що любов до грошей - передчасна оптимізація?
Джон Фухі

5
Передчасна оптимізація - це підмножина любові до грошей, оскільки це означає, що ви намагаєтесь витратити менше на обробку потужності :)
Роб Грант

41
  • del більш чіткий і ефективний;
  • delattr дозволяє динамічне видалення атрибутів.

Розглянемо наступні приклади:

for name in ATTRIBUTES:
    delattr(obj, name)

або:

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)

Ви не можете зробити це з дель .


2
Ви можете зробити другий за допомогою del. del self.__dict__[name], якщо припустити, що з мета-класом не відбувається жодного смішного бізнесу
smac89

17

Безперечно колишній. На мій погляд, це як запитання, чи foo.barкраще getattr(foo, "bar"), і я не думаю, що це питання хтось задає :)


3
Я впевнений, що там хоча б одна людина, яка вважає за краще getattr (foo, "bar") над foo.bar. Зрозуміло, я б не погодився з ними. Але однієї людини все-таки достатньо, щоб зробити її не безперечно першою.
Джейсон Бейкер

3
@Jason Тоді ніщо не є "безперечно кращим", ніж будь-що інше з вашого тлумачення фрази. Я думаю, що це цілком розумне використання "безперечно".
Phob

26
getattr є кращим, коли є можливість, що властивість не існує, і ви хочете встановити значення за замовчуванням без необхідності писати спробувати / крім блоків. тобто. gettattr (foo, "bar", None)
Marc Gibbons

2
@MarcGibbons: Зачекайте, це річ? Я завжди використовував шаблон if hasattr(obj, 'var') and obj.var == ...... Я міг просто звести це до if getattr(obj, 'var', None) == ...більшості випадків! Трохи коротший і легший для читання, я думаю.
ArtOfWarfare

@ArtOfWarfare hasattrнасправді телефонуєgetattr
cheniel

14

Це дійсно питання переваги, але перший, мабуть, кращий. Я використовую другий лише тоді, коли ви не знаєте назви атрибута, який ви видаляєте достроково.


5

Як і getattr і setattr, delattr слід використовувати лише тоді, коли ім'я атрибута невідоме.

У цьому сенсі це приблизно еквівалентно декільком функціям python, які використовуються для доступу до вбудованої функціональності на нижчому рівні, ніж зазвичай у вас є, наприклад __import__замість importі operator.addзамість+


3

Не впевнений у внутрішніх роботах, але з точки зору використання коду та не будьте перспективним колегою, використовуйте del. Це більш зрозуміло і зрозуміло людям, які походять з інших мов.


1

Якщо ви вважаєте, що delattrце більш чітко, то чому б не використовувати getattrвесь час, а не object.attr?

Щодо під капотом ... ваша здогадка така ж гарна, як і моя. Якщо не значно краще.


1

Це старе питання, але я хотів би покласти свої 2 центи.

Хоча, del foo.barє більш елегантним, часом вам знадобиться delattr(foo, "bar"). Скажімо, якщо у вас є інтерактивний інтерфейс командного рядка, який дозволяє користувачеві динамічно видаляти будь-який член об’єкта, ввівши ім'я , то вам не залишається іншого вибору, як використовувати останню форму.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.