为什么我会收到“AttributeError: 对象没有属性”的错误?

111
我有一个名为MyThread的类。在其中,我有一个叫做sample的方法。我正在尝试在相同的对象上下文中运行它。请查看以下代码:
class myThread (threading.Thread):
    def __init__(self, threadID, name, counter, redisOpsObj):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
        self.redisOpsObj = redisOpsObj
        
    def stop(self):
        self.kill_received = True
            
    def sample(self):
        print "Hello"
                
    def run(self):
        time.sleep(0.1)
        print "\n Starting " + self.name
        self.sample()

看起来非常简单,不是吗?但是当我运行它时,我得到了这个错误:

AttributeError: 'myThread' object has no attribute 'sample'现在我有那个方法,就在那里。那么问题出在哪里呢?请帮忙解决。

编辑:这是堆栈跟踪

Starting Thread-0

Starting Thread-1
Exception in thread Thread-0:
Traceback (most recent call last):
File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner
self.run()
File "./redisQueueProcessor.py", line 51, in run
self.sample()
AttributeError: 'myThread' object has no attribute 'sample'

Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner
self.run()
File "./redisQueueProcessor.py", line 51, in run
self.sample()
AttributeError: 'myThread' object has no attribute 'sample'

我是这样调用它的

arThreads = []
maxThreads = 2;

for i in range( maxThreads ):
    redisOpsObj = redisOps()
    arThreads.append( myThread(i, "Thread-"+str(i), 10, redisOpsObj) )

抱歉,我不能发布redisOps类的代码。但是我可以向您保证它完全正常工作。


2
有代码丢失吗?这段代码片段在我的电脑上可以正常工作。 - ThirdOne
2
非常抱歉。是的,我的缩进重复了。在Python方面完全是个新手,可能忽视了缩进的重要性。 - Shades88
在编写Python代码时,您应该在代码编辑器中选择“显示制表符和空格”。 - vanduc1102
我认为对我来说,这是在子类中添加一个方法并忘记在基类中添加的情况。然后当调用基类的实例时,该方法不存在以执行。 - JGFMK
1
这个问题应该被复制到I'm getting an IndentationError. How do I solve it?,因为这个问题是一个无法重现的缩进问题,而这个链接是针对此类问题的规范解答。然而,这个标题完全不适合作为标志。对于绝大多数遇到这个错误信息的人来说,这个问题是完全没有帮助的,因此它应该被删除。然而,目前有很多问题被错误地关闭为此问题的重复(它们是不同的问题)。 - Karl Knechtel
显示剩余3条评论
9个回答

125

您的缩进有误,而且混合使用了制表符和空格。请使用python -tt命令运行脚本进行验证。


1
谢谢你的启示,我明白了。抱歉提了这么个愚蠢的问题并且解释得太长了 ;) - Shades88
10
请问您,“Run the script with python -tt to verify”这句话的意思是什么? 请使用python -tt命令运行脚本以进行验证。 - akshay_rahar
14
使用命令 python -tt script.py 以严格执行Python编码规范。 - Ignacio Vazquez-Abrams
1
那么,这个神奇的参数-tt是做什么用的?我在文档中没有找到它。 - Łukasz Nojek
31
Python 3 中不存在 -tt 标志,它仅存在于 Python 2 中。 - Łukasz Nojek
显示剩余3条评论

38

如果您正在使用Python 3+,这可能也会发生在您使用以双下划线开头的私有变量时,例如self.__yourvariable。对于可能遇到此问题的某些人,这是需要注意的事项。


它是否在PIP中有记录? - dashesy
3
刚遇到这个问题,看到了这条评论,为什么他们会这样设计呢? - neurothew
3
这里有文档记录:https://docs.python.org/3/tutorial/classes.html#private-variables - Mohit
1
我正在使用Spyder进行调试,如果在执行过程中调用私有类函数,则可以正常工作;但是尝试将其作为回调参数提供给选择器,则会出现错误。我在Python2中从未遇到过这种情况。非常令人沮丧。 - PfunnyGuy

19

当使用Python多线程时,此类错误很常见。发生这种情况是因为在解释器清除时,相关模块(在本例中为myThread)会经历一种类似于del myThread的过程。

调用self.sample()大致相当于myThread.__dict__["sample"](self)。但如果正在进行解释器的清除序列,则已知类型的自身字典可能已经删除了myThread,现在它基本上是一个NoneType - 并且没有'sample'属性。


3
我知道我晚了五年,但你知道这个问题的解决方案吗? - djo

13

这也可能发生在使用__slots__的类中,该类未提及所需属性的情况下。例如:

class xyz(object):
    __slots__ = ['abc', 'ijk']
    def __init__(self):
       self.abc = 1
       self.ijk = 2
       self.pqr = 6

尝试创建实例失败:
>>> xyz()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __init__
AttributeError: 'xyz' object has no attribute 'pqr'

2

在多线程场景下(特别是在处理ZMQ时),我遇到了这个错误。结果发现,一个线程仍在连接套接字,而另一个线程已经开始发送数据。由于另一个线程尝试访问尚未创建的变量,因此发生了事件。如果您的场景涉及多线程,并且在添加一点延迟后事情正常运行,则可能会遇到类似的问题。


1

Python通过在名称中包含类名来保护这些成员。 您可以访问这些属性,如object._className__attrName。


0
我也遇到了同样的错误。我确定我的缩进没有问题。只有重新启动Python shell才解决了这个问题。

1
你可以发布重新启动或其他命令。对于初学者来说可能会有所帮助。 - User
1
如何“重新启动Python Shell”? - Andrew
1
@Andrew 很确定他指的是“Python shell”,当然,这仅适用于您正在使用Python解释器的情况下。 - kaios

0
当我有另一个名为mythread的变量时,发生了相同的错误。那个变量覆盖了这个变量,这就是为什么我会得到错误。

-3

你无法访问类的私有字段。私有字段以 __ 开头。 例如 -

class car:
    def __init__(self):
        self.__updatesoftware()

    def drive(self):
        print("driving")

    def __updatesoftware(self):
        print("updating software:")

obj = car()
obj.drive()  
obj.__updatesoftware()  ## here it will throw an error because 

__updatesoftware 是一个私有方法。


4
作者并不是在尝试访问私有方法,此问题也超过了6年并已解决,因此无需再次尝试回答它。 - Johan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接