2016-04-26 6 views
1

Ich schreibe einen Facebook-Bot, der irgendwann ein paar zufällig generierte Status pro Tag produzieren wird. Gerade jetzt bin ich auf der Stufe, wo ich die Logik habe, Phrasen aus Wörterbucheinträgen auszuwählen, und ich habe es geschrieben, so dass es vorerst nur in der Python-Shell funktionieren wird - die Facebook-Authentifizierung wird kommen später.Wie kann ich ein zufälliges Element in ein Wörterbuch einfügen und es randomisieren lassen, wann immer ich es nenne?

Gerade jetzt aber, ich dachte, es wäre cool bestimmte Substantive innerhalb der Sätze in den Wörterbüchern enthalten sind, randomisieren, und ich tat dies mit random.choice() und eine Funktion ausgeführt wird, dass jedes Mal, wenn ich ein erzeugen ein neues Zufallselement zurückgeben soll Status. Aber das Problem ist, dass, wann immer ich die Phrase rufe, ich sehe, dass es ein zufälliges Substantiv erzeugt, aber dieses Substantiv wird aus irgendeinem Grund "fixiert", so dass jedes Mal das gleiche Substantiv reproduziert wird. Wenn ich die Funktion als Teil des Erstellens eines Status ausführe, scheint es gut zu funktionieren, aber aus irgendeinem Grund kann ich nicht verstehen, dass neue zufällige Substantive nicht an das Wörterbuch übergeben werden. Natürlich funktioniert es, wenn ich das Programm neu starte, aber wenn ich das als Bot machen möchte, möchte ich das Programm idealerweise nicht jedes Mal neu starten müssen, wenn ich einen neuen Status möchte.

Ich habe einige Nachforschungen gemacht und ich denke, das Problem ist nicht mit meinen tatsächlichen random.choice() Sachen oder die Funktionen, die sie sind, aber das Wörterbuch wird "behoben", bevor meine zufällige Substantiv-Funktion kann es berühren (ZB die Zufallsauswahlfunktion erzeugt eine zufällige Auswahl aus der Fruchtliste, aber das Wörterbuch wird immer nur das selbe Obst haben, das ausgewählt wird, wenn ich die StatusBuilder-Funktion ausführe). Ich habe einige mögliche Lösungen mit globalen Variablen und so weiter ausprobiert, aber nichts hat funktioniert. Der Auszug, der im folgenden Code gezeigt wird, ist meiner Meinung nach der nächste, dem ich gekommen bin.

from random import randint 
from random import choice 
from textwrap import fill 

def RandomFruit(): 
    return choice(["mango", "pomelo", "guava", "grapefruit", "watermelon"]) 

class DoTable(): 
    def __init__(self, text): 
     self.text = text 

DoDict = { 
    "do0": DoTable("sitting on the roof, completely naked, throwing Herb Alpert records at a dog like they were frisbees"), 
    "do1": DoTable("eating a " + RandomFruit() + " like it's a handfruit"), 
    "do2": DoTable("lurching around a supermarket"), 
    } 

class BeTable(): 
    def __init__(self, start_text, end_text): 
     self.start_text = start_text 
     self.end_text = end_text 

BeDict = { 
    "be0": BeTable("I guess ", " is what my life has come to."), 
    "be1": BeTable("", ", just waiting for the police to arrive."), 
    "be2": BeTable("If ", " is wrong, then I don't ever want to be right!"), 
    } 

def StatusBuilder(): 
#DoDict and BeDict will always have one entry selected from each, though 
#BeDict will always have two attributes selected as part of the one entry. 
    DoRNG = randint(0,len(DoDict)-1) 
    BeRNG = randint(0,len(BeDict)-1) 
#Logic to display concatenated strings 
    status = BeDict["be" + str(BeRNG)].start_text + DoDict["do" + str(DoRNG)].text + BeDict["be" + str(BeRNG)].end_text 
#print the status with textwrapping and with the first letter always capitalised. 
    print fill((status[0].capitalize() + status[1:]), 80) 
    print 
    Controls() 

def Controls(): 
    command = raw_input("([RETURN] FOR ANOTHER ROUND OF BULLSHIT, [Q] TO QUIT): ") 
    if command.lower() == "q": 
     quit() 
    elif command.lower() == "": 
     print 
     RandomFruit() 
     StatusBuilder() 
    else: 
     print 
     print fill("Some kind of wise guy are you? Try again, this time with a PROPER command please.", 80) 
     print 
     Controls() 

#Start the program 
print "PHILBOT V1.0" 
print "A social media status generator." 
print 
command = raw_input("(PRESS [RETURN] TO GET STARTED): ") 
print 
RandomFruit() 
StatusBuilder() 

Die Probe Wörterbücher sind in dem obigen Code enthalten (das ist ein massiv verglichen ist abgespeckte Version des Programms, das, wenn Sie laufen mit ihm spielen wollen). Die Ausgabe, mit der ich Probleme habe, wäre das Element in DoDict mit dem Schlüssel "do1". Nehmen wir zum Beispiel an, dass die StatusBuilder-Funktion nacheinander die gleichen Phrasen ("do1" und "be2") auswählt, was jedes Mal, wenn sie mit der StatusBuilder-Funktion aufgerufen wird, ein anderes Obst erzeugt:

"Wenn ich eine Mango esse wie eine Handfrucht ist falsch, dann will ich niemals richtig sein!"

"Wenn ich eine Grapefruit wie eine Handfruit falsch mag, dann will ich nie richtig sein!"

Momentan "klebt" immer, welches Obst ausgewählt wird, immer wenn ich es durch StatusBuilder() führe, obwohl die RandomFruit() Funktion normal zu funktionieren scheint.

EDIT: Ich habe jetzt ein paar vorgeschlagene Alternativen (mit Lambdas und mit Generatoren) versucht und habe versucht, mit einem einfacheren Datenformat (Listen ohne Klassen) zu arbeiten, aber das Problem wird noch reproduziert. SO, ich fange an zu denken, dass es mehr mit meiner Reihenfolge der Operationen zu tun hat, wie im Wörterbucheintrag geschrieben wird, nachdem die RandomFruit-Funktion anfänglich ausgeführt wird (yay!), Aber es wird nicht "neu geschrieben" wenn ich es nochmal starte (boo!) ... das gibt mir ein Problem, da ich entweder die Funktion dann das Dictionary deklarieren kann (wo die Funktion nach dem ersten Gebrauch nicht mit dem Dictionary zu sprechen scheint), oder deklariere das Dictionary und dann die Funktion (was nicht funktioniert, da das Dictionary versucht, sich auf eine noch nicht deklarierte Funktion zu verlassen). Also, ich denke, das ist die Wurzel des Problems - jede Hilfe?

+0

können Sie eine MCVE bieten. zeigt uns ein Beispielwörterbuch und die erwarteten Ausgaben oder Ausgaben, die Sie wünschen. Mein Verständnis ist jetzt, dass Sie die Werte des Wörterbuchs randomisieren möchten, wenn Sie versuchen, mit einem Schlüssel darauf zuzugreifen, ist das richtig? – danidee

+0

OK, gutes Denken, danke - wird den Beitrag bearbeiten. – phillipbrooker

+0

Und ich sollte auch sagen, das Programm randomisiert bereits die Werte des Wörterbuchs als Teil der StatusBuilder() - Funktion, aber ich frage mich, ob ich auch den Inhalt von Wörterbucheinträgen randomisieren kann, bevor sie von StatusBuilder() aufgerufen werden Helfen Sie jedem Status neu/anders. Ich könnte nur in ähnlichen Wörterbuch Einträge mit verschiedenen Obstnamen hinzufügen, aber das fühlt sich nicht Pythonic ... – phillipbrooker

Antwort

5

Sie konnten die random.choice Funktion als Wert in Ihrem Wörterbuch benutzen (Ich habe Ihr Beispiel einiges vereinfacht):

import random 
fruits = ["mango", "pomelo", "guava", "grapefruit", "watermelon"] 
DoDict = {'do1': random.choice} 

Auf diese Weise können Sie ein zufälliges Obst bekommst jedes Mal, wenn das Wörterbuch zugreifen:

def random_fruit(): 
    while True: 
     yield random.choice(["mango", "pomelo", "guava", "grapefruit", "watermelon"]) 
DoDict = {'do1': random_fruit().next} 
012:
>>> for i in range(10): print DoDict['do1'](fruits) 
guava 
pomelo 
watermelon 
mango 
watermelon 
grapefruit 
pomelo 
watermelon 
watermelon 
watermelon 

Sie könnten auch einen Generator verwenden

In diesem Fall brauchen Sie nicht die Liste der Früchte als Parameter zu übergeben:

>>> for i in range(10): print DoDict['do1']() 
grapefruit 
pomelo 
pomelo 
guava 
grapefruit 
pomelo 
pomelo 
pomelo 
mango 
guava 
+0

Ich werde versuchen, diese beiden Lösungen so bald wie möglich, beide sehen wirklich vielversprechend, so dass Sie sehr viel dafür, wird melde mich zurück, wenn ich mit ihnen gereist bin! ABER, schnelle Frage zuerst - ist hier dringend notwendig? Ich habe absolut keine Ahnung, was numpy tut, habe es vorher nicht benutzt, also frage mich nur, was es jenseits der bestehenden zufälligen Auswahlmöglichkeit bietet ... – phillipbrooker

+0

Ja, numpy ist nicht unbedingt notwendig, du kannst das Zufallsmodul verwenden stattdessen (ich habe meine Antwort entsprechend bearbeitet). – Tonechas

+0

Hmmm, versuchte beide, und beide schienen das Problem zu reproduzieren (dh es würde zufällig eine Frucht zum ersten Mal auswählen, als der Eintrag aufgerufen wurde, aber würde dann diese Auswahl für alle zukünftigen Instanzen behalten) ... Ich habe auch versucht, die neu zu formatieren Wörterbücher in eine einfachere Liste und entfernte die Klassen, um zu versuchen und Dinge zu vereinfachen, und kein Glück. Zu denken, dass es eher ein Problem mit meiner Reihenfolge der Operationen ist - wird meinen ursprünglichen Beitrag bearbeiten. Danke für die großartigen Ideen, gut, neue Wege zu lernen! – phillipbrooker

Verwandte Themen