【问题标题】:__setattr__ breaking code?__setattr__ 破坏代码?
【发布时间】:2012-08-25 22:22:24
【问题描述】:

这是我的代码

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时输入的名字?

【问题讨论】:

  • 为什么要覆盖__setattr__?也许更好的主意是在Soliderofficer 类中为__init__ 方法添加一些逻辑。
  • 您应该使用属性设置器,而不是使用setattr 来检查参数的有效性。

标签: python setattr


【解决方案1】:

你没有发布的是你__setattr__创建的两条消息:

Invalid officer rank
Invalid officer rank

这些来自以下几行:

self.name = name
self.gender = gender

由于这些失败,您以后无法检索名称:

 print 'Hi there, I am '+ self.name

修复:

def __setattr__(self, key, value):
    if key == "rank" and value not in [.....]

【讨论】:

    【解决方案2】:

    Officer 的任何属性在任何时间以任何方式设置时都会调用您的__setattr__,包括在通过超类__init__ 进行初始化期间。

    当调用__setattr__ 时,self 将是Officer 实例,rank 将是正在设置的属性的名称value 将是所需的值对于那个归因。

    您所做的是创建Officer 类,这样它就可以为列表中的值设置.lieutenant 等,但不能使用.rank(或.name.gender) - 而你实际上根本没有限制该属性的值。

    这比你想要的更深奥的魔法;您显然想限制在设置.rank 属性时使用的。为此,请使用属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 1970-01-01
      • 2017-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多