回答:
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】
disモジュール。コマンドラインを使用python -m disしてコードを入力したり、関数を逆アセンブルしたりできますdis.dis()。
                    次の例を検討してください。
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ではできません。
del self.__dict__[name]、もちろん、メタクラスで面白いビジネスが行われていないと仮定
                    間違いなく前者。私の意見では、これはfoo.barがより良いかどうかを尋ねるようなものgetattr(foo, "bar")であり、誰もその質問をしているとは思わない:)
if hasattr(obj, 'var') and obj.var == ...... if getattr(obj, 'var', None) == ...ほとんどの場合、これを単に減らすことができます!少し短くて読みやすいと思います。
                    hasattr実際に電話をかけるgetattr