2016-04-26 11 views
1

Ich bin häufig in einer Situation, in der ich eine Gruppe logisch verbundener Symbole habe, über die ich iterieren möchte. Die naheliegende Lösung besteht darin, diese Symbole zu einer Liste hinzuzufügen, aber die Duplizierung ist mühsam zu pflegen, und ich muss darauf vertrauen, dass, wenn meine Mitentwickler einen ändern, sie auch den anderen ändern.Python: Iterieren über eine Gruppe von Symbolen

Gibt es eine Möglichkeit, Symbole zu erstellen und gleichzeitig ihren Wert einer Liste hinzuzufügen?

Zum Beispiel

# A group of like symbols that can be used independently in this scope 
hippo = 'hippo' 
gator = 'gator' 
mouse = 'mouse' 

# To loop across them I have to put them into a list 
valid_animals = [hippo, gator, mouse] # Maintain me separately, fool! 

Psuedo-Code für das, was ich will

# Data structure that declares symbols whose values can be iterated over 
valid_animals = { # Even your mom could maintain this 
    hippo = 'hippo' 
    gator = 'gator' 
    mouse = 'mouse' 
} 

# Use the symbols by themselves 
print "I had a", mouse, "in my house" 

# Iterate over the symbols 
print mouse in valid_animals # True 
+1

Würde ein [Enum] (https://docs.python.org/3/library/enum.html) Ihren Anforderungen entsprechen? – rkersh

+0

Enums sind fantastisch, aber es gibt subtile, aber signifikante Unterschiede. Vor allem konzentrieren sich Enums auf die NAMEN der Symbole und nicht auf die WERTE der Symbole. Dies macht sich besonders beim Iterieren bemerkbar. Wenn ich zum Beispiel 'valid_animals' in ein Enum umwandle, gibt die' print mouse in valid_animals' False zurück. – user2859458

+0

Es kann nicht sein, was Sie wollen, aber Sie könnten 'Maus in [i.value für i in valid_animals] drucken ', oder? Und Sie könnten eine Klassenmethode "values" hinzufügen, die das etwas hübscher macht (z. B. "print mouse in valid_animals.values ​​()"). – rkersh

Antwort

0

@T. Arboreus war richtig; Die Lösung war objektorientiertes Programmieren. Um Symbole im lokalen Bereich zu deklarieren, während sie gleichzeitig zu einem iterierbaren Objekt hinzugefügt werden, benötigte ich nur einen Rückgabewert für eine Append-Aktion, die dann meinem Symbol zugewiesen werden konnte.

Ich tat dies durch Erben von list und Hinzufügen einer bind Methode.

# Iterable object that has a return on append 
class SymGroup(list): 
    def add(self, value): 
     self.append(value) 
     return value 



# Create my list that represents a group of symbol values 
valid_animals = SymGroup() 

# Assign and append values at the same time 
hippo = valid_animals.bind("hippo") 
gator = valid_animals.bind("gator") 
mouse = valid_animals.bind("mouse") 



# Symbol can be used by itself 
print "There is a", mouse, "in my house" 

# Can iterate across the symbol values 
print mouse in valid_animals # True 
print "horse" in valid_animals # False 

Jetzt muss ich nur die eine Deklaration pflegen.

2

Das klingt wie das, was die objektorientierte Programmierung ist für:

class Animal(object): 
    list = [] 
    def __init__(self,name): 
     self.name = name 
     Animal.list.append(self.name) 


mouse = Animal("mouse") 
cat = Animal("cat") 

print(mouse)  # <test.Animal object at 0x7f835e146860> 
print(mouse.name) # 'mouse' 
print(cat.name) # 'cat' 
print(Animal.list) # ['mouse', 'cat'] 

Regel in Python, Klassen haben eine init Methode. Dies kann mysteriös erscheinen, aber alles, was es wirklich ist, ist ein Code, der aufgerufen wird, wenn ein Objekt basierend auf der Klasse instanziiert wird. (Stellen Sie sich die Klasse als Vorlage zum Erstellen von Objekten vor, und die Methode init wird ausgeführt, wenn das Objekt erstellt wird.)

In der Klasse eine leere Liste erstellen. Dies ist eine Liste auf Klassenebene, auf die Sie in Ihrem Code mit Animal.list zugreifen können. Es ist nicht mit einem bestimmten instanziierten Objekt (d. H. Katze oder Maus) verbunden.

Wenn die Methode init aufgerufen wird, wird der Name des neu erstellten Objekts der Liste auf Klassenebene hinzugefügt. Wenn Sie also zehn Tiere anlegen (Tier ('Ozelot'), Tier ('Känguru'), usw.), können Sie Animal.list aufrufen, um die Namen aller Tiere zu sehen.

EDIT: Sie bat um eine allgemeinere Lösung für Ihr Problem:

class Symbol(object): 
    types = [] 
    def __init__(self,name): 
     self.name = name 
     Symbol.types.append(self.name) 
     self.item_list = [] 


    def add(self,item): 
     self.item_list.append(item) 


animal = Symbol('animal') 

print(animal.item_list) # [] 

animal.add('tiger') 
animal.add('llama') 

print(animal.item_list) # ['tiger', 'llama'] 

food = Symbol('food') 

food.add('carrot') 
food.add('beans') 

print(food.item_list) # ['carrot', 'beans'] 

print(Symbol.types) # ['animal', 'food'] 
+0

Die Verwendung eines Klassenwerts zum Speichern der Liste ist eine hervorragende Idee und löst den grundlegenden Anwendungsfall in meinem Beispiel, aber ich suche nach etwas allgemeinerem, das verwendet werden kann, ohne jedes Mal eine neue Klasse erstellen zu müssen Gruppe. Wenn ich zum Beispiel eine Gruppe von Essenssymbolen neben der Tiergruppe hätte, würde ich eine Klasse brauchen, um die Essenssymbole zu speichern, damit ich meine Tiere nicht mische. – user2859458

+0

Lassen Sie mich wissen, was Sie von der obigen Bearbeitung halten. –

+0

Das Problem mit dem neuen Code ist, dass die hinzugefügten Tiere nun keine Symbole mehr im lokalen Bereich sind. :(Ich kann zB animal.tiger nicht aufrufen, um "tiger" zu bekommen. Dies ist jedoch eine gute Idee :) – user2859458

0

Eine Idee, die es nur noch die Liste halten: valid=['foo','bar','baz'].

Wenn Sie zu einem Zeitpunkt möchten, dass Variable mit dem gleichen Namen definiert wird, wird locals().update(zip(valid,valid)) es tun.

Aber es ist sicherlich eine schlechte Idee in seriösen Projekten.

+0

'Einheimische' könnte nicht funktionieren: http://Stackoverflow.com/a/8028772/4996248. Es ist jedoch nicht wirklich wichtig, da Sie sicherlich richtig sind, dass so etwas in einem seriösen Projekt keine gute Idee ist. –

+0

Ich benutze das nur im interaktiven Modus, wenn ich müde bin, um Vielfache in intensiven Trash-String-Manipulationen zu tippen .... –

0

Ich bin mir nicht sicher, ob dies eine gute Idee, für jedes großes Projekt ist, aber man konnte folgendes tun:

def varsFromStrings(*strings): 
    newVars = [] 
    for s in strings: 
     globals()[s] = s 
     newVars.append(s) 
    return newVars 

Die Funktion eine Liste von Strings nehmen, erstellen Variablen für jeden Zeichenfolge eingeben Diese Variablen in das Wörterbuch und weisen den Variablen die einzelnen Variablen zu und geben als Ergebnis die Liste der Zeichenfolgen zurück. Dann sogar Ihre Mutter konnte ein:

valid_animals = varsFromStrings('hippo','gator','mouse') 

wonach

print("I had a", mouse, "in my house") 

for critter in valid_animals: print(critter) 

beide arbeiten wie erwartet.

Dies kann in einigen kleineren Programmen hilfreich sein, aber wenn Programmpflege ein Problem ist - warum nicht einfach ein normales Wörterbuch gültiger Tiere verwenden?

+0

Soweit ich weiß, sind Wörterbücher dem, wovon ich hier träume, am nächsten , aber am Ende sind Dictionary Keys und Symbole sehr unterschiedliche Bestien und spielen nicht ganz dasselbe. Da Schlüssel Primitive sein müssen, enden sie normalerweise als magische Strings und Zahlen, die ich lieber meiden würde. Auch Linting und andere Code-Intelligence-Tools sind bei Symbolen wesentlich hilfreicher. – user2859458

Verwandte Themen