Trong Python 3.4+, tại sao tôi nên sử dụng namtuple trên SimpleNamespace khi không sử dụng dict, chúng có vẻ rất giống nhau


11

Tại một thời điểm nào đó, bạn có thể đi qua các chức năng với rất nhiều đối số. Đôi khi nó có ý nghĩa để kết hợp một số đối số thành siêu đối số. Tôi thường làm điều này với các bài viết, nhưng bây giờ tôi đang tìm cách tốt hơn để làm điều đó.

Tôi muốn biến ...

def do_something(ax, ay, az, bu, bv, c):
    # Do something

... vào ...

def do_something(a, b, c):
    # Do something

... Nơi abchứa các phân nhóm của họ.

Một cách để làm điều này là làm:

A = namedtuple('A', 'x, y, z')
a = A(ax, ay, az)
B = namedtuple('B', 'u, v')
b = B(bu, bv)

Tuy nhiên, điều này có vẻ đơn giản hơn:

a = SimpleNamespace(x=ax, y=ay, z=az)
b = SimpleNamespace(u=bu, v=bv)

Hạn chế là gì? Thực tế đó abkhông được đánh máy tốt? Chúng không phải là vật A và B?

(Btw, đừng lo lắng về tên biến. Tôi thường không sử dụng làm tên biến ngắn.)


1
Không có nhược điểm nào cả, chúng chỉ là những thứ khác nhau. Đối với startuples starter là không thể thay đổi trong khi không gian tên là có thể thay đổi. Là đột biến tốt hơn hay tồi tệ hơn không thể thay đổi? Nó phụ thuộc vào những gì bạn cần hoặc muốn, trong nhiều trường hợp nó không thành vấn đề. Hàm của bạn có thể sẽ làm việc với bất kỳ đối tượng nào có các thuộc tính bắt buộc, làm thế nào để xây dựng nó tùy thuộc vào người gọi.
Ngừng làm hại Monica

@Goyo Cảm ơn bạn. Điều "nhược điểm" là một cách nói vụng về. Tôi không có ý ám chỉ cái này vốn dĩ tốt hơn cái kia. Chỉ muốn những ưu và nhược điểm. Cảm ơn, một lần nữa.
André Christoffer Andersen

1
Không phải dòng thứ 4 trông giống như "b = B (bu, bv)"?
Alen Siljak

@AlenSiljak Có nên. Tôi sẽ sửa nó ngay.
André Christoffer Andersen

Câu trả lời:


21

SimpleNamespacevề cơ bản chỉ là một mặt tiền đẹp trên đầu từ điển. Nó cho phép bạn sử dụng các thuộc tính thay vì các khóa chỉ mục. Điều này là tốt đẹp vì nó siêu linh hoạt và dễ dàng để thao tác.

Nhược điểm của tính linh hoạt đó là nó không cung cấp bất kỳ cấu trúc nào. Không có gì để ngăn ai đó gọi SimpleNamespace(x=ax, y=ay)(và del a.ztại một số điểm sau đó). Nếu trường hợp này được chuyển đến chức năng của bạn, ngoại lệ xảy ra khi bạn cố gắng truy cập vào trường.

Ngược lại, namedtuplecho phép bạn tạo một kiểu có cấu trúc. Loại này sẽ có một tên và nó sẽ biết những lĩnh vực mà nó được cho là có. Bạn sẽ không thể tạo một ví dụ mà không có từng trường đó và chúng không thể bị xóa sau đó. Ngoài ra, ví dụ là bất biến, vì vậy bạn sẽ biết rằng giá trị trong a.xsẽ luôn giống nhau.

Tùy thuộc vào bạn để quyết định xem bạn có cần sự linh hoạt SimpleNamespacemang lại cho bạn hay không, nếu bạn muốn có cấu trúc và đảm bảo được cung cấp bởi namedtuple.


2

Tôi thực sự thích câu trả lời về cấu trúc so với không, vì vậy tôi chỉ cung cấp một ví dụ cụ thể dưới đây.

SimpleNamespacesẽ chấp nhận các khóa bắt đầu bằng _. Nếu bạn đang tìm kiếm một cách nhanh chóng và dễ dàng để biến, giả sử, JSON bạn không điều khiển thành các đối tượng có tên trường, thì điều này rất tiện dụng:

d = {"_id": 2342122, "text": "hi there!"} # Elasticsearch gives this id!
e = SimpleNamespace(**d) # works
Name = namedtuple("Name", sorted(d)) # ValueError so we can't do Name(**d)

Lưu ý ở trên mà bạn có thể thấy rằng namedtuplecung cấp cho chúng tôi toàn bộ đối tượng SimpleNamespacesẽ không bao giờ có. Mỗi cái SimpleNamespacethực sự là một "bông tuyết độc nhất vô nhị", trong khi namedtupletồn tại mà không bao giờ được khởi tạo với bất kỳ giá trị cụ thể nào. Bất cứ nơi nào bạn có nhu cầu trừu tượng khái quát về các giá trị cụ thể, có lẽ bạn nên thích nó.


1

Tóm tắt SimpleNamespace

Nó cho phép khởi tạo các thuộc tính trong khi xây dựng đối tượng:

sn = SimpleNamespace(a=1, b=2)

Nó cung cấp một dễ đọc

repr(): eval(repr(sn)) == sn

Nó ghi đè so sánh mặc định. Thay vì so sánh bằng id(), nó so sánh các giá trị thuộc tính thay thế.

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.