Chuyển đổi một tên được đặt thành một từ điển


147

Tôi có một lớp tuple có tên trong python

class Town(collections.namedtuple('Town', [
    'name', 
    'population',
    'coordinates',
    'population', 
    'capital', 
    'state_bird'])):
    # ...

Tôi muốn chuyển đổi các phiên bản Town thành từ điển. Tôi không muốn nó bị ràng buộc chặt chẽ với tên hoặc số của các lĩnh vực trong Thị trấn.

Có cách nào để viết nó sao cho tôi có thể thêm nhiều trường hơn, hoặc chuyển một tuple hoàn toàn khác có tên và lấy một từ điển.

Tôi không thể thay đổi định nghĩa lớp gốc như trong mã của người khác. Vì vậy, tôi cần lấy một ví dụ của Thị trấn và chuyển đổi nó thành một từ điển.


2
btw ... nhìn vào hoàn thành tab hoặc dirlệnh, nó sẽ hiển thị cho bạn các trường cho bất kỳ đối tượng nào ... sẽ hiển thị _asdictchức năng trực tiếp.
Corley Brigman

có vẻ như những gì bạn thực sự muốn làm là phân lớp từ dictthay vì 'têntuple', và chuyển têntuple vào trình khởi tạo. Hãy nhớ rằng nếu bạn đã quen với Cxx, class Town(x)không phải là nhà xây dựng, def __init__(self, *args, **kwargs)bên trong nó là.
Corley Brigman

Tôi không thể thay đổi lớp gốc như trong mã của ai đó. vì vậy tôi phải phân lớp từ nametouble
Without Me It Just Aweso

@CorleyBrigman bạn có thể giải thích điều này nhiều hơn? Tôi đã cố gắng tìm tài liệu trên touple có tên, hoặc tìm những gì tôi có thể gọi trên đó và tôi không thể tìm ra cách. (Một lần nữa trăn không phải là ngôn ngữ mạnh nhất của tôi)
Không có tôi Nó chỉ là Aweso

2
phần nào? dirchỉ là một con trăn được tích hợp sẵn ... bạn có thể chạy nó trên bất kỳ đối tượng python nào , trong bàn điều khiển hoặc trong tập lệnh (nơi nó trả về một danh sách bạn có thể in hoặc làm bất cứ điều gì với) và nó sẽ trả về một danh sách (gần như ) tất cả các thuộc tính đối tượng. hữu ích nếu bạn đang cố gắng tìm hiểu làm thế nào một đối tượng không xác định hoạt động.
Corley Brigman

Câu trả lời:


267

TL; DR: có một phương pháp _asdictđược cung cấp cho việc này.

Dưới đây là một minh chứng về việc sử dụng:

>>> fields = ['name', 'population', 'coordinates', 'capital', 'state_bird']
>>> Town = collections.namedtuple('Town', fields)
>>> funkytown = Town('funky', 300, 'somewhere', 'lipps', 'chicken')
>>> funkytown._asdict()
OrderedDict([('name', 'funky'),
             ('population', 300),
             ('coordinates', 'somewhere'),
             ('capital', 'lipps'),
             ('state_bird', 'chicken')])

Đây là một phương pháp được đặt tên theo tài liệu , nghĩa là không giống như quy ước thông thường trong python , dấu gạch dưới hàng đầu trên tên phương thức không có ở đó để không khuyến khích sử dụng . Cùng với các phương pháp khác thêm vào namedtuples, _make, _replace, _source, _fields, nó có dấu gạch chân chỉ để thử và ngăn chặn xung đột với tên trường càng tốt.


Lưu ý: Đối với một số phiên bản 2.7.5 <python <3.5.0 ngoài tự nhiên, bạn có thể thấy phiên bản này:

>>> vars(funkytown)
OrderedDict([('name', 'funky'),
             ('population', 300),
             ('coordinates', 'somewhere'),
             ('capital', 'lipps'),
             ('state_bird', 'chicken')])

Trong một thời gian, tài liệu đã đề cập đến việc _asdictđã lỗi thời (xem tại đây ) và đề nghị sử dụng các vars phương thức tích hợp . Lời khuyên đó giờ đã lỗi thời; để sửa lỗi liên quan đến phân lớp, thuộc __dict__tính có trên tên đã được xóa lại bởi cam kết này .


1
Có ai biết nếu có một tiền lệ thành lập mà đề nghị _asdictkhông nên đặt bí danh trong thư viện tiêu chuẩn asdictkhông?
KobeJohn

1
@KobeJohn thì bạn không "asdict"thể là một trong những cái tên tuple.
Shadowtalker

28

Có một phương thức được xây dựng trong các namedtupletrường hợp cho việc này , _asdict.

Như đã thảo luận trong các ý kiến, trên một số phiên bản vars()cũng sẽ làm điều đó, nhưng rõ ràng nó phụ thuộc nhiều vào chi tiết xây dựng, trong khi đó _asdictđáng tin cậy. Trong một số phiên bản _asdictđược đánh dấu là không dùng nữa, nhưng các ý kiến ​​chỉ ra rằng đây không còn là trường hợp của 3,4.


1
Tôi không phải là downvoter, nhưng có thể là do _asdictphương thức này đã bị lỗi thời trong python3 (có lợi cho vars)
wim

Ngược lại, có vẻ như nó không varshoạt động trên một số phiên bản cũ hơn - vào ngày 2.7, nó tăng lên TypeError, vì namedtuplelớp của phiên bản đó không có __dict__thuộc tính.
Peter DeGlopper

vâng, Martijn và tôi đã thảo luận về vấn đề đó ở đây . Nó sẽ hoạt động trên các phiên bản mới hơn 2,7 btw (Tôi đang ở 2.7.6 và nó hoạt động)
wim

Qua cửa sổ chỉnh sửa trên nhận xét trên của tôi - nó không thành công vào ngày 2.7.5 vì vậy nó phải mới kể từ ngày 2.7.6. Trừ khi bản dựng 2.7.5 của tôi bị tắt, vì Martijn là câu trả lời được liên kết? Dù sao, có vẻ như nó có hoạt động trên 2.7.5 hay không phụ thuộc vào chi tiết xây dựng.
Peter DeGlopper

8
Chỉ cần ngẩng cao đầu: _asdict không còn bị che khuất nữa (và trả về OrderedDict ngay bây giờ) và vars tạo ra lỗi với Python 3.4 (từ việc loại bỏ thuộc tính dict của têntuples).
Alexander Huszagh

2

Trên Ubuntu 14.04 phiên bản LTS của python2.7 và python3.4, __dict__tài sản hoạt động như mong đợi. Các _asdict phương pháp cũng đã làm việc, nhưng tôi nghiêng để sử dụng, thống nhất, tài sản api tiêu chuẩn xác định thay vì các địa phương api không đồng nhất.

$ trăn2.7

# Works on:
# Python 2.7.6 (default, Jun 22 2015, 17:58:13)  [GCC 4.8.2] on linux2
# Python 3.4.3 (default, Oct 14 2015, 20:28:29)  [GCC 4.8.4] on linux

import collections

Color = collections.namedtuple('Color', ['r', 'g', 'b'])
red = Color(r=256, g=0, b=0)

# Access the namedtuple as a dict
print(red.__dict__['r'])  # 256

# Drop the namedtuple only keeping the dict
red = red.__dict__
print(red['r'])  #256

Xem như là dict là cách ngữ nghĩa để có được một từ điển đại diện cho những thứ tương tự, (ít nhất là theo sự hiểu biết tốt nhất của tôi).


Sẽ rất tốt nếu tích lũy một bảng gồm các phiên bản và nền tảng python chính và sự hỗ trợ của chúng __dict__, hiện tại tôi chỉ có một phiên bản nền tảng và hai phiên bản python như được đăng ở trên.

| Platform                      | PyVer     | __dict__ | _asdict |
| --------------------------    | --------- | -------- | ------- |
| Ubuntu 14.04 LTS              | Python2.7 | yes      | yes     |
| Ubuntu 14.04 LTS              | Python3.4 | yes      | yes     |
| CentOS Linux release 7.4.1708 | Python2.7 | no       | yes     |
| CentOS Linux release 7.4.1708 | Python3.4 | no       | yes     |
| CentOS Linux release 7.4.1708 | Python3.6 | no       | yes     |

1
Linux-3.10.0-693.el7.x86_64-x86_64-with-centos-7.4.1708-Core, Python 2.7 - __dict__không hoạt động.
gbtimmon

-1

Trường hợp # 1: tuple một chiều

TUPLE_ROLES = (
    (912,"Role 21"),
    (913,"Role 22"),
    (925,"Role 23"),
    (918,"Role 24"),
)


TUPLE_ROLES[912]  #==> Error because it is out of bounce. 
TUPLE_ROLES[  2]  #==> will show Role 23.
DICT1_ROLE = {k:v for k, v in TUPLE_ROLES }
DICT1_ROLE[925] # will display "Role 23" 

Trường hợp # 2: Bộ dữ liệu hai chiều
Ví dụ: DICT_ROLES [961] # sẽ hiển thị 'Lập trình viên Back-End'

NAMEDTUPLE_ROLES = (
    ('Company', ( 
            ( 111, 'Owner/CEO/President'), 
            ( 113, 'Manager'),
            ( 115, 'Receptionist'),
            ( 117, 'Marketer'),
            ( 119, 'Sales Person'),
            ( 121, 'Accountant'),
            ( 123, 'Director'),
            ( 125, 'Vice President'),
            ( 127, 'HR Specialist'),
            ( 141, 'System Operator'),
    )),
    ('Restaurant', ( 
            ( 211, 'Chef'), 
            ( 212, 'Waiter/Waitress'), 
    )),
    ('Oil Collector', ( 
            ( 211, 'Truck Driver'), 
            ( 213, 'Tank Installer'), 
            ( 217, 'Welder'),
            ( 218, 'In-house Handler'),
            ( 219, 'Dispatcher'),
    )),
    ('Information Technology', ( 
            ( 912, 'Server Administrator'),
            ( 914, 'Graphic Designer'),
            ( 916, 'Project Manager'),
            ( 918, 'Consultant'),
            ( 921, 'Business Logic Analyzer'),
            ( 923, 'Data Model Designer'),
            ( 951, 'Programmer'),
            ( 953, 'WEB Front-End Programmer'),
            ( 955, 'Android Programmer'),
            ( 957, 'iOS Programmer'),
            ( 961, 'Back-End Programmer'),
            ( 962, 'Fullstack Programmer'),
            ( 971, 'System Architect'),
    )),
)

#Thus, we need dictionary/set

T4 = {}
def main():
    for k, v in NAMEDTUPLE_ROLES:
        for k1, v1 in v:
            T4.update ( {k1:v1}  )
    print (T4[961]) # will display 'Back-End Programmer'
    # print (T4) # will display all list of dictionary

main()

-1

nếu không có _asdict (), bạn có thể sử dụng cách này:

def to_dict(model):
    new_dict = {}
    keys = model._fields
    index = 0
    for key in keys:
        new_dict[key] = model[index]
        index += 1

    return new_dict

-5

Python 3. Phân bổ bất kỳ trường nào vào từ điển làm chỉ mục cần thiết cho từ điển, tôi đã sử dụng 'name'.

import collections

Town = collections.namedtuple("Town", "name population coordinates capital state_bird")

town_list = []

town_list.append(Town('Town 1', '10', '10.10', 'Capital 1', 'Turkey'))
town_list.append(Town('Town 2', '11', '11.11', 'Capital 2', 'Duck'))

town_dictionary = {t.name: t for t in town_list}

Không hữu ích như bạn biết tên là có. nó nên là một phương pháp mù quáng
Mitchell Currie
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.