2016-12-01 5 views
1

Я пытаюсь вызвать функции в python 2.7, представив список и попросив пользователя выбрать индекс элемента в списке. Я смущен в двух пунктах:Вызывающие функции с пользователем Введенные индексы

  1. Как пользовательский индекс может соответствовать функции, определенной в исходном списке? Я понимаю, как выбирать элементы в списке, но не понимаю, как вызвать функцию.

  2. Где я должен помещать этот блок кода? В основной функции?

Вот мой код: Спасибо

''' 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''' возвращает строку, попробуйте' '', если user_input == '0'''' и '' ', если user_input ==' 1'''' – wwii

+0

правой спасибо, может также использовать его, но как это будет соответствовать вызовам функции? –

+0

Я уверен, что вы спрашиваете. Вы хотите выбрать функцию из списка по его индексу и вызвать его? – wwii

ответ

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

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

Помещенный функции в списке

>>> funcs = [f, g] 

Индексировать список с вводом пользователя и присвоить результат на имя.

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

Зов это

>>> func() 
bar 

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

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

Для вызова различных функций несколько раз с заданными аргументами на основе выбора пользователя - вам нужно связать выбор пользователя с функциями и функциями с аргументами, с которыми они будут вызываться. Это может быть сделано с помощью словаря

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

Тогда можно построить меню вариант с

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

Затем необходимо выбрать и вызвать функцию, как это. Обратите внимание, что *args, asterisk распаковывает несколько элементов в списке или кортеже.

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

Если построить словарь слишком много или слишком мало аргументов функции он будет бросать исключение TypeError при вызове функции. Если пользователь отправляет недействительный параметр, вы получите исключение KeyError. Handling Exceptions.


Это кажется немного запутанным по сравнению с простыми условными, которые вы использовали в вашем примере, но если у вас есть много функций, это может быть лучше, и это позволяет построить/изменить словарь во время выполнения с различными значениями аргументов.

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

Это не очень общий и кажется, что он может быть инкапсулирован в класс. Готов поспорить, это довольно обычная вещь, и если вы ищете вокруг, кто-то придумал что-то более утонченное.


Возможное уточнение было бы использовать collections.namedtuple, чтобы сделать его немного более удобным для чтения.

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

Спасибо. Это похоже на работу; однако, интересно, как это будет работать, если функция имеет аргументы или если вы хотите вызвать одну и ту же функцию несколько раз с разными аргументами (например, в моем коде выше). Моя цель - это когда индекс вводится пользователем, это будет соответствовать условию, которое допускает последовательность функций. (также, будет ли этот блок кода идти в основном заявлении или до объявления функций?) Еще раз спасибо, я очень ценю помощь. –

+0

@ErikSvenBroberg, используя условные утверждения, подобные вашему примеру, кажется простым и простым. Почему вы хотите сделать это по-другому? – wwii

+0

Благодарим вас за подробный ответ. Я думал об использовании словарей, и это хорошо работает. Я согласен, что «если утверждения» являются простейшим решением; однако мне было интересно узнать, как можно добиться решения, которое вы представили. Большое вам спасибо, поскольку я многому научился из ваших вкладов. –

Смежные вопросы