Cara lebih mudah untuk membuat kamus dari variabel yang terpisah?

220

Saya ingin bisa mendapatkan nama variabel sebagai string tetapi saya tidak tahu apakah Python memiliki banyak kemampuan introspeksi. Sesuatu seperti:

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

Saya ingin melakukan itu karena saya memiliki banyak variabel yang ingin saya ubah menjadi kamus seperti:

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

Tetapi saya ingin sesuatu yang lebih otomatis dari itu.

Python punya locals()dan vars(), jadi saya kira ada cara.

e-satis
sumber
31
Karena orang-orang tampaknya bingung tentang apa yang diminta, saya akan menyatakannya kembali di sini karena ini adalah pertanyaan yang menarik. Diberikan array [foo, bar, baz] Anda ingin kamus seperti {'foo': foo, 'bar': bar, 'baz': baz} dan Anda tidak tahu variabel apa yang ada dalam array. jadi penanya bertanya bagaimana Anda mendapatkan nama variabel sebagai string dengan python. Sekarang mudah-mudahan orang dapat menavigasi melalui tanggapan yang mengerikan untuk menemukan beberapa tempat di mana Anda belajar mengapa ini bukan ide yang baik dengan python.
Jesse Sherlock
3
Kemungkinan rangkap: stackoverflow.com/questions/544919/…
Anderson Green
2
Satu kegunaan untuk teknik adalah merampingkan panggilan pemformatan string: '{var} {foo} {bar}'. Format (** named (var, foo, bar)), di mana "name" adalah fungsi yang mengembalikan dict ( 'var': var) seperti yang dijelaskan.
Gordon Bean
4
Saya pikir ini sebenarnya pertanyaan yang buruk karena nama dipetakan ke objek, Anda dapat memiliki beberapa nama yang menunjuk ke objek yang sama, dan saya belum pernah melihat ada kebutuhan untuk mencapai tujuan membalikkan pemetaan itu. Jadi fakta bahwa jawaban yang salah diterima di sini tidak ada artinya - jika pencarian google membawa Anda ke sini, Anda jelas mengajukan pertanyaan yang salah.
Aaron Hall
1
Ini adalah ide bagus untuk debugging!
john ktejik

Jawaban:

48

Apakah Anda mencoba melakukan ini?

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

Contoh

>>> 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}
S.Lott
sumber
1
rlotun lebih dekat dengan "roh" awal karena memungkinkan untuk menemukan nama. Saya akan bisa menggunakan kedua anwser Anda. Atau mungkin gunakan saja tanganku untuk mengetik. Beberapa hal tidak dibuat menjadi otomatis ...
e-satis
7
@ e-satis: Agar @ rlotun berfungsi, Anda harus memberikan daftar variabel. Jika Anda memiliki daftar variabel, apa gunanya "menemukan" nama mereka?
S.Lott
4
Mengapa eval alih-alih secara eksplisit menggunakan penduduk lokal dan global?
1
@Roger Pate: Karena saya tidak tahu apa gunanya seluruh latihan ini.
S.Lott
242
Jawaban ini tidak menjawab pertanyaan yang diajukan. Jika Anda memiliki daftar variabel, apa gunanya "menemukan" nama mereka? Untuk menghindari duplikasi sehingga alih-alih print('x: ' + x)seseorang dapat menulis magic_print(x)dan memiliki output yang sama tanpa menulis nama variabel dua kali.
Piotr Dobrogost
130

Seperti kata bersantai, ini bukan sesuatu yang Anda lakukan dengan Python - variabel sebenarnya adalah pemetaan nama objek.

Namun , inilah salah satu cara untuk mencoba dan melakukannya:

 >>> 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'
rlotun
sumber
14
Gagasan ini pantas, tetapi perhatikan bahwa jika dua nama variabel merujuk nilai yang sama (misalnya True), maka nama variabel yang tidak diinginkan mungkin dikembalikan.
unutbu
14
Kenapa id(v) == id(a)bukannya v is a? Ini akan gagal untuk objek yang terikat ke beberapa variabel, seperti int, string, dan tipe yang didefinisikan pengguna yang diimplementasikan secara serupa.
Ya, v is aakan menjadi pilihan yang lebih baik. Dan ya, tentu berbahaya mengingat semua potensi jebakan yang bisa muncul! ;-)
rlotun
16
@ e-satis Saya terkejut Anda belum menandai jawaban ini sebagai jawaban karena saya setuju dengan komentar Anda yang mengatakan rlotun lebih dekat dengan "roh" awal karena itu memungkinkan untuk menemukan nama . Selain itu, jawaban S.Lott sama sekali tidak menjawab pertanyaan Anda ...
Piotr Dobrogost
2
"berlebihan dan berbahaya" ... dan menggunakan eval bukan?
bug
63

Saya ingin melakukan ini cukup banyak. Retasan ini sangat mirip dengan saran rlotun, tapi ini hanya satu-baris, yang penting bagi saya:

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]
keflavich
sumber
3
@ keflavich Saya sangat menyukai pendekatan ini dan telah menggunakannya dari waktu ke waktu sekarang. Namun saya tidak bisa membuatnya berfungsi di dalam fungsi. Saya kira ada cara "lebih baik" untuk melakukannya, tetapi tidak ada yang sebaik yang dikatakan nbubis. Apakah Anda dapat menggunakannya dalam fungsi keflavich? Ini adalah di mana saya mengajukan pertanyaan tentang hal ini.
Leo
10
Perhatikan bahwa dalam Python 3, iteritems()digantikan olehitems()
Jonathan Wheeler
Ini tidak bisa diandalkan: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)Outputspam
andreasdr
1
@ andreasdr itu karena spam = 1, blah = 1; assert spam is blah. Solusinya terputus ketika membandingkan tipe data primitif.
JYun
17

Ini adalah retasan. Itu tidak akan bekerja pada semua distribusi implementasi Python (khususnya, mereka yang tidak punya traceback.extract_stack.)

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}

Perhatikan bahwa peretasan ini rapuh:

make_dict(bar,
          foo)

(memanggil make_dict pada 2 baris) tidak akan berfungsi.

Alih-alih mencoba menghasilkan dict dari nilai - nilaifoo dan bar, itu akan jauh lebih Pythonic untuk menghasilkan dict dari nama variabel string 'foo'dan 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])
unutbu
sumber
1
+1 untuk peretasan cerdas. Tentu saja, jejak kembali sangat lambat sehingga mungkin lamban untuk menggunakannya.
e-satis
1
+1111111 !!!! Ya itu lambat, tetapi ketika digunakan untuk menggantikan print("a_very_long_name: {}'.format(a_very_long_name))siapa yang peduli!
frnhr
14

Ini tidak mungkin dalam Python, yang benar-benar tidak memiliki "variabel". Python memiliki nama, dan mungkin ada lebih dari satu nama untuk objek yang sama.

beristirahat
sumber
ya, saya tahu, saya membuat pertanyaan sederhana, tetapi saya mengharapkan lebih banyak sesuatu seperti "get_var_tags (var) [0]".
e-satis
10

Saya pikir masalah saya akan membantu mengilustrasikan mengapa pertanyaan ini bermanfaat, dan mungkin memberikan sedikit lebih banyak wawasan tentang bagaimana menjawabnya. Saya menulis fungsi kecil untuk melakukan cek inline cepat pada berbagai variabel dalam kode saya. Pada dasarnya, ini mencantumkan nama variabel, tipe data, ukuran, dan atribut lainnya, jadi saya dapat dengan cepat menangkap kesalahan yang saya buat. Kode ini sederhana:

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)))

Jadi, jika Anda memiliki situasi kamus / daftar / tuple yang rumit, akan sangat membantu jika juru bahasa mengembalikan nama variabel yang Anda tetapkan. Misalnya, ini kamus yang aneh:

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'>

Saya tidak yakin apakah saya meletakkan ini di tempat yang tepat, tetapi saya pikir itu mungkin membantu. Saya harap begitu.

TheProletariat
sumber
Jadi dengan cek kepala Anda, apakah itu memperhitungkan fakta bahwa variabel / nama dapat menunjuk ke hal-hal yang berbeda pada waktu yang berbeda dalam kode? Misalnya myconnectionbisa menunjuk ke nilai boolean pada satu titik, bilangan bulat di waktu lain, dan koneksi soket di titik lain dalam eksekusi kode ??
9

Saya menulis fungsi kecil yang rapi dan bermanfaat berdasarkan jawaban untuk pertanyaan ini. Saya taruh di sini kalau-kalau berguna.

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)

pemakaian:

>> a = 4
>> what(a)
a = 4
>>|
aurtdturtle
sumber
6

Saya menemukan bahwa jika Anda sudah memiliki daftar nilai tertentu, cara itu dijelaskan oleh @S. Lotts adalah yang terbaik; Namun, cara yang dijelaskan di bawah ini berfungsi dengan baik untuk mendapatkan semua variabel dan Kelas ditambahkan di seluruh kode TANPA perlu memberikan nama variabel meskipun Anda dapat menentukan mereka jika Anda mau. Kode dapat diperluas untuk mengecualikan Kelas.

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')

Keluaran:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}
cdhagmann
sumber
6

Dalam python 3 ini mudah

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

ini akan mencetak:

myVariable 5

pelayan resmi
sumber
Ini mirip dengan pendekatan rlotun tetapi sedikit lebih sederhana
officialhopsof
10
-1. Buka jendela juru bahasa baru dan coba for v in locals().
Air
Saya tidak begitu yakin apa yang Anda maksud?
officialhops of
4
Ini akan memberikan kesalahan: RuntimeError: kamus berubah ukuran saat iterasi ...
Nizar B.
2
namun Anda dapat melakukannyafor v in list(locals()):
Phylliida
5

Python3. Gunakan inspect untuk menangkap namespace lokal panggilan lalu gunakan ide yang disajikan di sini. Dapat mengembalikan lebih dari satu jawaban seperti yang telah ditunjukkan.

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
vvxxii
sumber
Jawaban yang bagus, tetapi bagi saya lebih baik dengan: ... id (eval (name, None, frame.f_back.f_locals)) == ...
Emmanuel DUMAS
5

Inilah fungsi yang saya buat untuk membaca nama variabel. Ini lebih umum dan dapat digunakan dalam berbagai aplikasi:

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]

Untuk menggunakannya dalam pertanyaan yang ditentukan:

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

Saat membaca utas, saya melihat banyak sekali gesekan. Cukup mudah untuk memberikan jawaban yang buruk, lalu biarkan seseorang memberikan jawaban yang benar. Bagaimanapun, inilah yang saya temukan.

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

Namanya sedikit berbeda - mereka tidak benar-benar properti objek, dan objek itu sendiri tidak tahu apa namanya.

Objek dapat memiliki sejumlah nama, atau tidak ada nama sama sekali.

Nama-nama tinggal di namespace (seperti module namespace, instance namespace, namespace lokal fungsi).

Catatan: itu tertulis objek itu sendiri tidak tahu apa namanya , jadi itu adalah petunjuknya. Objek python tidak merujuk pada diri sendiri. Kemudian dikatakan, Nama tinggal di ruang nama . Kami memilikinya di TCL / TK. Jadi mungkin jawaban saya akan membantu (tapi itu memang membantu saya)

    jj = 123
    cetak eval ("'" + str (id (jj)) + "'")
    print dir ()

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

Jadi ada 'jj' di akhir daftar.

Tulis ulang kode sebagai:

    jj = 123
    cetak eval ("'" + str (id (jj)) + "'")
    untuk x in dir ():
        print id (eval (x))

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

Ini sedikit jahat kode id nama variabel / objek / apa pun-Anda-pedantik-panggilan-itu.

Jadi begitulah. Alamat memori 'jj' adalah sama ketika kita mencarinya secara langsung, seperti ketika kita melakukan kamus mencari di ruang nama global. Saya yakin Anda dapat membuat fungsi untuk melakukan ini. Ingat saja namespace tempat variabel / objek / wypci Anda berada.

QED.

Jesse Monroy Jr.
sumber
6
Anda memiliki dua penggunaan eval yang gila di sini. Yang pertama adalah persis sama dengan: print id(jj). Yang kedua hanya mencari nama, dan dapat dilakukan dengan lebih mudah vars().
Ned Batchelder
2

Mungkin aku terlalu memikirkan ini tapi ..

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'
rh0dium
sumber
Bagus! Ini yang saya cari. Terima kasih @ 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)
xmduhan
sumber
2

Saya mengunggah solusi ke pypi . Ini adalah modul yang mendefinisikan setara dengan nameoffungsi C # .

Itu iterates melalui instruksi bytecode untuk frame yang dipanggil, mendapatkan nama-nama variabel / atribut yang diteruskan ke sana. Nama-nama yang ditemukan dalam .argreprdari LOADinstruksi berikut nama fungsi.


sumber
2

Saya menulis paket sihir untuk melakukan sihir semacam ini dengan kuat. Kamu bisa menulis:

from sorcery import dict_of

my_dict = dict_of(foo, bar)
Alex Hall
sumber
1

Sebagian besar objek tidak memiliki atribut __name__ . (Kelas, fungsi, dan modul melakukan; ada lagi tipe builtin yang memilikinya?)

Apa lagi yang Anda harapkan print(my_var.__name__)selain print("my_var")? Bisakah Anda menggunakan string secara langsung?

Anda bisa "mengiris" sebuah dikt:

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"})

Kalau tidak:

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)

sumber
2
+1 tetapi saya tahu nama itu tidak ada, mengapa semua orang menerima litteraly "sesuatu seperti" ini? Solusi Anda tidak menyelesaikan masalah karena saya tidak ingin men-harcode nama, tetapi saya akan melakukan solusi dict yang sudah saya berikan dalam pertanyaan.
e-satis
3
@ e-satis: Jika hanya menggunakan segala sesuatu di lokal () menyelesaikan masalah Anda, saya tidak tahu apa yang Anda tanyakan. Saya kira Anda baik-baik saja dengan menelepon some_func(var), jadi saya mencoba menunjukkan bahwa tidak jauh dari situsome_func("var") , dengan dictslice memungkinkan Anda mendapatkan pemetaan nilai-nama untuk beberapa variabel sekaligus.
1

Yah, aku menemui yang sama kebutuhan beberapa hari yang lalu dan harus mendapatkan variabel nama yang menunjuk ke objek itu sendiri.

Dan mengapa itu sangat diperlukan?

Singkatnya saya sedang membangun plug-in untuk Maya . Plug-in inti dibangun menggunakan C ++ tetapi GUI ditarik melalui Python (karena bukan prosesor yang intensif). Karena saya, sampai sekarang, tidak tahu bagaimana cara returnbeberapa nilai dari plug-in kecuali default MStatus, oleh karena itu untuk memperbarui kamus dengan Python saya harus memberikan nama variabel, menunjuk ke objek yang mengimplementasikan GUI dan yang berisi kamus itu sendiri, untuk plug-in dan kemudian gunakan MGlobal::executePythonCommand()untuk memperbarui kamus dari lingkup global Maya .

Untuk melakukan itu apa yang saya lakukan adalah sesuatu seperti:

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

Saya tahu itu bukan solusi sempurna di dalam globalsbanyak tombol yang dapat menunjuk ke objek yang sama, misalnya:

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

dan bahwa pendekatannya tidak aman. Koreksi saya jika saya salah.

Setidaknya pendekatan ini menyelesaikan masalah saya dengan mendapatkan nama variabel apa pun dalam lingkup global yang menunjuk ke objek itu sendiri dan meneruskannya ke plug-in, sebagai argumen, untuk digunakan secara internal.

Saya mencoba ini int(kelas integer primitif) tetapi masalahnya adalah bahwa kelas-kelas primitif ini tidak dilewati (perbaiki istilah teknis yang digunakan jika salah). Anda bisa menerapkan kembali intdan kemudian melakukannya int = footetapi a = 3tidak akan pernah menjadi objek fooselain dari primitif. Untuk mengatasinya Anda harus a = foo(3)mulai a.name()bekerja.

Jari-jari yang berdarah
sumber
1

Dengan python 2.7 dan yang lebih baru ada juga pemahaman kamus yang membuatnya sedikit lebih pendek. Jika mungkin saya akan menggunakan getattr sebagai gantinya eval (eval is evil) seperti pada jawaban teratas. Diri dapat berupa objek apa pun yang memiliki konteks yang Anda lihat. Ini bisa berupa objek atau penduduk lokal = penduduk lokal () dll.

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

Saya sedang mengerjakan masalah yang sama. @ S.Lott berkata, "Jika Anda memiliki daftar variabel, apa gunanya" menemukan "nama mereka?" Dan jawaban saya hanya untuk melihat apakah itu bisa dilakukan dan jika karena alasan tertentu Anda ingin mengurutkan variabel Anda dengan mengetikkan ke dalam daftar. Jadi, bagaimanapun, dalam penelitian saya, saya menemukan utas ini dan solusi saya sedikit diperluas dan didasarkan pada solusi @rlotun. Satu hal lagi, @unutbu berkata, "Gagasan ini pantas, tetapi perhatikan bahwa jika dua nama variabel mereferensikan nilai yang sama (misalnya Benar), maka nama variabel yang tidak diinginkan mungkin dikembalikan." Dalam latihan ini yang benar jadi saya berurusan dengan itu dengan menggunakan daftar pemahaman seperti ini untuk setiap kemungkinan: isClass = [i for i in isClass if i != 'item']. Tanpanya "item" akan muncul di setiap daftar.

__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 []
'''
Michael Swartz
sumber
Masalah yang akan saya bawa adalah bahwa nama bukan properti objek. Objek tunggal mungkin memiliki banyak nama, atau tidak ada nama sama sekali. Misalnya, Anda menambahkan pi = pieke kode Anda, Anda akan mendapatkan entri tambahan dalam isFloatdaftar Anda . Jika Anda menambahkan tuple_1[0]ke mixedDataTypesdaftar Anda , tidak ada nama yang akan ditemukan untuk itu meskipun "satu" ada dalam kode Anda dua kali (meskipun berkat string magang, mereka berdua akan menjadi referensi ke objek yang sama).
Blckknght
1
@ Blckknght --- Saya setuju. Ini hanyalah cara lain untuk melakukan sesuatu yang sebenarnya tidak dimaksudkan untuk dilakukan. Saya tidak mengatakan itu memberikan hasil yang unik atau itu sempurna. Dalam melakukan ini saya menemukan bahwa menggunakan pidan esebagai variabel menyebabkan output yang tidak diinginkan dan itu karena keduanya adalah bagian dari mathperpustakaan. Bagi saya ini hanya latihan untuk melihat apakah itu bisa dilakukan meskipun hasil akhirnya tidak sempurna. Dalam pembelajaran saya tentang bahasa ini membaca buku hanya berjalan sejauh ini. Menurut pendapat saya, jika Anda benar-benar ingin belajar bahasa maka Anda harus bermain "bagaimana jika" dan melihat apa yang Anda hasilkan.
Michael Swartz
1

Anda dapat menggunakan easydict

>>> 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

contoh lain:

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

Pada python3, fungsi ini akan mendapatkan nama paling luar di stack:

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]

Ini berguna di mana saja pada kode. Lintasi tumpukan terbalik untuk mencari kecocokan pertama.

juan Isaza
sumber
0

Meskipun ini mungkin ide yang buruk, ini sejalan dengan jawaban rlotun tetapi akan mengembalikan hasil yang benar lebih sering.

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

Anda menyebutnya seperti ini:

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

harus mendapatkan daftar lalu kembali

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

Itu tidak akan mengembalikan nama variabel tetapi Anda dapat membuat kamus dari variabel global dengan mudah.

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}
pengguna5828964
sumber
0

Dengan python-varnameAnda dapat dengan mudah melakukannya:

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}

Penafian: Saya penulis perpustakaan python-varname.

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

cara ini mendapatkan varname untuk mungkin 'a' atau 'b'.

su dazhuang
sumber