Змінні Python як ключі до дикту


79

Чи є простіший спосіб зробити це в Python (2.7)?: Примітка: Це не щось химерне, як розміщення всіх локальних змінних у словнику. Тільки ті, які я вказав у списку.

apple = 1
banana = 'f'
carrot = 3
fruitdict = {}

# I want to set the key equal to variable name, and value equal to variable value
# is there a more Pythonic way to get {'apple': 1, 'banana': 'f', 'carrot': 3}?

for x in [apple, banana, carrot]:
    fruitdict[x] = x # (Won't work)

1
Чи можна змінні визначити в дикті? Як фруктовий вирок = дикт (яблуко = 1, банан = 2, морква = 3)?
dr jimbob

Неправда, для кожної змінної існує багато коду, тому вона буде нечитабельною.
atp

Я припускаю, ви знаєте, що ваш код робить не те, що, за словами коментаря, робить? Ви не можете перейти назад від об’єктів до імен, якщо не знайдете те, що вам потрібно, у словнику простору імен, наприклад, local (). Однак ви можете написати функцію, яка шукає ці змінні у словнику простору імен і присвоює знайдені значення цьому ключу; див. відповідь Jimbob.
Томас

Так, вибачте, я повинен пояснити.
atp

Відповіді:


80
for i in ('apple', 'banana', 'carrot'):
    fruitdict[i] = locals()[i]

16
однорядковийdict([(i, locals()[i]) for i in ('apple', 'banana', 'carrot')])
диня

3
Хоча це питання стосується 2.7, зауважте, що наведений вище однорядковий рядок не працює в Python 3, оскільки, locals()мабуть, вказує на обсяг розуміння списку.
Roope

То яке рішення в Python 3?
Dr_Zaszuś

@ Dr_Zaszuś, який ви встановили loc=locals()раніше dict([(i, loc[i]) for in ('apple', 'banana', 'carrot')]).
bers

{i: loc[i] for i in ('apple', 'banana', 'carrot')}, немає необхідності створювати список і перетворювати його в дикт.
Гімуте

20

globals()Функція повертає словник , що містить всі глобальні змінні.

>>> apple = 1
>>> banana = 'f'
>>> carrot = 3
>>> globals()
{'carrot': 3, 'apple': 1, '__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'banana': 'f'}

Існує також подібна функція, яка називається locals().

Я розумію, що це, мабуть, не зовсім те, що ви хочете, але це може дати деяке розуміння того, як Python забезпечує доступ до ваших змінних.

Редагувати : Схоже, вашу проблему може бути краще вирішити простим використанням словника:

fruitdict = {}
fruitdict['apple'] = 1
fruitdict['banana'] = 'f'
fruitdict['carrot'] = 3

Вибачте, я мав редагувати після того, як ви писали свою відповідь. Мені потрібні лише зазначені змінні, а не всі місцеві () або глобальні ()
atp

@Jasie: Я додав приклад простого використання словника, замість того, щоб возитися зі змінними.
Грег Хьюгілл,

6

Однокласний:

fruitdict = dict(zip(('apple','banana','carrot'), (1,'f', '3'))

Дякую, але цифри були випадковими призначеннями (не потребував діапазону ()).
atp

3

Ось це в один рядок, без необхідності переписувати будь-яку зі змінних чи їх значень:

fruitdict.update({k:v for k,v in locals().copy().iteritems() if k[:2] != '__' and k != 'fruitdict'})

2

На основі відповіді mouad, ось більш пітонічний спосіб вибору змінних на основі префікса:

# All the vars that I want to get start with fruit_
fruit_apple = 1
fruit_carrot = 'f'
rotten = 666

prefix = 'fruit_'
sourcedict = locals()
fruitdict = { v[len(prefix):] : sourcedict[v]
              for v in sourcedict
              if v.startswith(prefix) }
# fruitdict = {'carrot': 'f', 'apple': 1}

Ви навіть можете помістити це у функцію з префіксом та джерелом як аргументи.


1

Ну це трохи, ммм ... непітонічно ... потворно ... халтурно ...

Ось фрагмент коду, який передбачає, що ви хочете створити словник усіх локальних змінних, які ви створюєте після того, як буде взято певний контрольний пункт:

checkpoint = [ 'checkpoint' ] + locals().keys()[:]
## Various local assigments here ...
var_keys_since_checkpoint = set(locals().keys()) - set(checkpoint)
new_vars = dict()
for each in var_keys_since_checkpoint:
   new_vars[each] = locals()[each]

Зверніть увагу, що ми явно додаємо ключ 'checkpoint' у наш знімок, locals().keys() я також явно беру фрагмент цього, хоча це не повинно бути необхідним у цьому випадку, оскільки посилання має бути сплощеним, щоб додати його до контрольної точки [' '] список. Однак, якщо ви використовували варіант цього коду і намагалися скоротити ['checkpoint'] + portion (because that key was already inмісцеві жителі (), for example) ... then, without the [:] slice you could end up with a reference to the local (). Keys () `, значення яких змінювались би після додавання змінних.

Випадково я не можу придумати спосіб викликати щось на зразок new_vars.update()списку ключів, які потрібно додати / оновити. Отже, forцикл є найбільш портативним. Я припускаю, що розуміння словника може бути використано в більш пізніх версіях Python. Однак це, здається, не що інше, як раунд коду гольфу.


-1

На це питання практично дано відповіді, але я просто хотів сказати, що це було смішно

Це не щось химерне, як поміщення всіх локальних змінних у словник.

Тому що це насправді "любитель"

що ви хочете:

apple = 1
banana = 'f'
carrot = 3
fruitdict = {}

# I want to set the key equal to variable name, and value equal to variable value
# is there a more Pythonic way to get {'apple': 1, 'banana': 'f', 'carrot': 3}?

names= 'apple banana carrot'.split() # I'm just being lazy for this post
items = globals()                    # or locals()

for name in names:
    fruitdict[name] = items[name]

Чесно кажучи, те, що ви робите, це просто копіювання елементів з одного словника в інший.

(Грег Хьюгілл практично дав повну відповідь, я просто зробив її повною)

... і, як люди пропонували, вам, мабуть, слід було б помістити їх у словник, але я припускаю, що з якихось причин ви не можете


тому, мабуть, я не бачив допису jimbob ... практично те саме, просто не телефонує до місцевих жителів / глобалів більше одного разу
Terence Honles

Я не думаю, що дзвінки до глобальних організацій більше одного разу були б ефективнішими.
dr jimbob

Наприклад, якщо ви робите пункти = місцеві жителі (); id (local ()) == id (items) ви отримаєте рівність. Або якщо ви робили предмети = місцеві жителі (); b = 3; items ['b'] він знайде нову змінну b, оскільки насправді не скопіював місцевий дикт до елементів (що було б повільніше). Якщо ви зробили пункти = local (). Copy (), можливо, була незначна різниця; але знову ж таки крок копіювання, мабуть, повільніший, ніж доступ до невеликої кількості предметів із місцевих жителів.
dr jimbob

-1

Спробуйте:

to_dict = lambda **k: k
apple = 1
banana = 'f'
carrot = 3
to_dict(apple=apple, banana=banana, carrot=carrot)
#{'apple': 1, 'banana': 'f', 'carrot': 3}

1
Чим відрізняється від простого виконання dict(apple=apple, banana=banana, carrot=carrot)?
Басіт Алі

-1

Не найелегантніше рішення, і воно працює лише у 90% випадків:

def vardict(*args):
    ns = inspect.stack()[1][0].f_locals
    retval = {}
    for a in args:
        found = False
        for k, v in ns.items():
            if a is v:
                retval[k] = v
                if found:
                    raise ValueError("Value found in more than one local variable: " + str(a))
                found = True
        if found:
            continue
        if 'self' in ns:
            for k, v in ns['self'].__dict__.items():
                if a is v:
                    retval[k] = v
                    if found:
                        raise ValueError("Value found in more than one instance attribute: " + str(a))
                    found = True
        if found:
            continue
        for k, v in globals().items():
            if a is v:
                retval[k] = v
                if found:
                    raise ValueError("Value found in more than one global variable: " + str(a))
                found = True
        assert found, "Couldn't find one of the parameters."
    return retval

Ви зіткнетеся з проблемами, якщо ви зберігаєте одне і те ж посилання в декількох змінних, але також якщо кілька змінних зберігають один і той же малий int, оскільки вони інтернуються.


-2

чому ви не робите навпаки:

fruitdict = { 
      'apple':1,
      'banana':'f',
      'carrot':3,
}

locals().update(fruitdict)

Оновлення:

не використовуйте наведений вище код, перевірте коментар.

до речі, чому ви не відзначаєте варів, які хочете отримати, я не знаю, можливо, так:

# All the vars that i want to get are followed by _fruit
apple_fruit = 1
carrot_fruit = 'f'

for var in locals():
    if var.endswith('fruit'):
       you_dict.update({var:locals()[var])

4
Оновлення locals()настільки по-справжньому зле.
Грег Хьюгілл,

Як каже мій друг: "темний вуду"
Калеб Хаттінг,

погодьтеся, але я розумію його запитання в тому, що він хоче отримувати лише змінні, які є фруктами та бобовими ; що в принципі неможливо, якщо він не міг навчити свою програму робити різницю між фруктами та бобовими та іншими речами, або, можливо, я просто ускладнюю справу, можливо, він просто хоче
варити

3
оновлення місцевих жителів () заборонено docs.python.org/library/functions.html#locals
Джон Ла Рой,

-4
a = "something"
randround = {}
randround['A'] = "%s" % a

Працювали.


1
Це повинно бути, {'a' : 'something'}і ви отримуєте {'A' : 'something'}... Ви важко кодуєте КлючA
DarkCygnus
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.