__setattr__ взломать код?
Вот код, который у меня есть
class Human(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
print 'Hi there, I am '+ self.name
def ThankHeavens(self):
return 'Thanks Gods!'
class Soldier(Human):
def __init__(self, name, gender, rank):
super(Soldier, self).__init__(name, gender)
self.rank = rank
print self.rank + ' reporting!'
class Officer(Soldier):
def __init__(self, name, gender, rank, num_subordinates):
super(Officer, self).__init__(name, gender, rank)
self.num_subordinates = num_subordinates
def __setattr__(self, rank, value):
if rank not in ['lieutenant', 'captain', 'major', 'colonel', 'commander', 'admiral']:
print 'Invalid officer rank'
else:
super(Officer, self).__setattr__(rank, value)
Это ломается всякий раз, когда я пытаюсь создать офицера:
helo = Officer(name='Agathon',
gender='m',
rank='lieutenant',
num_subordinates=0)
Traceback (most recent call last):
File "hw7.py", line 39, in <module>
num_subordinates=0)
File "hw7.py", line 20, in __init__
super(Officer, self).__init__(name, gender, rank)
File "hw7.py", line 14, in __init__
super(Soldier, self).__init__(name, gender)
File "hw7.py", line 7, in __init__
print 'Hi there, I am '+ self.name
AttributeError: 'Officer' object has no attribute 'name'
Почему он не распознает имя, которое я ввел при определении helo
?
2 ответа
То, что вы не опубликовали, это два сообщения, созданные вашим __setattr__
:
Invalid officer rank
Invalid officer rank
Это происходит из следующих строк:
self.name = name
self.gender = gender
Так как они терпят неудачу, вы не можете получить имя позже:
print 'Hi there, I am '+ self.name
Fix:
def __setattr__(self, key, value):
if key == "rank" and value not in [.....]
Ваш __setattr__
вызывается, когда любой атрибут Officer
устанавливается в любое время любым способом, в том числе при инициализации через суперкласс __init__
,
когда __setattr__
называется, self
будет Officer
пример, rank
будет именем устанавливаемого атрибута, и value
будет значение, требуемое для того, чтобы приписать.
Что вы сделали, это сделать Officer
класс такой, что он может иметь .lieutenant
и т.д. для значений в вашем списке, но не .rank
(или же .name
или же .gender
) - и вы вообще не ограничивали значение этого атрибута.
Это более глубокая магия, чем вы искали; Вы явно хотели ограничить значения, используемые при настройке .rank
приписывать конкретно. Для этого используйте свойство.