#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