Eenvoudigere manier om een ​​woordenboek van afzonderlijke variabelen te maken?

Ik zou graag de naam van een variabele als string willen krijgen, maar ik weet niet of Python zoveel introspectiemogelijkheden heeft. Iets als:

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

Ik wil dat doen omdat ik een heleboel variabelen heb die ik in een woordenboek zou willen veranderen, zoals:

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

Maar ik zou graag iets meer automatischs willen dan dat.

Python heeft locals()en vars(), dus ik denk dat er een manier is.


Antwoord 1, autoriteit 100%

Zoals ontspannen zei, is dit niet echt iets wat je doet in Python – variabelen zijn eigenlijk naamtoewijzingen aan objecten.

Echter, hier is een manier om het te proberen:

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

Antwoord 2, autoriteit 48%

Ik heb dit heel vaak willen doen. Deze hack lijkt erg op de suggestie van rlotun, maar het is een one-liner, wat belangrijk voor mij is:

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]

Antwoord 3, autoriteit 36%

Probeer je dit te doen?

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

Voorbeeld

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

Antwoord 4, autoriteit 13%

Dit is een hack. Het werkt niet op alle distributies van Python-implementaties (in het bijzonder die die geen traceback.extract_stackhebben.)

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}

Merk op dat deze hack kwetsbaar is:

make_dict(bar,
          foo)

(aanroepen van make_dict op 2 regels) werkt niet.

In plaats van te proberen het dictaat te genereren uit de waardenfooen bar,
het zou veel Pythonischer zijn om het dictaat te genereren uit de string variabelen'foo'en 'bar':

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

Antwoord 5, autoriteit 11%

Dit is niet mogelijk in Python, dat echt geen “variabelen” heeft. Python heeft namen en er kan meer dan één naam zijn voor hetzelfde object.


6, Autoriteit 3%

Bij het lezen van de draad, zag ik een vreselijk veel wrijving. Het is gemakkelijk genoeg om te geven
Een slecht antwoord, laat dan iemand het juiste antwoord geven. Hoe dan ook, hier is wat ik heb gevonden.

Van: [effbot.org] (http://effbot.org/zone/ Python-Objects.htm # namen )


De namen zijn een beetje anders – ze zijn niet echt eigenschappen van het object en het object zelf weet niet wat het wordt genoemd.

Een object kan een aantal namen of helemaal geen naam hebben.

Namen leven in naamruimten (zoals een Module-naamruimte, een instantie-naamruimte, een lokale naamruimte van een functie).

Opmerking: dat het zegt het object zelf weet niet wat het wordt genoemd , dus dat was de aanwijzing. Python-objecten zijn niet zelfverwijzing. Dan zegt het, namen leven in naamruimten . We hebben dit in TCL / TK. Dus misschien zal mijn antwoord helpen (maar het hielp me)

  JJ = 123
  Print EVY ("'" + STR (ID (JJ)) + "'")
  Print Dir ()

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

Dus er is ‘JJ’ aan het einde van de lijst.

Herschrijf de code als:

  JJ = 123
  Print EVY ("'" + STR (ID (JJ)) + "'")
  voor x in dir ():
    Print ID (EVAL (X))
161922920
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']
3077447796
136515736
3077408320
3077656800
136515736
161922920

Dit vervelende bit van de code-ID is de naam van variabele / object / wat-you-pedantics-call-it.

Dus daar is het. Het geheugenadres van ‘JJ’ is hetzelfde als we er rechtstreeks naar op zoek zijn, zoals wanneer we het woordenboek opkijken in de wereldwijde ruimte. Ik weet zeker dat je een functie kunt maken om dit te doen. Onthoud gewoon welke naamruimte / object / wypci zich bevindt.

QED.


7

Met python 2.7 en nieuwer is er ook woordenboekbegrip waardoor het een beetje korter is. Indien mogelijk zou ik in plaats daarvan getattr gebruiken eval (eval is evil) zoals in het bovenste antwoord. Zelf kan elk object zijn dat de context heeft waar je naar kijkt. Het kan een object zijn of locals=locals() etc.

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

Antwoord 8

Ik werkte aan een soortgelijk probleem. @S.Lott zei: “Als je de lijst met variabelen hebt, wat heeft het dan voor zin om hun namen te “ontdekken”?” En mijn antwoord is gewoon om te zien of het mogelijk is en of je om wat voor reden dan ook je variabelen op type in lijsten wilt sorteren. Dus hoe dan ook, in mijn onderzoek kwam ik deze thread tegen en mijn oplossing is een beetje uitgebreid en is gebaseerd op de @rlotun-oplossing. Nog iets, zei @unutbu: “Dit idee heeft voordelen, maar let op: als twee variabelenamen verwijzen naar dezelfde waarde (bijvoorbeeld True), dan kan een onbedoelde variabelenaam worden geretourneerd.” In deze oefening was dat waar, dus ik heb het aangepakt door voor elke mogelijkheid een lijstbegrip te gebruiken dat vergelijkbaar is met dit: isClass = [i for i in isClass if i != 'item']. Zonder dit zou “item” in elke lijst verschijnen.

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

Antwoord 9

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

op deze manier krijg je varname voor een misschien ‘a’ of ‘b’.

Other episodes