2012-06-22 30 views
13

Tôi đang học Python và hiện đang học một số từ điển khác.Chia từ điển thành các biến

Tôi đã tự hỏi;

Nếu tôi có từ điển như: d = {'key_1': 'value_a', 'key_2': 'value_b'} và tôi muốn tách/chia từ điển này thành các biến trong đó mỗi biến là khóa từ điển và mỗi giá trị biến là giá trị của khóa đó trong từ điển.

Điều gì sẽ là cách tốt nhất để đạt được điều này?

d = {'key_1': 'value_a', 'key_2': 'value_b'} 
#perform the command and get 
key_1 = 'value_a' 
key_2 = 'value_b' 

Tôi đã thử: key_1, key_2 = d nhưng không hoạt động.

Về cơ bản, tôi đang tìm kiếm sự khôn ngoan của chuyên gia để tìm hiểu xem có cách nào tốt hơn để giảm 2 dòng mã thành một.

Lưu ý: Đây không phải là tạo biến động.

+1

Từ điển không có thứ tự khiến nhiệm vụ khó khăn này tạo ra một giải pháp chung cho, không cần phải làm điều này. Nếu nó đã được thực hiện nó sẽ là hacky. – jamylak

+4

Không có cách nhiệt đới, bởi vì ý tưởng rất không phải là pythonic. Trong python, bạn không muốn tạo biến động. – georg

+2

Bạn không nên làm điều đó. Câu trả lời là 'key_1, key_2 = d.values ​​()'. nhưng 1) điều này dễ bị ngoại lệ; 2) bạn sẽ không biết cái nào là, trừ khi bạn sắp xếp 'd.values ​​()' trước khi gán. Nó rất khó mà bạn cần tất cả điều này. –

Trả lời

8

Vấn đề là các dấu gạch ngang không có thứ tự, do đó bạn không thể sử dụng giải nén đơn giản d.values(). Bạn có thể của khóa học đầu tiên sắp xếp các dict theo mã, sau đó giải nén các giá trị:

ds = sorted(d.iteritems()) 
name0, name1, name2..., namen = [v[1] for v in ds] 

Bạn cũng có thể, ít nhất là trong vòng một đối tượng, làm một cái gì đó như:

for k, v in dict.iteritems(): 
    setattr(self, k, v) 

Ngoài ra, như tôi đã đề cập trong nhận xét ở trên, nếu bạn có thể nhận được tất cả logic của mình cần từ điển được giải nén của bạn dưới dạng biến trong một hàm, bạn có thể làm:

def func(**kwargs): 
    # Do stuff with labeled args 

func(**d) 
+0

Cảm ơn bạn rất nhiều vì đã đọc câu hỏi của tôi và trả lời. Tôi đoán tôi nên đi với con đường nổi bật của việc tách biệt dict thành biến của tôi. Tôi chỉ nghĩ rằng có thể có một giải pháp một dòng mà không cần lặp lại hoặc sắp xếp, nhưng tôi đoán là không. vì vậy tôi sẽ làm key = dict ['key'] cho mỗi khóa. Nhưng cảm ơn bạn rất nhiều vì điều này. – Phil

+0

Nếu usecase của bạn cho phép từ điển nguồn của bạn là một 'OrderedDict', và bạn có thể dự đoán thứ tự chèn, bạn có thể bỏ qua sắp xếp và chỉ giải nén' od.values ​​() 'trực tiếp. –

+0

Trong trường hợp sử dụng này, nó có vẻ giống như một overkill nhưng cảm ơn bạn. Bạn nghĩ tôi một cái gì đó. các giá trị trông rất hữu ích. – Phil

0

Không nên khai báo biến dynami cally, bởi vì nó trở nên rất khó khăn để tìm nguồn gốc của một tên biến. Điều đó nói rằng, nó có thể hack cùng một giải pháp Dynamic variable name in python nhưng tôi sẽ không khuyên bạn nên nó. Có lẽ tốt hơn bằng cách sử dụng một từ điển cũ đơn giản.

+0

Xin chào, tôi không cố gắng tạo động các biến. Tôi muốn giảm số lượng n dòng (n là số đếm chính trong dict) thành một dòng. Tôi nghĩ rằng nó sẽ có thể với Python nhưng bây giờ tôi đoán không. – Phil

1

Tôi thực sự có một usecase, nơi tôi kéo tất cả các đối số của một phương pháp __init__ vào tự namespace về xây dựng đối tượng:

vars(self).update(somedict) 

Chức năng vars giúp bạn một dict của “namespace” liên quan đến việc đối tượng đã qua. Tuy nhiên, điều này sẽ không làm việc với người dân địa phương trong một chức năng, do chi tiết thực hiện CPython. Vì vậy, nó không phải làm việc trên tất cả các thông dịch viên.

Đối với không gian tên chung bạn sẽ thay thế vars(self) bằng globals(), nhưng đây thực sự là dấu hiệu cho thấy có điều gì đó sai với logic của bạn. Như đã nói, đối với các biến cục bộ, thao tác này sẽ không hoạt động (Nó sẽ là NameError ngay cả khi bạn gán giá trị cho dict).

+0

Cảm ơn bạn rất nhiều! – Phil

1

Bạn có thể làm điều này, nếu bạn dũng cảm:

for k, v in d.items(): 
    locals()[k] = v 

Nhưng là dũng cảm có thể không đủ - bạn cũng có thể cần phải liều lĩnh, vv

Nếu bạn muốn trở thành một anh hùng liều lĩnh như @ecatmur, bạn có thể làm điều này:

locals().update(d) 

Nhưng bây giờ OP đã cập nhật câu hỏi của anh và ý kiến ​​trả lời, có vẻ như, đây không phải là những gì ông thực sự muốn làm. Chỉ để ghi lại: Có những lý do chính đáng để tạo các biến động - ngay cả khi mọi người ở đây đồng ý rằng nó không phải là pythonic. Rất nhiều vấn đề về kiểu phiên dịch có thể được giải quyết một cách thẳng thắn với sự thay đổi năng động trong phạm vi của bạn. Chỉ cần làm điều này trong một thời trang được kiểm soát. Và ... uh, không triển khai này cho một số địa điểm sản xuất;)

+0

Hoặc thậm chí là 'local(). Update (d)'. – ecatmur

+0

@ecatmur, bạn là một anh hùng! –

+1

btw, đừng bao giờ làm điều đó - theo http://docs.python.org/library/functions.html#locals * Không được sửa đổi nội dung của từ điển này; thay đổi có thể không ảnh hưởng đến giá trị của các biến địa phương và miễn phí được sử dụng bởi thông dịch viên. * – ecatmur

12

Một giải pháp mà chưa được mentionned trước sẽ

dictget = lambda d, *k: [d[i] for i in k] 

và sau đó sử dụng nó:

key_1, key_2 = dictget(d, 'key_1', 'key_2') 

có lợi thế là nó khá dễ đọc ngay cả với nhiều biến được lấy ra.

Thậm chí dễ đọc hơn, tuy nhiên, sẽ là một "thực" chức năng như

def dictget(d, *k): 
    """Get the values corresponding to the given keys in the provided dict.""" 
    return [d[i] for i in k] 
    # or maybe 
    return (d[i] for i in k) # if we suppose that we have bigger sets of result 
    # or, equivalent to this 
    for i in k: 
     yield d[i] 

mà cũng hỗ trợ cho ý kiến ​​với một docstring và được ưa thích.

+0

Tuyệt vời và thanh lịch! – Phil

+0

@Phil Không thực sự như vậy. Vì vậy, tôi vừa thêm giải pháp 'def'. – glglgl

1

tôi nghĩ rằng điều này sẽ giải quyết vấn đề của bạn

d = {'key_1': 'value_a', 'key_2': 'value_b'} 
for k,v in d.items(): 
    exec '%s=%s'%(k,v) 
+0

Điều này phù hợp với các giá trị không nhất thiết phải là chuỗi: 'cho k trong my_dict.keys(): exec" {0} = my_dict [\ '{0} \'] ". Format (k)' –

1
var1, var2 = (lambda key1, key2: (key1, key2))(**d) 

Nếu bạn muốn cho bất cứ ai đọc code của bạn bị đau đầu, bạn có thể sử dụng chức năng ẩn danh để giải nén các giá trị như thế này.

Các vấn đề liên quan