2012-02-28 8 views
12

W python jeśli I wykonaj następujące czynności:W pythonie jest coś takiego jak zaktualizowane, aby zaktualizować sortowane pliki?

>>> list = [ 3, 2, 1] 
>>> sorted_list = k.sort() 

Następnie sorted_list jest None i list jest posortowana:

>>> sorted_list = k.sort() 
>>> print list, sorted_list 
[1, 2, 3] None 

Jednakże, jeśli I wykonaj następujące czynności:

>>> list = [ 3, 2, 1] 
>>> sorted_list = sorted(list) 

Następnie list pozostaje nieposortowany i sorted_list zawiera kopię posortowanej listy:

>>> print list, sorted_list 
[3, 2, 1] [1, 2, 3] 

Zastanawiam się, czy istnieje odpowiednik dla funkcji update do słowników.

ten sposób mógłby zrobić coś takiego:

def foo(a, b, extra={}): 
    bar = { 'first': a, 'second': b } 
    special_function(**updated(bar, extra)) 
    normal_function(**bar) 

zamiast zrobić coś takiego:

def foo(a, b, extra={}): 
    bar = { 'first': a, 'second': b } 
    special_bar = bar.copy() 
    special_bar.update(extra) # [1] 
    special_function(**special_bar) 
    normal_function(**bar) 

[1] Tak zdaję sobie sprawę, może po prostu zastąpić te dwie linie z extra.update(bar), ale załóżmy, że chcę zachować extra, tak jak na później w funkcji.

Zdaję sobie sprawę, mogłem realizować ten sam wygląda następująco:

def updated(old_dict, extra={}): 
    new_dict = old_dict.copy() 
    new_dict.update(extra) 
    return new_dict 

lub kolejny bardzo nieczytelny oświadczenie w miejscu:

special_function(**(dict(bar.items()+extra.items()))) 

ale miałem nadzieję, że coś zbudowany w które mogłem już używam.

+1

Powinieneś * nie * używać 'dict' jako nazwy zmiennej. Zwróć też uwagę na zmienne argumenty domyślne - lepiej weź się w nawyk, aby nigdy ich nie używać. –

+1

Twój powinien * nie * używać 'dict' jako nazwy zmiennej, myślę, że @SvenMarnach znaczy :) –

+0

@MattLuongo: Dzięki. Rzeczywiście powiedziałem coś przeciwnego do tego, co miałem na myśli. :) –

Odpowiedz

17

można po prostu użyć wbudowanej dict():

updated_dict = dict(old_dict, **extra_dict) 
+11

Pamiętaj, że to nie zadziała, jeśli klucze 'extra_dict' nie są ciągami. –

+1

@RikPoggi: Zdecydowanie powinienem był o tym wspomnieć. W przypadku użycia podanego w pytaniu to ograniczenie nie ma znaczenia. –

+0

Wow. Python nigdy nie przestaje zadziwiać! –

6

Jeśli potrzebujesz kluczy non-strunowych, można użyć funkcji tak: (To nie jest tak brzydka jak twój „w miejscu” wyrażenie + działa dla dowolnej liczby słowników)

from itertools import chain # ← credits go to Niklas B. 

def updated(*dicts): 
    return dict(chain(*map(dict.items, dicts))) 

updated({42: 'the answer'}, {1337: 'elite'}) # {42: 'the answer', 1337: 'elite'} 

W przeciwnym razie sugestia Svena jest w porządku.

Edycja: Jeśli używasz Pythona 2.7 lub nowszego, można również użyć słownika ze zrozumieniem, jak Sven sugerowane w komentarzach:

def updated(*dicts): 
    return {k: v for d in dicts for k, v in d.items()} 
+1

+1, podoba mi się to :) Chociaż myślę, że 'suma' dla listy konkatenacji jest dość brzydka, może' itertools.chain' będzie nieco czystsza. Dla dwóch dyktorów jest to po prostu 'dict (d1.items() + d2.items())' przy okazji, który jest nieco bardziej czytelny, IMO. –

+3

Używanie 'sum()' do łączenia list jest nie tylko brzydkie, ale sprawi, że cała sprawa O (n^2). Co powiesz na użycie czegoś takiego jak '{k: v dla d w dyktach dla k, v in d.items()}'? –

+0

@SvenMarnach Właściwie to naprawdę dobry pomysł! Jestem przyzwyczajony do Pythona 2.6, więc nie zawsze używam funkcji Pythona 2.7 ... – Gandaro

4

naprawdę nie zobaczyć, co się dzieje w użyciu dwie linie, tak jak Ty:

new_bar = bar.copy() 
new_bar.update(extra) 

Jest czysty i czytelny.

>>> d = {1:2, 3:4} 
>>> e = {3:9, 5:25} 
>>> f = d.copy() 
>>> f.update(e) 
>>> d 
{1: 2, 3: 4} 
>>> f 
{1: 2, 3: 9, 5: 25} 
>>> e 
{3: 9, 5: 25} 

W trzech słowach: Zen of Python.

Aby być bardziej zrozumiałym: Chodzi mi o to, że nie zastąpiłbym tych dwóch linii funkcją updated(), która nie pochodzi ze standardowej biblioteki.

Gdybym był gorszy w linii kodu, takich jak:

new_bar = updated(bar, extra) 

bym mieć śledzić tę funkcję w dół, aby zobaczyć, co robi. Nie mogłem ufać, że to nie jest coś dziwnego.

OP również porównał to z sorted(), ale sorted() ma powód, aby istnieć, działa na wszystko, co jest iterable i robi to z niesamowitym timsort. Zamiast tego jakie powinno być zachowanie hipotetycznego updated()? Czy może to być metoda klasy dict? To naprawdę nie jest jasne IMHO.

Powiedziałem, że można wybrać OP dwie linie, lub rozwiązanie Svena, lub rozumienie dict/ekspresję generatora, myślę, że to naprawdę tylko kwestia gustu.

+0

Hm, to jest styl proceduralny, w przeciwieństwie do podejścia funkcjonalnego, takiego jak Sven's lub like 'merge' w Ruby:' {1 => 3, 2 => 4} .merge ({4 => 5}) ', który nie mutować wszystko. –

+0

@Niklas: Rozumiem, ale wygląda na to, że OP próbuje zaimplementować funkcję 'updated()', moim celem było to, że nie zrobiłbym tego. Wyjaśniłem to lepiej w mojej "zaktualizowanej" odpowiedzi. –

+1

+1. Wykonaj oczywistą rzecz i zacznij żyć. – DSM

Powiązane problemy