Python Simplenamespace so với nametuple

Không có người đăng ký, LWN sẽ không tồn tại. Vui lòng xem xét đăng ký và giúp tiếp tục xuất bản LWN

Bởi Jake Edge
Ngày 29 tháng 4 năm 2020

Lớp SimpleNamespace của Python cung cấp một cách dễ dàng để lập trình viên tạo một đối tượng để lưu trữ các giá trị dưới dạng thuộc tính mà không cần tạo lớp [gần như trống] của riêng họ. Mặc dù nó hữu ích [và được sử dụng] ở dạng hiện tại, nhưng Raymond Hettinger nghĩ rằng nó có thể tốt hơn. Anh ấy muốn xem các móc được sử dụng bởi ánh xạ [e. g. từ điển] được thêm vào lớp, để có thể thêm và xóa các thuộc tính bằng cách sử dụng x. a hoặc x['a']. Nó sẽ mang lại lợi ích cho việc xử lý JSON và hơn thế nữa trong ngôn ngữ

Một SimpleNamespace cung cấp một cơ chế để khởi tạo một đối tượng có thể chứa các thuộc tính và không có gì khác. Trên thực tế, đó là một lớp trống với một __init__[] đẹp hơn và một __repr__[] hữu ích

    >>> from types import SimpleNamespace
    >>> sn = SimpleNamespace[x = 1, y = 2]
    >>> sn
    namespace[x=1, y=2]
    >>> sn.z = 'foo'
    >>> del[sn.x]
    >>> sn
    namespace[y=2, z='foo']

Hettinger đã đề xuất ý tưởng của mình với danh sách gửi thư của python-dev vào giữa tháng 4. Ông mô tả nó như sau

SimpleNamespace[] thực sự giỏi trong việc cấp quyền truy cập kiểu thuộc tính. Tôi muốn cung cấp chức năng đó cho mô-đun JSON [hoặc bất kỳ thứ gì khác chấp nhận lệnh tùy chỉnh] bằng cách thêm các phương thức ma thuật cho ánh xạ để chức năng này hoạt động.

     catalog = json.load[f, object_hook=SimpleNamespace]
     print[catalog['clothing']['mens']['shoes']['extra_wide']['quantity']] # currently possible with dict[]
     print[catalog.clothing.mens.shoes.extra_wide.quantity]                # proposed with SimpleNamespace[]
     print[catalog.clothing.boys['3t'].tops.quantity]                      # would also be supported

json. hàm load[] sẽ sử dụng object_hook để tạo các đối tượng SimpleNamespace thay vì từ điển. Sau đó, một hỗn hợp các hoạt động có thể được sử dụng để lấy thông tin từ cấu trúc dữ liệu. Trong thực tế, json. load[] sẽ sử dụng quyền truy cập kiểu từ điển để lưu trữ mọi thứ vào cấu trúc dữ liệu và Hettinger muốn khả năng làm việc với nó bằng cách sử dụng ký hiệu thuộc tính

Anh ấy nói, có những ví dụ về mã sản xuất thực hiện loại công việc này, nhưng mỗi người dùng cần phát minh lại bánh xe. "Đây là loại [a] lập dị vì các lớp con tùy chỉnh rất khó viết, không chuẩn và thường hơi chậm. " Anh ấy đã bắt đầu với một yêu cầu tính năng trong trình theo dõi lỗi Python, nhưng các phản hồi ở đó đề xuất thêm một lớp mới

[. ] nhưng tôi không thấy vấn đề trong việc sao chép đáng kể mọi thứ mà SimpleNamespace đã làm chỉ để chúng tôi có thể thêm một số phương thức hỗ trợ. Vui lòng thêm bình luận để chúng tôi có thể tìm ra cách tốt nhất để cung cấp chức năng mạnh mẽ này

Guido van Rossum nghĩ rằng kiểu sử dụng đó không đặc biệt dành cho Pythonic và không thực sự ủng hộ việc truyền bá nó

Tôi đã thấy mô hình này rất nhiều ở một nhà tuyển dụng trước đây và mặc dù sự tiện lợi rõ ràng nhưng tôi đã coi nó là một mô hình phản đối. đối với những người mong đợi ngữ nghĩa Python, thật ngạc nhiên khi đọc mã viết foo. bar và sau đó đọc lại foo['bar']. Chúng ta không nên cố nhập mô hình đối tượng của JavaScript vào Python

Kyle Stanley tự hỏi liệu tính năng này nằm trong mô-đun json có hợp lý hay không; . Anh ấy nghĩ rằng người dùng JSON sẽ không ngạc nhiên với phong cách sử dụng đó, nhưng Van Rossum không đồng ý

Chà, với tư cách là người dùng JSON trong Python, tôi *sẽ* ngạc nhiên về điều đó, vì ký hiệu JSON thực tế sử dụng ký hiệu chính tả và hầu hết mã Python tôi thấy rằng việc truy cập dữ liệu JSON thô trực tiếp sử dụng ký hiệu chính tả. Nơi bạn nhìn thấy ký hiệu dấu chấm là nếu chính tả JSON thô được xác minh và chuyển đổi thành một đối tượng thông thường [thường với sự trợ giúp của một số thư viện lược đồ], nhưng có vấn đề về ký hiệu chính tả

Một số người khác đồng ý rằng tính hai mặt của truy cập đối tượng và từ điển không phù hợp với Python, nhưng vẫn còn một vấn đề cần giải quyết, như Hettinger lưu ý. "làm việc với các từ điển được lồng nhiều [điển hình cho JSON] không thú vị với dấu ngoặc vuông và dấu ngoặc kép". Victor Stinner đã liệt kê một số dự án khác nhau từ Chỉ mục gói Python [PyPI] cung cấp một số hoặc tất cả các tính năng mong muốn, nhưng ông không thấy rằng bất kỳ dự án nào trong số đó đã "được thử nghiệm thực tế và đạt đủ mức độ phổ biến" mà chúng

Stinner [và những người khác trong chuỗi] đã chỉ ra thư viện glom là thư viện có thể được sử dụng để làm việc với dữ liệu JSON được lồng sâu. Nhưng mẫu "AttrDict" khá phổ biến, như Hettinger đã chỉ ra. glom có ​​thể làm được nhiều thứ hơn, nhưng nó không thể tự do trộn và kết hợp hai loại truy cập như Hettinger mong muốn

Có một số người nghĩ rằng việc mô-đun json cung cấp chức năng này có thể hợp lý, như Stanley đã đề xuất, bao gồm cả Van Rossum, người dường như đã nảy ra ý tưởng này. Glenn Linderman đã hỗ trợ thêm tính năng này trong nhận xét báo cáo lỗi; . "Một tính năng như vậy quá thiết thực để không phải là Pythonic. " Tương tự như vậy, Cameron Simpson nghĩ rằng nó sẽ là một sự bổ sung tốt

Tôi với Raymond ở đây. Tôi nghĩ vị trí của tôi là không giống như hầu hết các lớp, SimpleNamespace có ngữ nghĩa rất đơn giản và không có cơ sở __getitem__ nào cả, vì vậy việc tạo __getitem__ ánh xạ tới __getattr__ có vẻ ít tác động

Đúng là việc thêm chức năng giống như từ điển vào SimpleNamespace sẽ không ảnh hưởng đến mã hiện có, nhưng hầu hết trong luồng dường như vẫn phản đối việc thêm tính năng vào lớp đó. Eric Snow nói theo cách này

Hãy nhớ rằng tôi đã thêm SimpleNamespace khi triển khai PEP [Đề xuất cải tiến Python] 421, để sử dụng cho "sys" mới. thực hiện". Toàn bộ vấn đề là giữ cho nó đơn giản, như các tài liệu gợi ý

Có lẽ gợi ý triệt để nhất đến từ Rob Cliffe. Anh ấy nghĩ sẽ hợp lý hơn nếu thêm một toán tử mới vào ngôn ngữ [có lẽ là ". "] không có triển khai mặc định. Điều đó sẽ cho phép các lớp tự xác định toán tử

Sau đó, trong một lớp cụ thể, bạn có thể triển khai x. y có nghĩa là x['y'] và sau đó bạn có thể viết_______2Vẫn khá ngắn gọn, nhưng cảnh báo rằng những gì đang xảy ra không phải là tra cứu thuộc tính bình thường

Tuy nhiên, như Stinner đã chỉ ra, thay vào đó, điều đó và một số bài đăng mang tính suy đoán khác có thể thuộc về chủ đề ý tưởng trăn. Có vẻ như không có khả năng SimpleNamespace sẽ sớm nhận được tính năng bổ sung này — hoặc hoàn toàn không. Có đủ sự phản đối để thực hiện thay đổi đó, nhưng có sự thừa nhận vấn đề, vì vậy một số giải pháp khác có thể xảy ra. Tuy nhiên, có lẽ nó sẽ cần điều trị PEP;

Chủ Đề