Как печатать функции с изменяющимся именем функции

#python #python-3.x

#python #python-3.x

Вопрос:

Я пишу функцию, которая печатает пользовательский ввод в виде алфавитного шаблона. Пример: если пользовательский ввод является A, то на выходе должна быть форма из звездочек (*)

Вот мой код

 def letter_a():
    for hz_line in range(4):
        for vert_line in range(4):
            if ((vert_line == 0 or vert_line == 3) and hz_line != 0) or ((hz_line == 0 or hz_line == 2)
                                                                         and (0 < vert_line < 3)):
                print("x", end="")
            else:
                print(end=" ")
        print()


def letter_n():
    for hz_line in range(4):
        for vert_line in range(5):
            if (vert_line == 0 or vert_line == 4) or (vert_line == hz_line):
                print("x", end="")
            else:
                print(end=" ")
        print()


def letter_u():
    for hz_line in range(4):
        for vert_line in range(4):
            if ((vert_line == 0 or vert_line == 3) and hz_line != 3) or (hz_line == 3
                                                                         and (vert_line == 1 or vert_line == 2)):
                print("x", end="")
            else:
                print(end = " ")
        print()


userinput = input()
inputlen = int(len(userinput))
print(inputlen)
for char in range(inputlen):
    print("letter_%s()" % userinput[char], end=" ")
  

Как вы можете видеть, на выходе выводится имя функции, а не сама функция. Как это можно сделать?

Комментарии:

1. Создайте словарь, который сопоставит символ с функцией. d={"a": letter_a}; d["a"]()

Ответ №1:

Делать то, что вы делаете, не лучший способ добиться этого. Как упоминал @jakub, неплохо было бы использовать словарь.

Вы могли бы даже сделать что-то вроде этого:

 
LETTERS = {
    "A": [
        " xx ",
        "x  x",
        "xxxx",
        "x  x"
    ],
    "N": [
        "x   x",
        "xx  x",
        "x x x",
        "x  xx"
    ]
}

def print_letter(letter):
    for line in letter:
        print(line)

userinput = input()

for char in userinput:
    if char.upper() in LETTERS:
        letter = LETTERS[char.upper()]
        print_letter(letter)

  

Попытка вызвать методы на основе их имени несколько банальна, и я бы не рекомендовал ее, если только вам действительно не пришлось. Вы должны убедиться, что полученные вами входные данные были правильными. Что, если входные данные a(0- -== . Проще проверить словарь, чтобы узнать, поддерживаете ли вы этот символ (что я и делаю в if char.upper() in LETTERS строке).

Если бы вам действительно нужно было, вы могли бы сделать это:

 userinput = input()

for char in userinput:
    # access the method
    letter_method = locals()["letter_"   char]
    #call the method
    letter_method()
  

locals() globals() ) возвращают словари, которые затем можно использовать для доступа к переменным в зависимости от области видимости. (См.https://docs.python.org/3/library/functions.html#locals). Это довольно метапрограммирование, и я бы не стал использовать его на данном этапе.

Ответ №2:

используйте globals() для вызова функции со строкой вместо имени:

 userinput = input()
inputlen = int(len(userinput))
print(inputlen)
for char in range(inputlen):
    print(globals()["letter_%s()" % userinput[char]]())
  

Ответ №3:

Несколько моментов:

  • Печать обрабатывается вашими функциями letter_a , letter_u и letter_n . Они ничего не возвращают ( None ) и, следовательно, передача их на печать не будет полезной.

  • Вы передаете print строку имени функции, не вызывая функцию. Попробуйте следующее:

 ...
for c in userinput:
  if c.lower() == 'a':
    letter_a()
  elif c.lower() == 'u':
    letter_u()
  elif c.lower() == 'n':
    letter_n()
  else:
    print(c   " is not a valid character!")
  

Я не проверял логику в ваших letter_ функциях, но предполагая, что они в порядке, это должно сработать.