Cách đơn giản hơn để tạo từ điển của các biến riêng biệt?


220

Tôi muốn có thể lấy tên của một biến là một chuỗi nhưng tôi không biết liệu Python có nhiều khả năng hướng nội không. Cái gì đó như:

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

Tôi muốn làm điều đó bởi vì tôi có một loạt các biến tôi muốn biến thành một từ điển như:

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

Nhưng tôi muốn một cái gì đó tự động hơn thế.

Python có locals()vars(), vì vậy tôi đoán có một cách.


31
Vì mọi người dường như bối rối về những gì được yêu cầu, tôi sẽ trình bày lại ở đây vì đây là một câu hỏi thú vị. Đưa ra một mảng [foo, bar, baz] bạn muốn có một từ điển như {'foo': foo, 'bar': bar, 'baz': baz} và bạn không biết biến nào trong mảng. Vì vậy, người hỏi đang hỏi làm thế nào bạn có được tên của một biến là một chuỗi trong python. Bây giờ hy vọng mọi người có thể điều hướng qua các phản hồi khủng khiếp để tìm một vài nơi mà bạn tìm hiểu lý do tại sao điều này thực sự không phải là một ý tưởng tốt trong python.
Jesse Sherlock


2
Một cách sử dụng cho kỹ thuật sẽ là hợp lý hóa các cuộc gọi định dạng chuỗi: '{var} {foo} {bar}'. Format (** có tên (var, foo, bar)), trong đó "tên" là hàm trả về dict ( 'var': var) như mô tả.
Gordon Bean

4
Tôi nghĩ rằng đây thực sự là một câu hỏi tồi vì các tên được ánh xạ tới các đối tượng, bạn có thể có nhiều tên trỏ đến cùng một đối tượng và tôi chưa bao giờ thấy cần phải hoàn thành mục tiêu đảo ngược ánh xạ đó. Vì vậy, thực tế rằng câu trả lời sai được chấp nhận ở đây là vô nghĩa - nếu một tìm kiếm google đưa bạn đến đây, bạn rõ ràng đang hỏi sai câu hỏi.
Aaron Hall

1
Đây là một ý tưởng tuyệt vời để gỡ lỗi!
john ktejik

Câu trả lời:


48

Bạn đang cố gắng để làm điều này?

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

Thí dụ

>>> 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 gần với "tinh thần" ban đầu của nó vì nó cho phép khám phá tên. Tôi sẽ có thể sử dụng cả anwser của bạn. Hoặc có thể chỉ cần sử dụng bàn tay chết tiệt của tôi để gõ. Một số thứ không được tạo ra để tự động hóa ...
e-satis

7
@ e-satis: Để @ rlotun hoạt động, bạn phải cung cấp danh sách các biến. Nếu bạn có danh sách các biến, điểm "khám phá" tên của chúng là gì?
S.Lott

4
Tại sao eval thay vì sử dụng rõ ràng người địa phương và toàn cầu?

1
@Roger Pate: Bởi vì tôi không thể hiểu được điểm của toàn bộ bài tập là gì.
S.Lott

242
Câu trả lời này không trả lời câu hỏi. Nếu bạn có danh sách các biến, điểm "khám phá" tên của chúng là gì? Để tránh trùng lặp để thay vì print('x: ' + x)người ta có thể viết magic_print(x)và có cùng một đầu ra mà không cần viết tên biến hai lần.
Piotr Dobrogost

130

Như đã nói, đây không thực sự là thứ bạn làm trong Python - các biến thực sự là ánh xạ tên cho các đối tượng.

Tuy nhiên , đây là một cách để thử và làm điều đó:

 >>> 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
Ý tưởng này có giá trị, nhưng lưu ý rằng nếu hai tên biến tham chiếu cùng một giá trị (ví dụ True), thì một tên biến ngoài ý muốn có thể được trả về.
unutbu

14
Tại sao id(v) == id(a)thay vì v is a? Điều này sẽ thất bại đối với các đối tượng bị ràng buộc với nhiều biến, chẳng hạn như int, chuỗi và bất kỳ loại nào do người dùng xác định tương tự.

Vâng, v is asẽ là một lựa chọn tốt hơn. Và vâng, chắc chắn nguy hiểm với tất cả những cạm bẫy tiềm năng có thể phát sinh! ;-)
rlotun

16
@ e-satis Tôi ngạc nhiên khi bạn không đánh dấu câu trả lời này là câu trả lời vì tôi đồng ý với nhận xét của bạn nói rằng rlotun gần với "tinh thần" ban đầu của nó vì nó cho phép khám phá tên . Ngoài ra, câu trả lời của S.Lott hoàn toàn không trả lời câu hỏi của bạn ...
Piotr Dobrogost

2
"Quá mức cần thiết và nguy hiểm" ... và sử dụng eval phải không?
lỗi

63

Tôi đã muốn làm điều này khá nhiều. Bản hack này rất giống với đề xuất của rlotun, nhưng nó là một phần mềm, rất quan trọng đối với tôi:

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 Tôi rất thích cách tiếp cận này và thỉnh thoảng đã sử dụng nó. Tuy nhiên tôi không thể làm cho nó hoạt động bên trong các chức năng. Tôi đoán có những cách "tốt hơn" để làm điều đó, nhưng không có cách nào tốt đẹp như nbubis đưa ra. Bạn đã có thể sử dụng nó trong các chức năng keflavich? Đây là nơi tôi hỏi một câu hỏi về điều này.
Leo

10
Lưu ý rằng trong Python 3, iteritems()được thay thế bằngitems()
Jonathan Wheeler

Điều này không đáng tin cậy: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)Đầu raspam
andreasdr

1
@andreasdr đó là vì spam = 1, blah = 1; assert spam is blah. Các giải pháp phá vỡ khi so sánh các loại dữ liệu nguyên thủy.
JYun

17

Đây là một hack. Nó sẽ không hoạt động trên tất cả các bản phân phối triển khai Python (đặc biệt là các bản phân phối không có 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}

Lưu ý rằng bản hack này rất dễ vỡ:

make_dict(bar,
          foo)

(gọi make_dict trên 2 dòng) sẽ không hoạt động.

Thay vì cố gắng tạo ra dict ra khỏi các giá trị foobar, Pythonic sẽ tạo ra dict ra khỏi các tên biến chuỗi 'foo''bar':

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

1
+1 cho hack thông minh. Tất nhiên, dấu vết trở lại là rất chậm vì vậy nó có thể là chậm chạp để sử dụng nó.
e-satis

1
+111111 !!!! Vâng, nó chậm, nhưng khi sử dụng để thay thế print("a_very_long_name: {}'.format(a_very_long_name))ai quan tâm!
frnhr

14

Điều này là không thể với Python, thứ thực sự không có "biến". Python có tên và có thể có nhiều hơn một tên cho cùng một đối tượng.


vâng, tôi biết, tôi đã làm cho câu hỏi trở nên đơn giản, nhưng tôi đang mong đợi nhiều thứ hơn như "get_var_tags (var) [0]".
e-satis

10

Tôi nghĩ vấn đề của tôi sẽ giúp minh họa tại sao câu hỏi này hữu ích, và nó có thể cung cấp thêm một chút cái nhìn sâu sắc về cách trả lời nó. Tôi đã viết một hàm nhỏ để thực hiện kiểm tra nội tuyến nhanh chóng trên các biến khác nhau trong mã của mình. Về cơ bản, nó liệt kê tên biến, kiểu dữ liệu, kích thước và các thuộc tính khác, vì vậy tôi có thể nhanh chóng nắm bắt mọi lỗi tôi đã mắc phải. Mã rất đơn giản:

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

Vì vậy, nếu bạn có một số tình huống từ điển / danh sách / bộ dữ liệu phức tạp, sẽ rất hữu ích khi trình thông dịch trả về tên biến bạn đã gán. Ví dụ, đây là một từ điển kỳ lạ:

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

Tôi không chắc chắn nếu tôi đặt nó ở đúng nơi, nhưng tôi nghĩ nó có thể giúp ích. Tôi hy vọng nó làm.


Vì vậy, với kiểm tra đầu của bạn, nó có tính đến thực tế là các biến / tên có thể được trỏ đến những thứ khác nhau tại các thời điểm khác nhau trong mã không? Chẳng hạn, myconnectioncó thể trỏ đến một giá trị boolean tại một điểm, một số nguyên tại một thời điểm khác và một kết nối ổ cắm tại một điểm khác trong thực thi mã ??

9

Tôi đã viết một chức năng hữu ích nhỏ gọn dựa trên câu trả lời cho câu hỏi này. Tôi đang đặt nó ở đây trong trường hợp nó hữu ích.

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)

sử dụng:

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

6

Tôi thấy rằng nếu bạn đã có một danh sách cụ thể các giá trị, đó là cách được mô tả bởi @S. Lotts là tốt nhất; tuy nhiên, cách được mô tả dưới đây hoạt động tốt để có được tất cả các biến và Lớp được thêm trong mã mà KHÔNG cần cung cấp tên biến mặc dù bạn có thể chỉ định chúng nếu bạn muốn. Mã có thể được mở rộng để loại trừ các lớp.

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

Đầu ra:

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

6

Trong python 3, điều này thật dễ dàng

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

cái này sẽ in:

myVariable 5


Điều này tương tự phương pháp rlotun nhưng một chút đơn giản hơn
officialhopsof

10
-1. Mở một cửa sổ thông dịch mới và thử for v in locals().
Không khí

Tôi không hoàn toàn chắc chắn về ý bạn?
officialhopsof

4
Điều này sẽ báo lỗi: RuntimeError: từ điển thay đổi kích thước trong khi lặp ...
Nizar B.

2
tuy nhiên bạn có thể làmfor v in list(locals()):
Phylliida

5

Python3. Sử dụng kiểm tra để nắm bắt không gian tên gọi cục bộ sau đó sử dụng các ý tưởng được trình bày ở đây. Có thể trả lại nhiều hơn một câu trả lời như đã được chỉ ra.

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

Câu trả lời hay, nhưng đối với tôi thì tốt hơn với: ... id (eval (name, none, frame.f_back.f_locals)) == ...
Emmanuel DUMAS

5

Đây là chức năng tôi tạo để đọc tên biến. Nó tổng quát hơn và có thể được sử dụng trong các ứng dụng khác nhau:

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]

Để sử dụng nó trong câu hỏi được chỉ định:

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

4

Khi đọc bài viết, tôi thấy rất nhiều ma sát. Thật dễ dàng để đưa ra một câu trả lời tồi, sau đó để ai đó đưa ra câu trả lời chính xác. Dù sao, đây là những gì tôi tìm thấy.

Từ: [effbot.org] ( http://effbot.org/zone/python-objects.htmlm#names )

Tên hơi khác một chút - chúng không thực sự là thuộc tính của đối tượng và bản thân đối tượng không biết nó được gọi là gì.

Một đối tượng có thể có bất kỳ số lượng tên, hoặc không có tên nào cả.

Tên sống trong không gian tên (như không gian tên mô-đun, không gian tên thể hiện, không gian tên cục bộ của hàm).

Lưu ý: rằng nó nói rằng chính đối tượng không biết nó được gọi là gì , vì vậy đó là đầu mối. Các đối tượng Python không tự tham chiếu. Sau đó, nó nói, Tên sống trong không gian tên . Chúng tôi có điều này trong TCL / TK. Vì vậy, có thể câu trả lời của tôi sẽ giúp (nhưng nó đã giúp tôi)

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

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

Vì vậy, có 'jj' ở cuối danh sách.

Viết lại mã dưới dạng:

    jj = 123
    in eval ("'" + str (id (jj)) + "'")
    cho x trong dir ():
        in id (eval (x))

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

Mã id khó chịu này là tên của biến / đối tượng / bất cứ điều gì bạn-pedantics-gọi-nó.

Vì vậy, nó đây Địa chỉ bộ nhớ của 'jj' giống nhau khi chúng ta tìm kiếm nó trực tiếp, như khi chúng ta tìm từ điển trong không gian tên toàn cầu. Tôi chắc rằng bạn có thể tạo ra một chức năng để làm điều này. Chỉ cần nhớ không gian tên biến / object / wypci của bạn nằm trong.

QED.


6
Bạn có hai cách sử dụng điên rồ ở đây. Đầu tiên là chính xác như : print id(jj). Thứ hai chỉ đơn giản là tìm kiếm tên, và có thể được thực hiện dễ dàng hơn với vars().
Ned Batchelder

2

Có lẽ tôi đang xem xét lại điều này nhưng ..

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'

Tuyệt quá! Đây là những gì tôi đang tìm kiếm. Cảm ơn @ 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

Tôi đã tải lên một giải pháp cho pypi . Đây là một mô-đun xác định tương đương với nameofchức năng của C # .

Nó lặp lại thông qua các hướng dẫn mã byte cho khung được gọi trong đó, lấy tên của các biến / thuộc tính được truyền cho nó. Các tên được tìm thấy trong .argreprcác LOADhướng dẫn sau tên của chức năng.


2

Tôi đã viết gói phù thủy để thực hiện loại phép thuật này một cách mạnh mẽ. Bạn có thể viết:

from sorcery import dict_of

my_dict = dict_of(foo, bar)

1

Hầu hết các đối tượng không có thuộc tính __name__ . (Các lớp, hàm và mô-đun làm; có thêm loại dựng sẵn nào có không?)

Bạn còn mong đợi gì print(my_var.__name__)khác ngoài print("my_var")? Bạn có thể chỉ cần sử dụng chuỗi trực tiếp?

Bạn có thể "cắt" một lệnh:

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

Cách khác:

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 nhưng tôi biết tên đó không tồn tại, tại sao mọi người lại lấy cái "giống như" này? Giải pháp của bạn không giải quyết được vấn đề vì tôi không muốn mã hóa tên, quá mức tôi sẽ thực hiện giải pháp chính tả mà tôi đã đưa ra trong câu hỏi.
e-satis

3
@ e-satis: Nếu chỉ đơn giản là sử dụng mọi thứ trong địa phương () sẽ giải quyết vấn đề của bạn, tôi không biết bạn đang hỏi gì. Tôi đoán bạn vẫn ổn khi gọi some_func(var), vì vậy tôi đã cố gắng chỉ ra rằng không xa lắm some_func("var"), với dictslice cho phép bạn có được ánh xạ giá trị tên cho nhiều biến số cùng một lúc.

1

Chà, tôi đã gặp phải nhu cầu tương tự vài ngày trước và phải lấy tên của một biến đang chỉ vào chính đối tượng .

Và tại sao nó lại cần thiết như vậy?

Nói tóm lại, tôi đang xây dựng một trình cắm thêm cho Maya . Trình cắm lõi được xây dựng bằng C ++ nhưng GUI được vẽ thông qua Python (vì nó không chuyên sâu về bộ xử lý). Vì tôi vẫn chưa biết cách tạo returnnhiều giá trị từ trình cắm ngoại trừ mặc định MStatus, do đó, để cập nhật từ điển trong Python, tôi phải chuyển tên của biến, chỉ vào đối tượng triển khai GUI và chứa từ điển, đến trình cắm và sau đó sử dụng MGlobal::executePythonCommand()để cập nhật từ điển từ phạm vi toàn cầu của Maya .

Để làm điều đó những gì tôi đã làm là một cái gì đó như:

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

Tôi biết rằng đó không phải là giải pháp hoàn hảo trong globalsnhiều khóa có thể được trỏ đến cùng một đối tượng, ví dụ:

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

và rằng phương pháp này không an toàn cho chủ đề. Đúng nếu tôi đã sai lầm.

Ít nhất cách tiếp cận này đã giải quyết vấn đề của tôi bằng cách lấy tên của bất kỳ biến nào trong phạm vi toàn cầu chỉ vào chính đối tượng đó và chuyển nó sang trình cắm thêm, làm đối số, cho nó sử dụng nội bộ.

Tôi đã thử điều này trên int(lớp nguyên nguyên) nhưng vấn đề là các lớp nguyên thủy này không bị bỏ qua (vui lòng sửa thuật ngữ kỹ thuật được sử dụng nếu nó sai). Bạn có thể thực hiện lại intvà sau đó làm int = foonhưng a = 3sẽ không bao giờ là một đối tượng của foonhưng nguyên thủy. Để khắc phục điều đó, bạn phải a = foo(3)để có được a.name()để làm việc.


1

Với python 2.7 và mới hơn cũng có khả năng hiểu từ điển khiến nó ngắn hơn một chút. Nếu có thể tôi sẽ sử dụng getattr thay vì eval (eval là ác) như trong câu trả lời hàng đầu. Bản thân có thể là bất kỳ đối tượng nào có bối cảnh mà bạn nhìn vào. Nó có thể là một đối tượng hoặc locals = locals (), v.v.

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

1

Tôi đã làm việc trên một vấn đề tương tự. @ S.Lott nói "Nếu bạn có danh sách các biến, điểm" khám phá "tên của họ là gì?" Và câu trả lời của tôi chỉ là để xem liệu nó có thể được thực hiện hay không và vì lý do nào đó bạn muốn sắp xếp các biến của mình theo loại vào danh sách. Vì vậy, dù sao đi nữa, trong nghiên cứu của tôi, tôi đã bắt gặp chủ đề này và giải pháp của tôi được mở rộng một chút và dựa trên giải pháp @rlotun. Một điều khác, @unutbu nói, "Ý tưởng này có giá trị, nhưng lưu ý rằng nếu hai tên biến tham chiếu cùng một giá trị (ví dụ True), thì một tên biến không lường trước có thể được trả về." Trong bài tập này là đúng vì vậy tôi đã xử lý nó bằng cách sử dụng cách hiểu danh sách tương tự như điều này cho từng khả năng : isClass = [i for i in isClass if i != 'item']. Nếu không có nó, "mục" sẽ hiển thị trong mỗi danh sách.

__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 []
'''

Vấn đề tôi gặp phải ở đây là tên không phải là thuộc tính của các đối tượng. Một đối tượng có thể có nhiều tên hoặc không có tên nào cả. Chẳng hạn, bạn đã thêm vào pi = piemã của mình, bạn sẽ có thêm một mục trong isFloatdanh sách của mình . Nếu bạn đã thêm vào danh sách tuple_1[0]của mình mixedDataTypes, sẽ không có tên nào được tìm thấy mặc dù "một" nằm trong mã của bạn hai lần (mặc dù nhờ thực hiện chuỗi, cả hai sẽ được tham chiếu đến cùng một đối tượng).
Blckknght

1
@Blckknght --- Tôi đồng ý. Đây chỉ là một cách khác để làm điều gì đó thực sự không có nghĩa là phải làm. Tôi đã không nói rằng nó làm cho kết quả độc đáo hoặc nó không thể sai được. Khi thực hiện điều này, tôi phát hiện ra rằng việc sử dụng pielàm các biến gây ra đầu ra không mong muốn và đó là vì cả hai đều là một phần của maththư viện. Đối với tôi đây chỉ là một bài tập để xem liệu nó có thể được thực hiện mặc dù kết quả cuối cùng không hoàn hảo. Trong học tập của tôi về ngôn ngữ này đi qua sách chỉ đi cho đến nay. Theo tôi, nếu bạn thực sự muốn học ngôn ngữ thì bạn phải chơi "what if" và xem những gì bạn nghĩ ra.
Michael Swartz

1

bạn có thể sử dụng 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

một vi dụ khac:

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

1

Trên python3, hàm này sẽ có tên ngoài cùng trong ngăn xếp:

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]

Nó là hữu ích bất cứ nơi nào trên mã. Đi qua ngăn xếp đảo ngược tìm kiếm trận đấu đầu tiên.


0

Mặc dù đây có lẽ là một ý tưởng tồi tệ, nó nằm cùng dòng với câu trả lời của rlotun nhưng nó sẽ trả về kết quả chính xác thường xuyên hơn.

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

Bạn gọi nó như thế này:

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

0

nên lấy danh sách rồi trở về

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

0

Nó sẽ không trả về tên của biến nhưng bạn có thể tạo từ điển từ biến toàn cục một cách dễ dàng.

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

Với python-varnamebạn có thể dễ dàng làm điều đó:

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}

Disclaimer: Tôi là tác giả của thư viện python-varname đó.


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

cách này có được tên biến cho một 'a' hoặc 'b'.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.