【问题标题】:AttributeError: <Class> object has no attribute outside loop?AttributeError: <Class> 对象在循环外没有属性?
【发布时间】:2020-03-09 21:30:53
【问题描述】:

我有一个班级叫state_class

class state_class:
  def __init__(self, state_name): 

    self.state_name = state_name

    @property
    def state_col(self):
        """state_col getter"""
        return self._state_col

    @state_col.setter
    def state_col(self):
        """state_col setter"""
        self._state_col = state_col

我在if 语句和for 循环中启动这个类:

for region in regions:
  if region == '1':
    for region in regions:
        for col in range(prelim_sheet.ncols):
          if (prelim_sheet.cell_value(0, col) == r.region_name):
           ...
          else:
            for state in state_list:
                if state.strip() == 'NewHampshire':  
                    s = state_class(state)
                    if ((prelim_sheet.cell_value(0, col)).replace(" ", "") == s.state_name):
                        s.state_col = col
                        print(s.state_col)
                        ...

如您所见,在底部,我有一个s.state_col 的打印语句,它打印出正确的值。但是,如果我尝试在 iffor 循环之外调用 s.state_col,则会收到错误消息:

AttributeError Traceback(最近调用 最后)在 ----> 1 s.state_col

AttributeError: 'state_class' 对象没有属性 'state_col'

我已经在循环之外对此进行了测试,它工作正常:

s = state_class('NewHampshire')
col = 20
s.state_col = col
print(s.state)
>>> 20

是否有理由将state_col 设置在循环内或让我在外部调用它?我该如何解决这个问题?

【问题讨论】:

  • 在您的情况下,在调用 setter 之前调用 getter 将调用该异常,因为 self._state_col 否则不存在,这与有状态编程的概念完全一致。这可以说是一个糟糕的设计选择:您应该要么处理异常,要么避免这种有状态的编程。顺便说一句,所有属性都应该在对象初始化期间声明。您始终可以将 None(或任何其他“空”值)分配给未设置的变量并在 getter 中处理这种情况。
  • 我对更好的设计有点困惑。我对使用classes 有点陌生,我不确定你在设置器之前调用getter 是什么意思。你能说明一下吗?

标签: python-3.x class initialization getter-setter


【解决方案1】:

经过多次尝试和错误,我确定这个问题的症结不在state_class getter 和 setter(它们在循环中工作),而是我放在最后的else 语句。

for col in range(prelim_sheet.ncols):
    if (prelim_sheet.cell_value(0, col) == r.region_name):
       ...
    else:
        for state in state_list:
            if state.strip() == 'NewHampshire':  
                s = state_class(state)
                if ((prelim_sheet.cell_value(0, col)).replace(" ", "") == s.state_name):
                    s.state_col = col
                    print(s.state_col)

本质上,这就是说,如果不满足第一个条件,则继续遍历列(大约有 34 列),并且类实例化在此过程中会变得混乱。 为了解决这个问题,我添加了一些东西。 1) 我更改了else' to anelif` 语句并设置了一些标准。 2)我添加了一个动态字典,允许我为每个州存储一个类的实例(使用'NewHampshire'只是为了测试目的)。虽然我认为 @big_bad_bison 的解决方案可能会奏效(我相信他们),但我的新解决方案实际上是在这种情况下最适合我的解决方案。感谢您的帮助:

    state_map = {}
    for col in range(prelim_sheet.ncols):
        col_name = prelim_sheet.cell_value(0, col)

        if (col_name == region_map[region].region_name):
            region_map[region].region_total_col = col
            region_map[region].detailed_col = region_map[region].region_total_col
            region_map[region].approx_col = region_map[region].region_total_col + 1
            region_map[region].unmapped_col = region_map[region].region_total_col + 2
            region_map[region].total_col = region_map[region].region_total_col + 3


        elif (col_name.replace(" ", "") in region_map[region].region_long_list):
            state = col_name
            state_map[state] = state_class(state)
            state_map[state].state_col = col
            state_map[state].detailed_col = state_map[state].state_col
            state_map[state].approx_col = state_map[state].state_col + 1
            state_map[state].unmapped_col = state_map[state].state_col + 2
            state_map[state].total_col = state_map[state].state_col + 3    
            print("The col is {}".format(str(col)),state_map[state].state_col, state)

        region_map[region].state_map = state_map

【讨论】:

    【解决方案2】:

    正如@Eli Korvigo 所说,你应该在一个类的 init 函数中初始化所有变量,否则在你设置它们之前它们不存在。

    编辑:

    我仔细查看了您的代码,缩进不正确,setter 函数需要输入。不太重要的是,类名应该是 CamelCase。这段代码现在应该可以工作了:

    class StateClass:
        def __init__(self, state_name):
            self.state_name = state_name
            self._state_col = None
    
        @property
        def state_col(self):
            """state_col getter"""
            return self._state_col
    
        @state_col.setter
        def state_col(self, s):
            """state_col setter"""
            self._state_col = s
    

    【讨论】:

    • 好的,我就是这样做的,但我仍然收到相同的AttributeError: 'state_class' object has no attribute 'state_col' 错误。
    • @gwydion93,不确定您是否注意到,但我不久前编辑了我的评论以解决问题。很抱歉没有通知你。
    猜你喜欢
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    • 2012-12-01
    • 2021-04-19
    • 2021-11-22
    相关资源
    最近更新 更多