Cái nào tốt hơn trong python, del hay delattr?


180

Điều này có thể là ngớ ngẩn, nhưng nó đã cằn nhằn phía sau bộ não của tôi trong một thời gian.

Python cung cấp cho chúng ta hai cách dựng sẵn để xóa các thuộc tính khỏi các đối tượng, từ lệnh delhàm dựng sẵn delattr . Tôi thích delattr vì tôi nghĩ nó rõ ràng hơn một chút:

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

Nhưng tôi tự hỏi liệu giữa họ có thể có sự khác biệt nào không.

Câu trả lời:


265

Cái thứ nhất hiệu quả hơn cái thứ hai. del foo.barbiên dịch thành hai hướng dẫn mã byte:

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

trong khi delattr(foo, "bar")mất năm:

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

Điều này chuyển thành lần đầu tiên chạy nhanh hơn một chút (nhưng nó không phải là một sự khác biệt lớn - .15 μ trên máy của tôi).

Giống như những người khác đã nói, bạn thực sự chỉ nên sử dụng hình thức thứ hai khi thuộc tính mà bạn đang xóa được xác định một cách linh hoạt.

[Đã chỉnh sửa để hiển thị các hướng dẫn mã byte được tạo bên trong một hàm, trong đó trình biên dịch có thể sử dụng LOAD_FASTLOAD_GLOBAL]


6
Công cụ nào bạn đã sử dụng để tạo ra điều này?
Triptych

33
Các dismô-đun. Bạn có thể chạy nó từ dòng lệnh bằng cách sử dụng python -m disvà nhập một số mã hoặc tháo rời một chức năng với dis.dis().
Miles

15
Tối ưu hóa sớm là gốc rễ của mọi tội lỗi. ;-) Nhưng tất nhiên, bạn đúng, tất nhiên.
Lennart Regebro

26
.. nó có theo dõi rằng tình yêu tiền là tối ưu hóa sớm?
John Fouhy

5
Tối ưu hóa sớm là một tập hợp con của tình yêu tiền bạc, vì điều đó có nghĩa là bạn đang cố gắng chi tiêu ít hơn cho sức mạnh xử lý :)
Rob Grant

41
  • del rõ ràng và hiệu quả hơn;
  • delattr cho phép xóa thuộc tính động.

Hãy xem xét các ví dụ sau:

for name in ATTRIBUTES:
    delattr(obj, name)

hoặc là:

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)

Bạn không thể làm điều đó với del .


2
Bạn có thể làm cái thứ hai với del. del self.__dict__[name], giả sử tất nhiên không có hoạt động kinh doanh hài hước nào xảy ra với lớp meta
smac89

17

Không thể nghi ngờ là trước đây. Theo quan điểm của tôi, điều này giống như hỏi liệu foo.barcó tốt hơn không getattr(foo, "bar"), và tôi không nghĩ có ai hỏi câu hỏi đó :)


3
Tôi chắc chắn có ít nhất một người ở ngoài đó thích getattr (foo, "bar") hơn foo.bar. Cấp, tôi sẽ không đồng ý với họ. Nhưng một người vẫn đủ để khiến nó không còn nghi ngờ gì nữa.
Jason Baker

3
@Jason Sau đó, không có gì là "tốt hơn không thể nghi ngờ" hơn bất cứ điều gì khác bằng cách giải thích cụm từ của bạn. Tôi nghĩ rằng đây là một cách sử dụng hoàn toàn hợp lý của "không nghi ngờ gì".
Phob

26
getattr thích hợp hơn khi có khả năng thuộc tính không tồn tại và bạn muốn đặt giá trị mặc định mà không phải viết thử / ngoại trừ các khối. I E. gettattr (foo, "bar", Không ai)
Marc Gibbons

2
@MarcG Ribbon: Đợi đã, đó là một điều? Tôi đã luôn sử dụng mô hình if hasattr(obj, 'var') and obj.var == ...... Tôi chỉ có thể giảm điều này xuống, if getattr(obj, 'var', None) == ...trong hầu hết các trường hợp! Hơi ngắn và dễ đọc hơn, tôi nghĩ vậy.
ArtOfWarfare

@ArtOfWarfare hasattrthực sự gọigetattr
cheniel

14

Đó thực sự là một vấn đề ưu tiên, nhưng điều đầu tiên có lẽ là thích hợp hơn. Tôi chỉ sử dụng cái thứ hai nếu bạn không biết tên thuộc tính mà bạn đang xóa trước thời hạn.


5

Cũng giống như getattr và setattr, delattr chỉ nên được sử dụng khi không biết tên thuộc tính.

Theo nghĩa đó, nó gần tương đương với một số tính năng python được sử dụng để truy cập chức năng tích hợp ở mức thấp hơn mức bạn thường có, chẳng hạn như __import__thay vì importoperator.addthay vì+


3

Không chắc chắn về hoạt động bên trong, nhưng từ khả năng sử dụng lại mã và không phải là một quan điểm đồng nghiệp giật, sử dụng del. Nó rõ ràng hơn và được hiểu bởi những người đến từ các ngôn ngữ khác.


1

Nếu bạn nghĩ delattrlà rõ ràng hơn, thì tại sao không sử dụng getattrtất cả thời gian hơn là object.attr?

Đối với dưới mui xe ... dự đoán của bạn là tốt như của tôi. Nếu không tốt hơn đáng kể.


1

Đó là một câu hỏi cũ, nhưng tôi muốn đặt 2 xu của tôi vào.

Mặc dù, del foo.barlà thanh lịch hơn, đôi khi bạn sẽ cần delattr(foo, "bar"). Giả sử, nếu bạn có giao diện dòng lệnh tương tác cho phép người dùng tự động xóa bất kỳ thành viên nào trong đối tượng bằng cách nhập tên , thì bạn không có lựa chọn nào khác ngoài sử dụng biểu mẫu sau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.