Ubah nama namesuple menjadi kamus

148

Saya memiliki kelas tuple bernama dalam python

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

Saya ingin mengonversi instance Town menjadi kamus. Saya tidak ingin itu terikat ketat dengan nama atau jumlah bidang di Kota.

Apakah ada cara untuk menulisnya sehingga saya bisa menambahkan lebih banyak bidang, atau mengoper tuple bernama yang sama sekali berbeda dan mendapatkan kamus.

Saya tidak dapat mengubah definisi kelas asli seperti dalam kode orang lain. Jadi saya perlu mengambil contoh dari Kota dan mengubahnya menjadi kamus.

Tanpa Aku Ini Hanya Aweso
sumber
2
btw ... lihat penyelesaian tab atau dirperintah, yang akan menampilkan bidang untuk objek apa pun ... yang akan menunjukkan _asdictfungsi secara langsung.
Corley Brigman
sepertinya apa yang benar - benar ingin Anda lakukan adalah subkelas dari dictalih-alih 'namedtuple', dan meneruskan namesuple ke inisialisasi. Ingat bahwa jika Anda terbiasa dengan Cxx, class Town(x)bukan konstruktornya, def __init__(self, *args, **kwargs)di dalamnya ada.
Corley Brigman
Saya tidak dapat mengubah kelas asli seperti pada kode elses seseorang. jadi saya harus subclass dari namedtouble
Without Me It Just Aweso
@CorleyBrigman dapatkah Anda menjelaskan lebih lanjut? Saya mencoba menemukan dokumentasi pada nama touple, atau menemukan apa yang bisa saya panggil dan saya tidak tahu caranya. (Lagi-lagi python bukan bahasa terkuat saya)
Tanpa Aku Ini Hanya Aweso
2
bagian mana? dirhanyalah sebuah python built-in ... Anda dapat menjalankannya pada objek python apa saja , di konsol atau dalam skrip (di mana ia mengembalikan daftar yang dapat Anda cetak atau lakukan apa saja dengan), dan itu akan mengembalikan daftar (hampir ) semua atribut objek. membantu jika Anda mencoba mencari tahu cara kerja objek yang tidak dikenal.
Corley Brigman

Jawaban:

268

TL; DR: ada metode yang _asdictdisediakan untuk ini.

Berikut ini adalah demonstrasi penggunaannya:

>>> 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')])

Ini adalah metode yang terdokumentasi dari namestuple, yaitu tidak seperti konvensi biasa dalam python garis bawah utama pada nama metode tidak ada untuk mencegah penggunaan . Seiring dengan metode lain ditambahkan ke namedtuples, _make, _replace, _source, _fields, ia memiliki garis bawah hanya untuk mencoba dan mencegah konflik dengan kemungkinan nama field.


Catatan: Untuk kode 2.7.5 <python <<.0.0 keluar di alam bebas, Anda mungkin melihat versi ini:

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

Untuk sementara dokumentasi menyebutkan bahwa _asdictitu sudah usang (lihat di sini ), dan menyarankan untuk menggunakan metode built-in vars . Nasihat itu sekarang sudah ketinggalan zaman; untuk memperbaiki bug yang terkait dengan subclassing, __dict__properti yang ada di namestuples telah dihapus oleh komit ini .

wim
sumber
1
Adakah yang tahu jika ada preseden mapan yang menyarankan _asdicttidak boleh alias di perpustakaan standar asdict?
KobeJohn
1
@ JohnJohn maka Anda tidak bisa "asdict"menjadi salah satu nama tuple.
shadowtalker
28

Ada metode namedtuplebawaan pada instance untuk ini _asdict,.

Seperti yang dibahas dalam komentar, pada beberapa versi vars()juga akan melakukannya, tetapi tampaknya sangat bergantung pada detail bangunan, padahal _asdictseharusnya dapat diandalkan. Dalam beberapa versi _asdictditandai sebagai usang, tetapi komentar menunjukkan bahwa ini tidak lagi berlaku pada 3.4.

Peter DeGlopper
sumber
1
Saya bukan downvoter, tetapi bisa jadi karena _asdictmetode ini telah usang dalam python3 (mendukung vars)
wim
Sebaliknya, sepertinya tidak varsberfungsi pada beberapa versi yang lebih lama - pada 2.7 itu memunculkan TypeError, karena namedtuplekelas versi itu tidak memiliki __dict__atribut.
Peter DeGlopper
ya, Martijn dan saya sudah membahasnya di sini . Ini akan bekerja pada versi yang lebih baru dari 2.7 btw (Saya di 2.7.6 dan bekerja)
wim
Lewati jendela edit pada komentar saya di atas - gagal pada 2.7.5 sehingga harus baru pada 2.7.6. Kecuali build 2.7.5 saya mati, karena Martijn ada di jawaban yang tertaut? Bagaimanapun, sepertinya apakah itu berfungsi pada 2.7.5 atau tidak tergantung pada spesifikasi bangunan.
Peter DeGlopper
8
Hanya kepala: _asdict tidak lagi dihilangkan (dan mengembalikan OrderedDict sekarang), dan vars menghasilkan kesalahan dengan Python 3.4 (dari penghapusan atribut dict dari namedtuples).
Alexander Huszagh
2

Pada Ubuntu 14,04 LTS versi python2.7 dan python3.4 __dict__properti bekerja seperti yang diharapkan. The _asdict Metode juga bekerja, tapi aku cenderung untuk menggunakan standar yang ditetapkan, seragam, api properti bukan lokal api non-seragam.

$ python2.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

Melihat sebagai dikt adalah cara semantik untuk mendapatkan kamus yang mewakili segalanya, (setidaknya menurut pengetahuan saya).


Akan menyenangkan untuk mengakumulasi tabel versi dan platform python utama dan dukungannya untuk __dict__, saat ini saya hanya memiliki satu versi platform dan dua versi python seperti yang diposting di atas.

| 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     |
ThorSummoner
sumber
1
Linux-3.10.0-693.el7.x86_64-x86_64-with-centos-7.4.1708-Core, Python 2.7 - __dict__tidak berfungsi.
gbtimmon
-1

Kasus # 1: tuple satu dimensi

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" 

Kasus # 2: Dua dimensi tuple
Contoh: DICT_ROLES [961] # akan menampilkan 'Back-End Programmer'

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()
yongtaek jun
sumber
-1

jika tidak ada _asdict (), Anda dapat menggunakan cara ini:

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
Ebubekir Tabak
sumber
-5

Python 3. Alokasikan bidang apa pun ke kamus sebagai indeks yang diperlukan untuk kamus, saya menggunakan 'nama'.

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}
Andre Odendaal
sumber
Tidak membantu karena Anda tahu nama ada di sana. itu harus menjadi metode yang buta
Mitchell Currie