Ayrı değişkenlerin sözlüğünü oluşturmanın daha basit bir yolu var mı?


220

Bir dize olarak bir değişkenin adını almak istiyorum ama Python bu kadar içgörü yetenekleri olup olmadığını bilmiyorum. Gibi bir şey:

>>> print(my_var.__name__)
'my_var'

Bunu yapmak istiyorum çünkü ben gibi bir sözlüğe dönüştürmek istiyorum değişkenler bir demet var:

bar = True
foo = False
>>> my_dict = dict(bar=bar, foo=foo)
>>> print my_dict 
{'foo': False, 'bar': True}

Ama bundan daha otomatik bir şey istiyorum.

Python var locals()ve vars()sanırım bir yolu var.


31
İnsanlar neyin sorulduğu konusunda kafası karışmış gibi göründüğünden, burada yeniden ifade edeceğim çünkü bu ilginç bir soru. Bir dizi [foo, bar, baz] verildiğinde, {'foo': foo, 'bar': bar, 'baz': baz} gibi bir sözlük istersiniz ve dizide hangi değişkenlerin olduğunu bilmezsiniz. bu yüzden soru soran, bir değişkenin ismini python'da dize olarak nasıl alacağınızı soruyor. Şimdi umarım insanlar python'da bunun neden iyi bir fikir olmadığını öğrendiğiniz birkaç yeri bulmak için korkunç tepkiler arasında gezinebilirler.
Jesse Sherlock


2
Teknik için bir kullanım, dize biçimlendirme çağrılarını kolaylaştırmaktır: '{var} {foo} {bar}'. Biçim (** adlı (var, foo, bar)); burada "adlı", dikseli döndüren işlevdir ( 'var': var) açıklandığı gibi.
Gordon Bean

4
Bu aslında kötü bir soru olduğunu düşünüyorum, çünkü isimler nesnelerle eşleştirildi, aynı nesneyi gösteren birden fazla isme sahip olabilirsiniz ve bu eşlemeyi ters çevirme hedefine ulaşmak için hiç bir ihtiyaç görmedim. Burada yanlış cevabın kabul edilmesi gerçeği anlamsız - bir google araması sizi buraya getirdiğinde, açıkça yanlış soruyu soruyorsunuz.
Aaron Hall

1
Bu hata ayıklama için harika bir fikir!
john ktejik

Yanıtlar:


48

Bunu yapmaya mı çalışıyorsun?

dict( (name,eval(name)) for name in ['some','list','of','vars'] )

Misal

>>> some= 1
>>> list= 2
>>> of= 3
>>> vars= 4
>>> dict( (name,eval(name)) for name in ['some','list','of','vars'] )
{'list': 2, 'some': 1, 'vars': 4, 'of': 3}

1
rlotun adını keşfetmeye izin verdiği için ilk “ruhuna” daha yakındır. Her ikisini de kullanacağım. Ya da sadece yazmak için lanet olası elimi kullan. Bazı şeyler sadece otomatize edilmedi ...
e-satis

7
@ e-satis: @ rlotun'un çalışması için değişkenlerin listesini sağlamanız gerekir. Değişkenler listeniz varsa, isimlerini "keşfetmenin" anlamı nedir?
S.Lott

4
Yerelleri ve küreselleri açıkça kullanmak yerine neden değerlendirme yapmalısınız?

1
@ Roger Pate: Çünkü tüm egzersizin amacının ne olduğunu anlayamadım.
S.Lott

242
Bu cevap, sorulan soruya cevap vermiyor. Değişkenler listeniz varsa, isimlerini "keşfetmenin" anlamı nedir? Çoğaltmayı önlemek için, print('x: ' + x)biri yerine magic_print(x)değişkenin adını iki kez yazmadan aynı çıktıyı yazabilir ve aynı çıktıya sahip olabilirsiniz .
Piotr Dobrogost

130

Gevşediği gibi, bu gerçekten Python'da yaptığınız bir şey değildir - değişkenler aslında nesnelerle ad eşleştirmeleridir.

Ancak , bunu denemenin bir yolu var:

 >>> a = 1
 >>> for k, v in list(locals().iteritems()):
         if v is a:
             a_as_str = k
 >>> a_as_str
 a
 >>> type(a_as_str)
 'str'

14
Bu fikir haklıdır, ancak iki değişken adı aynı değere (örneğin True) başvuruyorsa, istenmeyen bir değişken adının döndürülebileceğini unutmayın.
unutbu

14
Neden id(v) == id(a)yerine v is a? Bu, ints, dize ve benzer şekilde uygulanan kullanıcı tanımlı türler gibi birden çok değişkene bağlı nesneler için başarısız olur.

Evet, v is adaha iyi bir seçim olurdu. Ve evet, ortaya çıkabilecek tüm olası tuzaklar göz önüne alındığında kesinlikle tehlikeli! ;-)
rlotun

16
@ e-satis Bu cevabı cevap olarak işaretlemediğinize şaşırdım, çünkü rlotun adını keşfetmeye izin verdiği için ilk “ruhuna” daha yakın olduğunu söyleyerek yorumunuzu kabul ediyorum . Ayrıca S.Lott'un cevabı sorunuza hiç cevap vermiyor ...
Piotr Dobrogost

2
"aşırı ve tehlikeli" ... ve eval kullanmak değil mi?
böcek

63

Bunu çok yapmak istedim. Bu kesmek rlotun'un önerisine çok benziyor, ancak benim için önemli olan tek astarlı:

blah = 1
blah_name = [ k for k,v in locals().iteritems() if v is blah][0]

Python 3+

blah = 1
blah_name = [ k for k,v in locals().items() if v is blah][0]

3
@keflavich Bu yaklaşımı çok beğendim ve zaman zaman kullandım. Ancak fonksiyonların içinde çalışamıyorum. Sanırım bunu yapmak için "daha iyi" yolları vardır, ama hiçbiri nbubis koyar gibi nice'n'simple değildir. Keflavich fonksiyonlarında kullanabildiniz mi? İşte bu konuda bir soru soruyorum.
Leo

10
Python 3'te,iteritems()items()
Jonathan Wheeler'ın

Bu güvenilmez: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)Çıktılarspam
andreasdr

1
@andreasdr bunun nedeni spam = 1, blah = 1; assert spam is blah. İlkel veri türleri karşılaştırılırken çözüm kırılır.
JYun

17

Bu bir hack. Tüm Python uygulama dağıtımlarında (özellikle sahip olmayanlarda traceback.extract_stack) çalışmaz .

import traceback

def make_dict(*expr):
    (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
    begin=text.find('make_dict(')+len('make_dict(')
    end=text.find(')',begin)
    text=[name.strip() for name in text[begin:end].split(',')]
    return dict(zip(text,expr))

bar=True
foo=False
print(make_dict(bar,foo))
# {'foo': False, 'bar': True}

Bu kesmek kırılgan olduğunu unutmayın:

make_dict(bar,
          foo)

(2 satırda make_dict çağrısı) çalışmaz.

Yerine dicti dışarı üretmek için çalışmakla değerler foo ve barbu çok daha Pythonictir dize dışına dicti oluşturmak olacaktır değişken isimleri 'foo' ve 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])

1
Akıllı kesmek için +1. Tabii ki, iz geri çok yavaştır, bu yüzden kullanmak sümüklü olabilir.
e-satis

1
+1111111 !!!! Evet, yavaş, ama print("a_very_long_name: {}'.format(a_very_long_name))kimin umurunda değiştirmek için kullanırken !
frnhr

14

Gerçekten "değişkenleri" olmayan Python'da bu mümkün değildir. Python'un adları vardır ve aynı nesne için birden fazla ad olabilir.


evet, biliyorum, soruyu basitleştirdim, ama "get_var_tags (var) [0]" gibi bir şey bekliyordum.
e-satis

10

Sorunumun bu sorunun neden faydalı olduğunu göstermeye yardımcı olacağını düşünüyorum ve bu sorunun nasıl cevaplanacağı konusunda biraz daha fikir verebilir. Kodumdaki çeşitli değişkenlere hızlı bir satır içi kafa kontrolü yapmak için küçük bir işlev yazdım. Temel olarak, değişken adını, veri türünü, boyutunu ve diğer nitelikleri listeler, böylece yaptığım hataları hızlı bir şekilde yakalayabilirim. Kod basit:

def details(val):
  vn = val.__name__                 #  If such a thing existed
  vs = str(val)
  print("The Value of "+ str(vn) + " is " + vs)
  print("The data type of " + vn + " is " + str(type(val)))

Bazı karmaşık sözlük / liste / grup durumunuz varsa, yorumlayıcının atadığınız değişken adını döndürmesi oldukça yararlı olacaktır. Örneğin, garip bir sözlük:

m = 'abracadabra'
mm=[]    
for n in m:
  mm.append(n)
mydic = {'first':(0,1,2,3,4,5,6),'second':mm,'third':np.arange(0.,10)}



details(mydic)

The Value of mydic is {'second': ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'], 'third': array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.]), 'first': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
The data type of mydic is <type 'dict'>

details(mydic['first'])
The Value of mydic['first'] is (0, 1, 2, 3, 4, 5, 6)]
The data type of mydic['first'] is <type 'list'>

details(mydic.keys())
The Value of mydic.keys() is ['second', 'third', 'first']
The data type of mydic.keys() is <type 'tuple'>

details(mydic['second'][0])
The Value of mydic['second'][0] is a
The data type of mydic['second'][0] is <type 'str'>

Bunu doğru yere koyup koymadığımdan emin değilim, ama yardımcı olabileceğini düşündüm. Umarım öyledir.


Kafa kontrolünüzle, değişkenlerin / adların kodda farklı zamanlarda farklı şeylere işaret edebileceği gerçeğini açıklıyor mu? Örneğin myconnection, bir noktada bir boole değerine, başka bir zamanda bir tamsayı ve kod yürütmedeki başka bir noktada bir soket bağlantısı ??

9

Bu sorunun cevabına dayanarak düzgün ve kullanışlı bir fonksiyon yazdım. Yararlı olması durumunda buraya koyuyorum.

def what(obj, callingLocals=locals()):
    """
    quick function to print name of input and value. 
    If not for the default-Valued callingLocals, the function would always
    get the name as "obj", which is not what I want.    
    """
    for k, v in list(callingLocals.items()):
         if v is obj:
            name = k
    print(name, "=", obj)

kullanımı:

>> a = 4
>> what(a)
a = 4
>>|

6

Zaten belirli bir değerler listeniz varsa, @S tarafından açıklanan şekilde olduğunu görüyorum. Lotts en iyisidir; Ancak yolu aşağıda açıklanan tüm değişkenleri ve kod boyunca eklenen Sınıfları almak için iyi çalışır OLMADAN İsterseniz bunları belirtebilirsiniz olsa değişken adını temin etme ihtiyacı. Kod, Sınıfları hariç tutmak için genişletilebilir.

import types
import math  # mainly showing that you could import what you will before d

# Everything after this counts
d = dict(globals())

def kv_test(k,v):
    return (k not in d and 
            k not in ['d','args'] and
            type(v) is not types.FunctionType)

def magic_print(*args):
    if len(args) == 0: 
        return {k:v for k,v in globals().iteritems() if kv_test(k,v)}
    else:
        return {k:v for k,v in magic_print().iteritems() if k in args}

if __name__ == '__main__':
    foo = 1
    bar = 2
    baz = 3
    print magic_print()
    print magic_print('foo')
    print magic_print('foo','bar')

Çıktı:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}

6

Python 3'te bu kolay

myVariable = 5
for v in locals():
  if id(v) == id("myVariable"):
    print(v, locals()[v])

bu yazdırılacaktır:

myVariable 5


Bu rlotun'un yaklaşımına benzer, ancak biraz daha basit
officialhopsof

10
-1. Yeni bir tercüman penceresi açın ve deneyin for v in locals().
Hava

Ne demek istediğinden tam olarak emin değilim?
officialhopsof

4
Bu bir hata verecektir: RuntimeError: sözlük yineleme sırasında boyut değiştirdi ...
Nizar B.

2
Ancak bunu yapabilirsinizfor v in list(locals()):
Phylliida

5

Python3. Çağıran yerel ad alanını yakalamak için denetlemeyi kullanın, ardından burada sunulan fikirleri kullanın. Belirtildiği gibi birden fazla cevap verebilir.

def varname(var):
  import inspect
  frame = inspect.currentframe()
  var_id = id(var)
  for name in frame.f_back.f_locals.keys():
    try:
      if id(eval(name)) == var_id:
        return(name)
    except:
      pass

İyi cevap, ama benim için daha iyi: ... id (eval (isim, Yok, frame.f_back.f_locals)) == ...
Emmanuel DUMAS

5

İşte değişken isimlerini okumak için oluşturduğum fonksiyon. Daha geneldir ve farklı uygulamalarda kullanılabilir:

def get_variable_name(*variable):
    '''gets string of variable name
    inputs
        variable (str)
    returns
        string
    '''
    if len(variable) != 1:
        raise Exception('len of variables inputed must be 1')
    try:
        return [k for k, v in locals().items() if v is variable[0]][0]
    except:
        return [k for k, v in globals().items() if v is variable[0]][0]

Belirtilen soruda kullanmak için:

>>> foo = False
>>> bar = True
>>> my_dict = {get_variable_name(foo):foo, 
               get_variable_name(bar):bar}
>>> my_dict
{'bar': True, 'foo': False}

4

İpliği okurken, çok fazla sürtünme gördüm. Kötü bir cevap verecek kadar kolay, sonra birisinin doğru cevabı vermesine izin ver. Her neyse, işte bulduğum şey.

Gönderen: [effbot.org] ( http://effbot.org/zone/python-objects.htm#names )

İsimler biraz farklıdır - nesnenin özellikleri değildir ve nesnenin kendisi ne dediğini bilmez.

Bir nesnenin herhangi bir sayıda adı olabilir veya hiç adı olmayabilir.

Adlar ad alanlarında yaşar (modül ad alanı, örnek ad alanı, işlevin yerel ad alanı gibi).

Not: nesnenin kendisinin ne dediğini bilmediğini söylüyor , bu yüzden ipucu oldu. Python nesneleri kendi kendine referans değildir. Sonra diyor ki, İsimler isim alanlarında yaşıyor . Bu TCL / TK'de var. Yani belki cevabım yardımcı olacaktır (ama bana yardımcı oldu)

    jj = 123
    eval ("" "+ str (id (jj)) +" '") yazdır
    baskı dir ()

166707048
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']

Listenin sonunda 'jj' var.

Kodu şu şekilde yeniden yazın:

    jj = 123
    eval ("" "+ str (id (jj)) +" '") yazdır
    dir () içindeki x için:
        baskı kimliği (eval (x))

161922920
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']
3077447796
136515736
3077408320
3077656800
136515736
161922920

Bu kötü kod kimliği, değişken / nesne / ne olursa olsun pedantics-call-it'in adıdır.

Yani, işte burada. 'Jj' nin bellek adresi, doğrudan aradığımızda aynıdır, sözlük yaptığımızda global isim alanında arama yaparız. Eminim bunu yapmak için bir işlev yapabilirsiniz. Değişkeninizin / nesnenizin / wypci'nizin hangi ad alanında olduğunu hatırlamanız yeterlidir.

QED.


6
Burada eval'ün iki çılgın kullanımı var. İlk tam olarak aynıdır: print id(jj). İkincisi sadece adı arar ve ile daha kolay yapılabilir vars().
Ned Batchelder

2

Belki de bunu düşünüyorum ama ..

str_l = next((k for k,v in locals().items() if id(l) == id(v)))


>>> bar = True
>>> foo = False
>>> my_dict=dict(bar=bar, foo=foo)
>>> next((k for k,v in locals().items() if id(bar) == id(v)))
'bar'
>>> next((k for k,v in locals().items() if id(foo) == id(v)))
'foo'
>>> next((k for k,v in locals().items() if id(my_dict) == id(v)))
'my_dict'

Harika! Aradığım şey buydu. Teşekkür @ rh0dium ... \ nvariable = 1 \n [k for k,v in locals().items() if id(variable) == id(v)] \n Out[14]: ['variable']
Majdi

2
import re
import traceback

pattren = re.compile(r'[\W+\w+]*get_variable_name\((\w+)\)')
def get_variable_name(x):
    return pattren.match( traceback.extract_stack(limit=2)[0][3]) .group(1)

a = 1
b = a
c = b
print get_variable_name(a)
print get_variable_name(b)
print get_variable_name(c)

2

Pypi'ye bir çözüm yükledim . C # nameoffonksiyonunun eşdeğerini tanımlayan bir modüldür .

İçerdiği değişkenin / özniteliklerin adlarını alarak çağrıldığı karenin bayt kodu talimatlarını yineler. Adları bulunan .argreprbir LOADişlevin adında aşağıdaki talimatlara.


2

Bu büyüyü sağlam bir şekilde yapmak için sihirbazlık paketini yazdım . Yazabilirsin:

from sorcery import dict_of

my_dict = dict_of(foo, bar)

1

Çoğu nesnenin __name__ özelliği yoktur. (Sınıflar, fonksiyonlar ve modüller yapar; bir tane daha yerleşik tip var mı?)

Eğer için başka ne beklenir print(my_var.__name__)dışındaki print("my_var")? Dizeyi doğrudan kullanabilir misiniz?

Bir dikteyi "dilimleyebilirsiniz":

def dict_slice(D, keys, default=None):
  return dict((k, D.get(k, default)) for k in keys)

print dict_slice(locals(), ["foo", "bar"])
# or use set literal syntax if you have a recent enough version:
print dict_slice(locals(), {"foo", "bar"})

Alternatif:

throw = object()  # sentinel
def dict_slice(D, keys, default=throw):
  def get(k):
    v = D.get(k, throw)
    if v is not throw:
      return v
    if default is throw:
      raise KeyError(k)
    return default
  return dict((k, get(k)) for k in keys)

2
+1 ama bu adın olmadığını biliyorum , neden herkes bunu "gibi" bir şey alıyor? Adınızı kodlamak istemediğim için çözümünüz sorunu çözmüyor, tersine soruda zaten verdiğim dikte çözümünü yapardım.
e-satis

3
@ e-satis: Yerlilerdeki her şeyi () kullanmak sorununuzu çözerse, ne soruyorsunuz hakkında hiçbir fikrim yok. Ben arama ile tamam olduğunu tahmin ediyorum some_func(var), bu yüzden bir kerede birden çok değişken için isim-değer eşlemesini almak için izin dictslicesome_func("var") ile, çok uzak olmadığını işaret etmeye çalıştım .

1

Birkaç gün önce aynı ihtiyacı karşıladım ve nesnenin kendisine işaret eden bir değişkenin adını almak zorunda kaldım .

Ve neden bu kadar gerekliydi?

Kısacası Maya için bir eklenti yapıyordum . Çekirdek eklenti C ++ kullanılarak oluşturuldu, ancak GUI Python ile çizildi (işlemci yoğun değil). Ben henüz, returnvarsayılan dışında eklenti birden çok değer bilmiyorum MStatus, bu nedenle Python bir sözlük güncellemek için ben GUI uygulayan nesneyi işaret ve değişkenin adını geçmek zorunda kaldı sözlüğün kendisini eklentiye ekledikten sonra MGlobal::executePythonCommand(), sözlüğü Maya'nın genel kapsamından güncellemek için kullanın .

Bunu yapmak için ne gibi bir şeydi:

import time

class foo(bar):

    def __init__(self):
        super(foo, self).__init__()
        self.time = time.time() #almost guaranteed to be unique on a single computer

    def name(self):
        g = globals()
        for x in g:
            if isinstance(g[x], type(self)):
                if g[x].time == self.time:
                    return x
                    #or you could:
                    #return filter(None,[x if g[x].time == self.time else None for x in g if isinstance(g[x], type(self))])
                    #and return all keys pointing to object itself

globalsAynı nesneye işaret eden birçok anahtarda mükemmel bir çözüm olmadığını biliyorum :

a = foo()
b = a
b.name()
>>>b
or
>>>a

ve yaklaşımın güvenli değil. Eğer Yanlışsam beni düzelt.

En azından bu yaklaşım , nesnenin kendisine işaret eden ve dahili olarak kullanması için argüman olarak eklentiye ileten global kapsamdaki herhangi bir değişkenin adını alarak sorunumu çözdü .

Ben int(ilkel tamsayı sınıfı) üzerinde denedim ama sorun bu ilkel sınıflar bypass alamadım (yanlış ise kullanılan teknik terminoloji düzeltmek lütfen). Yeniden uygulayabilir intve sonra yapabilirsiniz int = fooama a = 3asla fooilkel bir nesnenin nesnesi olmayacaksınız . Eğer zorunda üstesinden gelmek için a = foo(3)almak için a.name()işe.


1

Python 2.7 ve daha yeni sürümlerde, biraz daha kısa hale getiren sözlük anlama da vardır. Mümkünse en iyi yanıtta olduğu gibi eval (eval kötü) eval yerine getattr kullanmak istiyorum. Benlik, baktığınız bağlama sahip herhangi bir nesne olabilir. Bir nesne veya yerliler olabilir = yerliler () vb.

{name: getattr(self, name) for name in ['some', 'vars', 'here]}

1

Benzer bir sorun üzerinde çalışıyordum. @ S.Lott "Değişkenlerin listesine sahipseniz, isimlerini" keşfetmenin "anlamı nedir? Ve cevabım, bunun yapıp yapamayacağını ve herhangi bir nedenden ötürü değişkenlerinizi listeye göre sıralamak isteyip istemediğinizi görmek. Her neyse, araştırmamda bu konuya rastladım ve çözümüm biraz genişledi ve @rlotun çözümüne dayanıyor. Başka bir şey, @ unutbu, "Bu fikir haklıdır, ancak iki değişken adı aynı değere (örneğin True) başvuruyorsa, istenmeyen bir değişken adının döndürülebileceğini unutmayın." Ben her olasılığa buna benzer bir liste anlama kullanarak onunla ele yüzden doğruydu Bu egzersizde: isClass = [i for i in isClass if i != 'item']. Onsuz her listede "öğe" görünürdü.

__metaclass__ = type

from types import *

class Class_1: pass
class Class_2: pass
list_1 = [1, 2, 3]
list_2 = ['dog', 'cat', 'bird']
tuple_1 = ('one', 'two', 'three')
tuple_2 = (1000, 2000, 3000)
dict_1 = {'one': 1, 'two': 2, 'three': 3}
dict_2 = {'dog': 'collie', 'cat': 'calico', 'bird': 'robin'}
x = 23
y = 29
pie = 3.14159
eee = 2.71828
house = 'single story'
cabin = 'cozy'

isClass = []; isList = []; isTuple = []; isDict = []; isInt = []; isFloat = []; isString = []; other = []

mixedDataTypes = [Class_1, list_1, tuple_1, dict_1, x, pie, house, Class_2, list_2, tuple_2, dict_2, y, eee, cabin]

print '\nMIXED_DATA_TYPES total count:', len(mixedDataTypes)

for item in mixedDataTypes:
    try:
        # if isinstance(item, ClassType): # use this for old class types (before 3.0)
        if isinstance(item, type):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isClass.append(mapping_as_str)
            isClass = [i for i in isClass if i != 'item']

        elif isinstance(item, ListType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isList.append(mapping_as_str)
            isList = [i for i in isList if i != 'item']

        elif isinstance(item, TupleType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isTuple.append(mapping_as_str)
            isTuple = [i for i in isTuple if i != 'item']

        elif isinstance(item, DictType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isDict.append(mapping_as_str)
            isDict = [i for i in isDict if i != 'item']

        elif isinstance(item, IntType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isInt.append(mapping_as_str)
            isInt = [i for i in isInt if i != 'item']

        elif isinstance(item, FloatType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isFloat.append(mapping_as_str)
            isFloat = [i for i in isFloat if i != 'item']

        elif isinstance(item, StringType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isString.append(mapping_as_str)
            isString = [i for i in isString if i != 'item']

        else:
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    other.append(mapping_as_str)
            other = [i for i in other if i != 'item']

    except (TypeError, AttributeError), e:
        print e

print '\n isClass:', len(isClass), isClass
print '  isList:', len(isList), isList
print ' isTuple:', len(isTuple), isTuple
print '  isDict:', len(isDict), isDict
print '   isInt:', len(isInt), isInt
print ' isFloat:', len(isFloat), isFloat
print 'isString:', len(isString), isString
print '   other:', len(other), other

# my output and the output I wanted
'''
MIXED_DATA_TYPES total count: 14

 isClass: 2 ['Class_1', 'Class_2']
  isList: 2 ['list_1', 'list_2']
 isTuple: 2 ['tuple_1', 'tuple_2']
  isDict: 2 ['dict_1', 'dict_2']
   isInt: 2 ['x', 'y']
 isFloat: 2 ['pie', 'eee']
isString: 2 ['house', 'cabin']
   other: 0 []
'''

Bununla ilgili alacağım sorun, isimlerin nesnelerin özellikleri olmamasıdır. Tek bir nesnenin birden fazla adı olabilir veya hiç adı olmayabilir. Örneğin, pi = piekodunuza eklediyseniz listenizde fazladan bir giriş alırsınız isFloat. tuple_1[0]Listenize eklediyseniz mixedDataTypes, kodunuzda iki kez "bir" olmasına rağmen bunun için bir ad bulunmayacaktır (dize stajı sayesinde ikisi de aynı nesneye referans olacaktır).
Blckknght

1
@Blckknght --- Katılıyorum. Bu, gerçekten yapılması amaçlanmayan bir şeyi yapmanın başka bir yoludur. Benzersiz sonuçlar verdiğini ya da yanılmaz olduğunu söylemedim. Bunu yaparken pive edeğişkenleri kullanmanın istenmeyen çıktıya neden olduğunu ve her ikisinin de mathkütüphanenin bir parçası olduğunu öğrendim . Benim için bu, sonuç mükemmel olmasa da yapılabileceğini görmek için sadece bir egzersizdi. Bu dili öğrendiğime göre sadece kitaplardan geçiyorum. Bence, eğer dili gerçekten öğrenmek istiyorsanız, o zaman "ne olursa olsun" oynamalı ve ne bulduğunuzu görmelisiniz.
Michael Swartz

1

easydict kullanabilirsiniz

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1
>>> d = edict(foo=3)
>>> d.foo
3

başka bir örnek:

>>> d = EasyDict(log=False)
>>> d.debug = True
>>> d.items()
[('debug', True), ('log', False)]

1

Python3'te, bu işlev yığındaki en dış adı alır:

import inspect


def retrieve_name(var):
        """
        Gets the name of var. Does it from the out most frame inner-wards.
        :param var: variable to get name from.
        :return: string
        """
        for fi in reversed(inspect.stack()):
            names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
            if len(names) > 0:
                return names[0]

Kodun herhangi bir yerinde kullanışlıdır. İlk eşleşmeyi arayan ters yığını gezdirir.


0

Bu muhtemelen korkunç bir fikir olsa da, rlotun cevabı ile aynı çizgidedir, ancak doğru sonucu daha sık döndürür.

import inspect
def getVarName(getvar):
  frame = inspect.currentframe()
  callerLocals = frame.f_back.f_locals
  for k, v in list(callerLocals.items()):
    if v is getvar():
      callerLocals.pop(k)
      try:
        getvar()
        callerLocals[k] = v
      except NameError:
        callerLocals[k] = v
        del frame
        return k
  del frame

Buna şöyle diyorsunuz:

bar = True
foo = False
bean = False
fooName = getVarName(lambda: foo)
print(fooName) # prints "foo"

0

liste almalı sonra geri dönmeli

def get_var_name(**kwargs):
    """get variable name
        get_var_name(var = var)
    Returns:
        [str] -- var name
    """
    return list(kwargs.keys())[0]

0

Değişkenin adını döndürmez, ancak global değişkenden kolayca sözlük oluşturabilirsiniz.

class CustomDict(dict):
    def __add__(self, other):
        return CustomDict({**self, **other})

class GlobalBase(type):
    def __getattr__(cls, key):
        return CustomDict({key: globals()[key]})

    def __getitem__(cls, keys):
        return CustomDict({key: globals()[key] for key in keys})

class G(metaclass=GlobalBase):
    pass

x, y, z = 0, 1, 2

print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}

0

İle python-varnamekolayca yapabilirsiniz:

pip install python-varname

from varname import Wrapper

foo = Wrapper(True)
bar = Wrapper(False)

your_dict = {val.name: val.value for val in (foo, bar)}

print(your_dict)

# {'foo': True, 'bar': False}

Feragatname: Bu python-varname kütüphanesinin yazarıyım.


-1
>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True

bu şekilde belki 'a' veya 'b' için varname alabilirsiniz.

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.