بالنظر إلى قائمة بالأسماء المتغيرة في Python ، كيف يمكنني إنشاء قاموس بأسماء متغيرة كمفاتيح (لقيم المتغيرات)؟

StackOverflow https://stackoverflow.com/questions/230896

  •  04-07-2019
  •  | 
  •  

سؤال

لدي قائمة بالأسماء المتغيرة ، مثل هذا:

['foo', 'bar', 'baz']

(سألت في الأصل كيف أقوم بتحويل قائمة بالمتغيرات. انظر إجابة جريج هيويل أدناه.)

كيف يمكنني تحويل هذا إلى قاموس حيث تكون المفاتيح هي الأسماء المتغيرة (كأوامر) والقيم هي قيم المتغيرات؟

{'foo': foo, 'bar': bar, 'baz': baz}

الآن بعد أن أعيد صياغة السؤال ، توصلت إلى:

d = {}
for name in list_of_variable_names:
    d[name] = eval(name)

هل يمكن تحسين ذلك؟

تحديث, ، الرد على السؤال (في تعليق) لماذا أرغب في القيام بذلك:

غالبًا ما أجد نفسي أستخدم مشغل ٪ إلى الأوتار مع قاموس الأسماء والقيم التي يمكن أن يديكها. في كثير من الأحيان الأسماء في السلسلة هي مجرد أسماء المتغيرات المحلية. لذلك (مع الإجابة أدناه) يمكنني أن أفعل شيئًا كهذا:

message = '''Name: %(name)s
ZIP: %(zip)s

Dear %(name)s,
...''' % dict((x, locals()[x]) for x in ['name', 'zip'])
هل كانت مفيدة؟

المحلول

ننسى التصفية locals()! يُسمح للقاموس الذي تقدمه لسلسلة التنسيق احتواء مفاتيح غير مستخدمة:

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> locals()
{'name': 'foo', 'zip': 123, ... 'unused': 'whoops!', ...}
>>> '%(name)s %(zip)i' % locals()
'foo 123'

مع الجديد ميزة F-String في بيثون 3.6 ، باستخدام locals() لم يعد ضروريا:

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> f'{zip: >5} {name.upper()}'
'  123 FOO'

نصائح أخرى

قائمتك الأصلية [foo, bar, baz] لا يحتوي على المتغير أسماء, ، أنه يحتوي فقط على عناصر تشير إلى نفس العناصر القيم كما المتغيرات التي أدرجتها. هذا لأنه يمكن أن يكون لديك اسم متغيران مختلفان يشيران إلى نفس القيمة.

لذلك ، لا تحتوي القائمة في حد ذاتها على معلومات حول الأسماء الأخرى التي تشير إلى الكائنات. العنصر الأول في صفيفك لديه الاسم foo ولكن لديها أيضا الاسم a[0] (على افتراض أن صفيفك يسمى a). بعد تنفيذ الكود التالي ، quux يشير أيضًا إلى نفس الكائن:

quux = a[0]

تحديث: أنت محق في أنه يمكنك استخدامه eval() لذلك ، ولكن استخدامه لا يثبط بشكل عام. يوفر بيثون عضوًا خاصًا يدعى __dict__ الذي يحتوي على جدول الرمز للوحدة الحالية. لذلك يمكنك:

import __main__
d = dict((x, __main__.__dict__[x]) for x in list_of_variable_names)

الحاجة الى import __main__ عندما يكون الكود الخاص بك في الوحدة الرئيسية التي لم يكشف عن اسمها ، يكون Quirk من Python.

يمكنك استخدام القائمة أو اختصارات المولد لإنشاء قائمة من المفاتيح ، والقيمة التي تستخدم لاستئصال مباشرة. أفضل طريقة أدناه:

dict((name, eval(name)) for name in list_of_variable_names)

بالإضافة إلى ذلك ، إذا كنت تعلم ، على سبيل المثال ، أن المتغيرات موجودة في جدول الرموز المحلية ، يمكنك إنقاذ نفسك من التقييم الخطير من خلال البحث عن المتغير مباشرة من السكان المحليين:

dict((name, locals()[name]) for name in list_of_variable_names)

بعد التحديث النهائي الخاص بك ، أعتقد أن الإجابة أدناه هي حقًا ما تريده. إذا كنت تستخدم هذا فقط لتوسيع السلسلة مع الأوتار التي تتحكم فيها ، فما عليك سوى تمرير السكان المحليين () مباشرة إلى توسيع السلسلة وسوف يختار القيم المطلوبة

ومع ذلك ، إذا كان من الممكن أن تأتي هذه الأوتار من مصدر خارجي (على سبيل المثال ملفات الترجمة) ، فمن الجيد تصفية السكان المحليين ()

غير فعال ، ولكن دون التذرع eval:

dict((k,v) for (k,v) in globals().iteritems() if k in list_of_variable_names)

أو

dict((k,v) for (k,v) in vars().iteritems() if k in list_of_variable_names)

اعتمادا على ما تريد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top