python、del、delattrのどちらが優れていますか?


180

これはばかげているかもしれませんが、しばらくの間、私の脳の後ろを悩ませてきました。

Pythonには、オブジェクトから属性を削除するための組み込みの方法が2つあります。それは、delコマンドワードとdelattr組み込み関数です。私はそれがもう少し明示的だと思うので、私はdelattrを好みます:

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

しかし、それらの間に実際の違いがあるのではないかと思います。

回答:


265

1つ目は2つ目よりも効率的です。 del foo.bar2つのバイトコード命令にコンパイルします。

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

一方、delattr(foo, "bar")5 つかかります。

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

これは、最初の実行がわずかに速くなることを意味します(ただし、大きな違いはありません。私のマシンでは0.15μs)。

他の人が言ったように、削除する属性が動的に決定される場合にのみ、実際には2番目の形式を使用する必要があります。

[コンパイラが使用できる機能、内部で発生したバイトコード命令を表示する編集LOAD_FASTとをLOAD_GLOBAL


6
これを生成するためにどのツールを使用しましたか?
トリプティク

33
disモジュール。コマンドラインを使用python -m disしてコードを入力したり、関数を逆アセンブルしたりできますdis.dis()
マイル

15
時期尚早の最適化は、すべての悪の根源です。;-)はい、もちろん、あなたは正しいです。
Lennart Regebro 2009

26
..それでは、お金への愛は時期尚早の最適化であるということになりますか?
John Fouhy、

5
時期尚早な最適化はお金への愛の一部です。それは、処理能力に費やすコストを削減しようとしていることを意味します:)
Rob Grant

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)

delではできません。


2
あなたはデルで2番目のものを行うことができます。del self.__dict__[name]、もちろん、メタクラスで面白いビジネスが行われていないと仮定
smac89

17

間違いなく前者。私の意見では、これはfoo.barがより良いかどうかを尋ねるようなものgetattr(foo, "bar")であり、誰もその質問をしているとは思わない:)


3
foo.barよりgetattr(foo、 "bar")を好む人が少なくとも1人はいると思います。確かに、私は彼らに同意しません。しかし、その1人で問題なく前者になることはできます。
Jason Baker、

3
@ジェイソンそれでは、あなたのフレーズの解釈によって、他の何よりも「間違いなく優れている」ものはありません。これは「疑いなく」の完全に合理的な使用法だと思います。
フォブ2013年

26
getattrは、プロパティが存在しない可能性があり、try / exceptブロックを記述せずにデフォルト値を設定したい場合に適しています。すなわち。gettattr(foo、 "bar"、None)
マークギボンズ

2
@MarcGibbons:待って、それって事?私はいつもパターンを使用してきましたif hasattr(obj, 'var') and obj.var == ...... if getattr(obj, 'var', None) == ...ほとんどの場合、これを単に減らすことができます!少し短くて読みやすいと思います。
ArtOfWarfare

@ArtOfWarfareがhasattr実際に電話をかけるgetattr
シェニエル

14

それは本当に好みの問題ですが、おそらく最初の方が望ましいでしょう。事前に削除する属性の名前がわからない場合にのみ、2番目のものを使用します。


5

getattrやsetattrと同様に、delattrは属性名が不明な場合にのみ使用してください。

その意味では、__import__代わりにimportoperator.add代わりになど、通常よりも低いレベルで組み込み機能にアクセスするために使用されるいくつかのpython機能とほぼ同じです。+


3

内部の仕組みについてはわかりませんが、コードの再利用性から、同僚のジャークではないため、delを使用してください。他の言語から来た人にもわかりやすく理解されています。


1

あなたdelattrがより明白であると思うなら、なぜgetattrいつもではなくいつも使用しないのobject.attrですか?

裏側については...あなたの推測は私のものと同じです。大幅に改善されない場合。


1

古い質問ですが、2セント入れたいと思います。

del foo.barはよりエレガントですが、場合によってはが必要になりますdelattr(foo, "bar")。たとえば、名前を入力してオブジェクトのメンバーを動的に削除できるインタラクティブなコマンドラインインターフェースがある場合、後者の形式を使用するしかありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.