Co jest lepsze w Pythonie, Del czy Delattr?


181

To może być głupie, ale od jakiegoś czasu męczy mnie tył mózgu.

Python daje nam dwa wbudowane sposoby usuwania atrybutów z obiektów, słowo polecenia del i funkcję wbudowaną delattr . Wolę delattr, ponieważ wydaje mi się, że jest nieco bardziej wyraźny:

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

Ale zastanawiam się, czy mogą istnieć między nimi ukryte różnice.

Odpowiedzi:


266

Pierwsza jest bardziej wydajna niż druga. del foo.barkompiluje się do dwóch instrukcji kodu bajtowego:

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

podczas gdy delattr(foo, "bar")zajmuje pięć:

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

Przekłada się to na pierwsze uruchomienie nieco szybciej (ale nie jest to duża różnica - na moim komputerze 0,15 μs).

Jak powiedzieli inni, tak naprawdę powinieneś używać drugiego formularza tylko wtedy, gdy usuwany atrybut jest określany dynamicznie.

[Edytowano, aby pokazać instrukcje kodu bajtowego wygenerowane wewnątrz funkcji, w przypadku których kompilator może używać LOAD_FASTi LOAD_GLOBAL]


6
Jakiego narzędzia użyłeś do wygenerowania tego?
— Tryptyk

33
disModuł. Możesz go uruchomić z linii poleceń używając python -m disi wpisując jakiś kod lub zdemontować funkcję za pomocą dis.dis().
— Miles

15
Przedwczesna optymalizacja jest źródłem wszelkiego zła. ;-) Ale tak, oczywiście masz rację.
— Lennart Regebro

26
.. czy z tego wynika, że ​​miłość do pieniędzy to przedwczesna optymalizacja?
— John Fouhy,

5
Przedwczesna optymalizacja to podzbiór zamiłowania do pieniędzy, ponieważ oznacza to, że starasz się wydawać mniej na moc obliczeniową :)
— Rob Grant

41
  • del jest bardziej wyraźny i skuteczny;
  • delattr umożliwia dynamiczne usuwanie atrybutów.

Rozważ następujące przykłady:

for name in ATTRIBUTES:
    delattr(obj, name)

lub:

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)

Nie możesz tego zrobić z del .


2
Drugą możesz zrobić za pomocą del. del self.__dict__[name], zakładając oczywiście, że z klasą meta nie dzieje się żaden śmieszny interes
— smac89

17

Bezsprzecznie ten pierwszy. Moim zdaniem to tak, jakby pytać, czy foo.barjest lepsze niż getattr(foo, "bar"), i nie sądzę, żeby ktokolwiek zadawał to pytanie :)


3
Jestem pewien, że istnieje przynajmniej jedna osoba, która wolałaby getattr (foo, "bar") od foo.bar. Zgoda, nie zgodziłbym się z nimi. Ale ta jedna osoba wciąż wystarczy, aby nie bezsprzecznie była pierwsza.
— Jason Baker

3
@Jason W takim razie nic nie jest „bezsprzecznie lepsze” niż cokolwiek innego dzięki twojej interpretacji wyrażenia. Myślę, że jest to całkiem rozsądne użycie słowa „bez wątpienia”.
— Fob

26
getattr jest preferowane, gdy istnieje możliwość, że właściwość nie istnieje i chcesz ustawić wartość domyślną bez konieczności pisania bloków try / except. to znaczy. gettattr (foo, "bar", None)
— Marc Gibbons

2
@MarcGibbons: Czekaj, to jest rzecz? Zawsze używałem tego wzorca if hasattr(obj, 'var') and obj.var == ...... if getattr(obj, 'var', None) == ...W większości przypadków mogłem to po prostu zredukować ! Myślę, że trochę krótszy i łatwiejszy do odczytania.
— ArtOfWarfare

@ArtOfWarfare hasattrfaktycznie dzwonigetattr
— cheniel

14

To naprawdę kwestia preferencji, ale pierwsza jest prawdopodobnie lepsza. Drugiego użyłbym tylko wtedy, gdy nie znasz nazwy atrybutu, który usuwasz z wyprzedzeniem.


5

Podobnie jak getattr i setattr, delattr powinien być używany tylko wtedy, gdy nazwa atrybutu jest nieznana.

W tym sensie jest to z grubsza odpowiednik kilku funkcji Pythona, które są używane do uzyskiwania dostępu do wbudowanych funkcji na niższym poziomie niż zwykle dostępne, na przykład __import__zamiast importi operator.addzamiast+


3

Nie jestem pewien co do wewnętrznego działania, ale z perspektywy ponownego wykorzystania kodu i nie bądź głupim współpracownikiem, użyj del. Jest to bardziej jasne i zrozumiałe również dla osób pochodzących z innych języków.


1

Jeśli uważasz, że delattrjest bardziej wyraźny, dlaczego nie używać go przez getattrcały czas, a nie object.attr?

Co do miejsca pod maską ... Twoje przypuszczenia są równie dobre jak moje. Jeśli nie znacznie lepiej.


1

To stare pytanie, ale chciałbym włożyć swoje 2 centy.

Chociaż del foo.barjest bardziej elegancki, czasami będziesz potrzebować delattr(foo, "bar"). Powiedzmy, że jeśli masz interaktywny interfejs wiersza poleceń, który umożliwia użytkownikowi dynamiczne usuwanie dowolnego elementu w obiekcie przez wpisanie jego nazwy , nie masz innego wyboru, jak tylko użyć tej drugiej formy.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.