2016-12-01 2 views
1

Ich versuche, Funktionen in Python 2.7 aufzurufen, indem ich eine Liste präsentiere und den Benutzer auffordere, den Index des Elements in der Liste auszuwählen. Ich bin in zwei Punkten verwirrt:Aufruf von Funktionen mit vom Benutzer eingegebenen Indizes

  1. Wie kann der vom Benutzer eingegebene Index der Funktion entsprechen, die in der ursprünglichen Liste definiert ist? Ich verstehe, wie man Elemente in einer Liste auswählt, aber nicht verstehe, wie man eine Funktion aufruft.

  2. Wo sollte ich diesen Codeblock setzen? In der Hauptfunktion?

Hier ist mein Code: Danke

''' neoPixel setups''' 
import time 
from neopixel import * 

# LED configuration. 
LED_COUNT = 16 # Number of LED pixels. 
LED_PIN = 12 # GPIO pin connected to the pixels (must support PWM!). 
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) 
LED_DMA = 5 # DMA channel to use for generating signal (try 5) 
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest 
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) 


def colorWipe(strip, color, wait_ms=50): 
    """Wipe color across display a pixel at a time.""" 
    for i in range(strip.numPixels()): 
     strip.setPixelColor(i, color) 
     strip.show() 
     time.sleep(wait_ms/1000.0) 


def theaterChaseRainbow(strip, wait_ms=50): 
    """Rainbow movie theater light style chaser animation.""" 
    for j in range(256): 
     for q in range(3): 
      for i in range(0, strip.numPixels(), 3): 
       strip.setPixelColor(i + q, wheel((i + j) % 255)) 
      strip.show() 
      time.sleep(wait_ms/1000.0) 
      for i in range(0, strip.numPixels(), 3): 
       strip.setPixelColor(i + q, 0) 


if __name__ == '_main_': 
    # create neopixel object with appropriate configuration 
    strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) 
    # initialize the library (must be called before other function) 
    strip.begin() 

    print 'Press Ctrl-C to quit' 

''' user input block ''' 
lighting_modes = 'rainbow', 'colorWipe' 

for i, item in enumerate(lighting_modes): 
    print i, item 

user_input = input("Please enter index of the lighting modes listed above") 

if user_input == 0: 
    colorWipe(strip, Color(255, 0, 0)) # red 
    colorWipe(strip, Color(0, 255, 0)) # blue 
    colorWipe(strip, Color(0, 0, 255)) # green 
elif user_input == 1: 
    theaterChase(strip, Color(127, 127, 127)) 
    theaterChase(strip, Color(127, 0, 0)) 
    theaterChase(strip, Color(0, 0, 127)) 
+0

'' 'input''' einen String zurückgibt, versuchen' '' wenn USER_INPUT == '0'''' und '' 'wenn USER_INPUT ==' 1'''' – wwii

+0

rechts danke, ich könnte es auch werfen, aber wie würde das den Funktionsaufrufen entsprechen? –

+0

Ich bin mir sicher, was Sie fragen. Möchten Sie eine Funktion aus einer Liste nach ihrem Index auswählen und aufrufen? – wwii

Antwort

4
>>> def f(): 
    print('foo') 

>>> def g(): 
    print('bar') 

die Funktionen in eine Liste setzen

>>> funcs = [f, g] 

Index die Liste mit der Eingabe des Benutzers und weist das Ergebnis ein Name.

>>> which = int(input('which .. ')) 
which .. 1 
>>> func = funcs[which] 

Nennen Sie es

>>> func() 
bar 

def fff(arg1, arg2): 
    print('f', arg1, arg2) 

def ggg(arg1, arg2): 
    print('g', arg1, arg2) 

verschiedene Funktionen mehrfach mit vorgegebenen Argumente auf einer Wahl des Benutzers basierend Anrufen - Sie die Auswahl des Benutzers mit den Funktionen und den Funktionen zuordnen müssen mit den Argumenten, mit denen sie aufgerufen werden. Dies könnte mit einem Wörterbuch

{choice : [function, [(args), (args), (args)]], ...} 

func_f = [fff, [('strip', 'blue'), ('strip', 'green'), ('strip', 'red')]] 
func_g = [ggg, [('strip', 'grey'), ('strip', 'dk_red'), ('strip', 'dk_blue')]] 

p = {'0': func_f, '1': func_g} 

Dann getan werden könnte Sie eine Option Menü mit

options = '\n'.join('{} - {}'.format(k, v[0].__name__) for k,v in p.items()) 
which = input('Which?\n' + options + '\n') 

konstruieren Dann würden Sie die Funktion wie folgt auswählen und anrufen. Beachten Sie die *args, das Sternchen entpackt mehrere Elemente in einer Liste oder Tupel.

func, calls = p[which] 
for args in calls: 
    func(*args) 

>>> 
Which? 
1 - ggg 
0 - fff 
1 
g strip grey 
g strip dk_red 
g strip dk_blue 
>>> 

Wenn Sie das Wörterbuch mit zu vielen oder zu wenigen Funktionsargumente konstruieren wird es eine Typeerror-Ausnahme ausgelöst wird, wenn die Funktion aufgerufen wird. Wenn der Benutzer eine ungültige Option sendet, erhalten Sie eine KeyError-Ausnahme. Handling Exceptions.


Dies scheint ein wenig gewunden im Vergleich zu den einfachen conditionals Sie in Ihrem Beispiel verwendet, aber wenn Sie viele Funktionen haben, das besser sein könnte und auf diese Weise können Sie das Wörterbuch zur Laufzeit mit unterschiedlichen Argumentwerten konstruieren/ändern.

f_calls = operator.itemgetter(1) 
f_calls(func_f).append(('strip', 'hazel')) 
f_calls (func_g)[0] = ('strip', 'maroon') 

pprint(p) 

>>> 
{'0': [<function fff at 0x000000000312C048>, 
     [('strip', 'blue'), 
     ('strip', 'green'), 
     ('strip', 'red'), 
     ('strip', 'hazel')]], 
'1': [<function ggg at 0x0000000003165268>, 
     [('strip', 'maroon'), 
     ('strip', 'dk_red'), 
     ('strip', 'dk_blue')]]} 
>>> 

Dies ist nicht sehr allgemein und es scheint, dass es in einer Klasse gekapselt werden könnte. Ich wette, das ist eine ziemlich gewöhnliche Sache, und wenn Sie sich umsehen, hat sich jemand etwas raffinierteres einfallen lassen.


Eine mögliche Ausgestaltung wäre collections.namedtuple zu verwenden, um es besser lesbar etwas zu machen.

Task = collections.namedtuple('Task', ['func', 'calls']) 
task_f = Task(fff, [('strip', 'blue'), ('strip', 'green'), ('strip', 'red')]) 
task_g = Task(ggg, [('strip', 'grey'), ('strip', 'dk_red'), ('strip', 'dk_blue')]) 

p = {'0': task_f, '1': task_g} 
options = '\n'.join('{} - {}'.format(item, task.func.__name__) for item,task in p.items()) 

which = input('Which?\n' + options + '\n') 

task = p[which] 
for args in task.calls: 
    task.func(*args) 


task_f.calls.append(('strip', 'candycane')) 
task_g.calls.remove(('strip', 'grey')) 
+0

Vielen Dank. Das scheint zu funktionieren; Ich frage mich jedoch, wie dies funktionieren würde, wenn die Funktion Argumente hätte, oder wenn Sie die gleiche Funktion mehrmals mit verschiedenen Argumenten aufrufen wollten (wie in meinem obigen Code). Mein Ziel ist, sobald der Index vom Benutzer eingegeben wird, dies erfüllt eine Bedingung, die eine Folge von Funktionen ermöglicht. (Würde auch dieser Code-Block in der Hauptaussage oder vor der Erklärung der Funktionen gehen?) Nochmals vielen Dank, ich schätze die Hilfe sehr. –

+0

@ErikSvenBroberg, mit bedingten Anweisungen wie Ihr Beispiel scheint am einfachsten und unkompliziert. Warum willst du es anders machen? – wwii

+0

danke für diese eingehende Antwort. Ich hatte über Wörterbücher nachgedacht und das funktioniert gut. Ich stimme zu, dass "wenn Aussagen" die einfachste Lösung sind; Ich war jedoch interessiert zu sehen, wie die von Ihnen präsentierte Lösung erreicht werden konnte. Vielen Dank, ich habe viel von Ihren Beiträgen gelernt. –

Verwandte Themen