Adlandırılmış bir diziyi sözlüğe dönüştürme


148

Python adlı adlandırılmış bir tuple sınıf var

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

Kasaba örneklerini sözlüklere dönüştürmek istiyorum. Bir Kasabadaki alanların adlarına veya numaralarına katı bir şekilde bağlanmasını istemiyorum.

Daha fazla alan ekleyebileceğim veya tamamen farklı bir adlandırılmış tuple geçirip sözlük alabilecek şekilde yazmanın bir yolu var mı?

Orijinal sınıf tanımını başkasının kodunda olduğu gibi değiştiremiyorum. Bu yüzden bir Kasaba örneğini alıp sözlüğe dönüştürmem gerekiyor.


2
btw ... sekmenin tamamlanmasına veya işlevi doğrudan dirgösteren herhangi bir nesnenin alanlarını gösterecek komuta bakın _asdict.
Corley Brigman

Ne gibi görünüyor gerçekten yapmak istiyorum den alt sınıfı olan dictyerine 'namedtuple' arasında ve başlatıcısı içine namedtuple geçmektedir. Cxx'e alışkınsanız, class Town(x)yapıcı değil, def __init__(self, *args, **kwargs)içinde olduğunu unutmayın.
Corley Brigman

Birisi kodu başka bir şey olduğu gibi orijinal sınıfı değiştiremezsiniz. bu yüzden namedtouble alt sınıf zorunda
Ben olmadan Sadece Aweso

@CorleyBrigman bunu daha fazla açıklayabilir misiniz? Adlandırılmış başlık hakkında belgeler bulmaya çalıştım ya da ne arayabileceğimi bulmaya çalıştım ve nasıl olduğunu anlayamadım. (Yine python benim en güçlü dilim değil)
Bensiz Sadece Aweso

2
hangi bölüm? diryalnızca bir python yerleşiktir ... herhangi bir python nesnesinde, bir konsolda veya bir komut dosyasında çalıştırabilirsiniz (burada bir liste döndürür, yazdırabileceğiniz veya yapabileceğiniz her şeyi yapabilirsiniz) ve ( ) nesnenin tüm niteliklerini gösterir. bilinmeyen bir nesnenin nasıl çalıştığını anlamaya çalışıyorsanız yardımcı olur.
Corley Brigman

Yanıtlar:


268

TL; DR: bunun için bir yöntem var _asdict.

İşte kullanımın bir gösterimi:

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

Bu, adlandırılmış üçlü bir belgelenmiş yöntemdir , yani python'daki olağan kuraldan farklı olarak, yöntem adının başındaki alt çizgi kullanımı caydırmak için orada değildir . Namedtuples eklenen diğer yöntemler ile birlikte, _make, _replace, _source, _fields, sadece denemek ve olası alan adları ile çakışmaları önlemek için alt çizgi vardır.


Not: Vahşi doğada bazı 2.7.5 <python sürüm <3.5.0 kodları için şu sürümü görebilirsiniz:

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

Dokümantasyon olduğunu söylemiştik iken için _asdict(bkz eskimiş oldu burada ) ve kullanımı önerilmektedir yerleşik yöntem vars . Bu tavsiye artık güncel değil; alt sınıflandırma ile ilgili bir hatayı düzeltmek için__dict__ , adlandırılmış gruplarda bulunan mülk yine bu taahhüt tarafından kaldırılmıştır .


1
Herkes _asdict, standart kütüphanede takma adı bulunmaması gerektiğini kanıtlamış bir emsal olup olmadığını biliyor mu asdict?
KobeJohn

1
@KobeJohn o zaman "asdict"grup isimlerinden biri olamazdınız .
shadowtalker

28

Bunun namedtupleörnekleri üzerinde yerleşik bir yöntem var _asdict.

Yorumlarda tartışıldığı gibi, bazı versiyonlarda vars()da bunu yapacak, ancak görünüşe göre yüksek derecede yapı detaylarına bağımlı, ancak _asdictgüvenilir olmalı. Bazı sürümlerde _asdictkullanımdan kaldırıldı olarak işaretlendi, ancak yorumlar bunun 3.4'ten beri geçerli olmadığını gösteriyor.


1
Ben downvoter değildim, ama _asdictyöntem python3 (vars lehine) modası geçmiş
wim

Tersine, varsbazı eski sürümlerde çalışmaz gibi görünüyor - 2.7'de bir yükseltir TypeError, çünkü bu sürümün namedtuplesınıfının bir __dict__özelliği yoktur.
Peter DeGlopper

evet, Martijn ve ben bunu burada tartıştık . 2.7 btw'nin daha yeni sürümlerinde çalışacak (2.7.6'dayım ve çalışıyor)
wim

Yukarıdaki yorumumda düzenleme penceresini geçtikten sonra - 2.7.5'te başarısız oluyor, bu yüzden 2.7.6'dan itibaren yeni olmalı. 2.7.5 derlemim kapalı olmadığı sürece, Martijn'in bağlantılı cevabı olduğu için? Her neyse, 2.7.5 üzerinde çalışıp çalışmadığı, yapı özelliklerine bağlı gibi görünüyor.
Peter DeGlopper

8
Sadece bir yukarı: _asdict artık silinmiş değil (ve şimdi bir OrderedDict döndürüyor) ve vars, Python 3.4 ile ( adlandırılmış başlıkların dict özniteliğinin kaldırılmasından sonra) bir hata üretir .
Alexander Huszagh

2

Ubuntu 14.04 LTS python2.7 ve python3.4 sürümlerinde __dict__özellik beklendiği gibi çalıştı. _asdict Yöntem ayrıca çalıştı ama onun yerine lokalize düzgün olmayan API standartları tanımlanmış, üniforma, mülkiyet api kullanmak eğimli ediyorum.

$ 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

Olarak gören dict (en azından benim en iyi bildiğim için), bir sözlük temsil soemthing almak için semantik yoldur.


Büyük python sürümleri ve platformları ve onların desteği için bir tablo biriktirmek güzel olurdu __dict__, şu anda yukarıda yayınlanan tek bir platform sürümü ve iki python sürümü var.

| 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-centos-7.4.1708-Core ile, Python 2.7 - __dict__çalışmıyor.
gbtimmon

-1

Durum # 1: bir boyut tuple

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" 

Durum # 2: İki boyutlu demet
Örnek: DICT_ROLES [961] # 'Arka Uç Programcısı' gösterecektir

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

_asdict () yoksa, şu şekilde kullanabilirsiniz:

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. Herhangi bir alanı sözlüğe sözlük için gerekli dizin olarak tahsis ettim, 'isim' kullandım.

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}

Adın orada olduğunu bildiğiniz gibi yardımcı değil. kör bir yöntem olmalı
Mitchell Currie
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.