Железный Python получает атрибуты экземпляра класса на основе ввода строки

#python #ironpython #instances

#python #ironpython #экземпляры

Вопрос:

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

 class Animal(object):
    def __init__(self, name, age, happiness, hunger):
        self.name = name
        self.age = age
        self.happiness = happiness
        self.hunger = hunger


def animal_print(animal):
    if animal.lower() in animals:
        print "%s, the %s, is %s years old. % (animal.name, animal, animal.age)


pig = Animal("Joe", 12, 7, 6)
fox = Animal("Fred", 4, 4, 6),
cow = Animal("Bessy", 9, 6, 3),
horse = Animal("Sally", 7, 8, 8),

animals = ["pig", "fox", "cow", "horse"]


animal_print(raw_input("Which animal would you like to see: "))
  

Основы этого кода заключаются в том, что пользователь вводит животное из списка animals, а затем я бы хотел, чтобы оно возвращало атрибуты элемента. Если я изменю свой код на приведенный ниже, это сработает, но в идеале я хотел бы получить только одну инструкцию print для всех экземпляров класса, тогда как приведенная ниже инструкция print потребует отдельной инструкции для каждого экземпляра:

 def animal_print(animal):
    if animal.lower() in animals:
        print "%s, the %s, is %s years old % (pig.name, animal, pig.age)
  

Ответ №1:

str 'pig' Это не то же самое, что экземпляр Animal , хранящийся в переменной pig .

raw_input возвращает str . Итак, в animal_print функции, animal является str . У str него нет name атрибута, поэтому animal.name возникнет AttributeError .

Есть по крайней мере три способа исправить код: использовать dict из «белого списка», выполнить поиск значения в globals() dict или использовать eval . Из этих трех использование белого списка является самым безопасным, поскольку глобальные запросы и eval не должны быть разрешены при произвольном пользовательском вводе. Один может привести к утечке личной информации, а другой может позволить злоумышленнику запускать произвольный код.

Поэтому используйте белый список:

 animap = {'pig': pig,
          'fox': fox}
anistr = raw_input(...)   # str
animal = animap[anistr]   # Animal instance
  

 class Animal(object):
    def __init__(self, name, age, happiness, hunger):
        self.name = name
        self.age = age
        self.happiness = happiness
        self.hunger = hunger


def animal_print(anistr):
    animal = animap.get(anistr.lower())
    if animal is not None:
        print "%s, the %s, is %s years old." % (animal.name, anistr, animal.age)


pig = Animal("Joe", 12, 7, 6)
fox = Animal("Fred", 4, 4, 6)
cow = Animal("Bessy", 9, 6, 3)
horse = Animal("Sally", 7, 8, 8)

animap = {'pig': pig,
          'fox': fox,
          'cow': cow,
          'horse': horse}

anistr = raw_input("Which animal would you like to see: ")

animal_print(anistr)
  

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

1. Спасибо за ответ, я понимаю, о чем вы говорите, и вроде бы понял, почему это не сработало, есть ли какие-либо способы решения этой проблемы с выбором пользователем экземпляра класса? raw_input не является обязательным, но мне нужно, чтобы пользователь мог выбрать животное

2. Работает как по волшебству, собираюсь поиграть со своим кодом, посмотреть, смогу ли я немного привести его в порядок. Еще раз спасибо

3. Вы можете заменить if anistr.lower() in animap: на if animal: в сочетании с animal = animap.get(anistr.lower())

Ответ №2:

Вероятно, вам лучше использовать словарь в качестве контейнера для ваших экземпляров animal. Ключом может быть название животного в виде строки, а значением будет Animal экземпляр. Тогда ваша animal_print() функция может обрабатывать только печать атрибутов animal.

 def animal_print(animal):
    print "%s, the %s, is %s years old." % (animal.name, animal, animal.age)

animals = {
    'pig': Animal("Joe", 12, 7, 6),
    'fox': Animal("Fred", 4, 4, 6),
    'cow': Animal("Bessy", 9, 6, 3),
    'horse': Animal("Sally", 7, 8, 8),
}

user_animal = raw_input("Which animal would you like to see: ")
try:
    animal_print(animals[user_animal.lower()])
except KeyError:
    print "I no nothing about animal %s." % user_animal