首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python类丢失属性

Python类丢失属性
EN

Stack Overflow用户
提问于 2012-11-10 19:02:49
回答 3查看 2.3K关注 0票数 10

我有一个特殊的蟒蛇问题。在我的gtk python应用程序的执行过程中,我的一些类对象神秘地丢失了属性,导致程序的一些功能中断。

很难理解为什么会发生这种情况--我从来没有故意删除属性,而且有问题的类继承自我自己编写的类(而不是其他类)。

我可以通过重复执行某个操作来触发问题(例如,通过疯狂单击或打开文件来生成对add_card方法的多次调用,从而导致add_card被调用20次左右)

我真的不知所措,我希望我有更多我认为有用的信息给你。

什么会导致python对象丢失属性?

编辑,重新。问题:

下面是与I‘lose’这两个属性相关的示例回溯:

代码语言:javascript
复制
Traceback (most recent call last):
  File "lib/genericlist.py", line 90, in cursor_changed
    if self.viewer:
AttributeError: 'DeckerRunnerList' object has no attribute 'viewer'



Traceback (most recent call last):
  File "lib/genericlist.py", line 100, in row_activated
    selection = self.TABLE_NAME+"&&"+text
AttributeError: 'DeckerRunnerList' object has no attribute 'TABLE_NAME'

下面是它们设置的位置:

代码语言:javascript
复制
class DeckerGenericList(object):   

    def __init__(self, database, viewer=None, deck=None):

        super(DeckerGenericList, self).__init__()

        self.database = database
        self.viewer = viewer
        self.deck = deck
        #TABLE_NAME is set in the subclass constructor

这个特殊的子类没有调用它的超类__init__,所以属性集在子类中是重复的:

代码语言:javascript
复制
class DeckerRunnerList(DeckerGenericList):

      def __init__(self, database, viewer=None, deck=None):

        self.database = database
        self.viewer = viewer
        self.deck = deck
        self.TABLE_NAME = "runners"

DeckerGenericList的所有其他子类都有同样的问题,它们都是这样定义的:

代码语言:javascript
复制
class DeckerGearList(DeckerGenericList):

    def __init__(self, database, viewer=None, deck=None):

        self.TABLE_NAME = "gear"
        #... some other class attributes

        super(DeckerGearList, self).__init__(database, viewer=viewer, deck=deck)
EN

回答 3

Stack Overflow用户

发布于 2012-11-28 18:30:07

python (因此也可能是PyGtk或其他框架)有一个奇怪的行为,即在属性代码内/下的某个地方实际引发一个AttributeError,实际上会使python报告该对象上不存在被调用的属性。

关于这是为什么(实际上是正确的和可以理解的行为),有一个(某种程度上更官方的)故事。这与在基类上定义__getattr__有关:它的工作原理是,如果调用对象的属性导致AttributeError,则会调用__getattr__方法。但是该方法并不知道实际上没有找到什么“属性”。由于(PyQt.QObject) __getattr__是为实现“特定”属性而设计的,因此它决定引发另一个提到“called”属性的AttributeError。

无论如何,可能的情况是,您正在从某个使用__getattr__的对象继承,而您自己的属性代码确实调用了(另一个)属性,而这个属性实际上并不存在。您可以执行以下操作来进行检查:

代码语言:javascript
复制
@property
def myproperty:
   try:
      doStuff..
   except AttributeError as e:
      print "Got ya! It is withing the attribute:", repr(e)
      raise ValueError("Got an AttributeError within my attribute!")

更新/注意:另外,如果您自己在DeckerGenericList对象上实现__getattr__,请出于同样的原因小心使用它!在__getattr__中引发AttributeError在大多数情况下会导致类似这样的奇怪行为。请注意,没有简单的解决方法:“真正的”AttributeError只携带字符串消息(而不是具体的实际属性名),但更重要的是:__getattr__函数从一开始就看不到原始的AttributeError。

票数 3
EN

Stack Overflow用户

发布于 2012-11-23 05:12:55

您可以使用属性和检查模块来跟踪属性的更改,如下所示:

代码语言:javascript
复制
import sys
import inspect

def from_where_called():
    info = inspect.getframeinfo(sys._getframe(2))
    code = info.code_context[0] if info.code_context else ''
    return '%s:%s %s' % (info.filename, info.lineno, code)

def add_watched_attribute(name):  
    def attr_watch_get(self):
        value = getattr(self, '_' + name, 'unset')
        print from_where_called(), name, 'is', value
        return value

    def attr_watch_set(self, value):
        print from_where_called(), name, 'set to', value
        setattr(self, '_' + name, value)

    def attr_watch_delete(self):
        print from_where_called(), name, 'deleted'
        delattr(self,'_' + name)

    sys._getframe(1).f_locals[name] = property(
        attr_watch_get, attr_watch_set, attr_watch_delete
    )


class InspectedClass(object):
    add_watched_attribute('victim')

    def __init__(self):
        self.victim = 2

    def kill(self):
        del self.victim


x = InspectedClass()
x.victim = 'asdf'
x.kill()

或者,您可以使用这个答案中的sys.settrace:https://stackoverflow.com/a/13404866/816449

票数 1
EN

Stack Overflow用户

发布于 2013-02-09 05:31:53

我认为这是一个垃圾收集器的错误。我也遇到过类似的问题,我想我已经把范围缩小到了GC。

尝试在包含丢失属性的类的模块顶部添加一个列表extra_references = []。在该类的__init__方法中,添加以下代码:

代码语言:javascript
复制
global extra_references
extra_references.append(self)

这将确保在GObject之外始终存在对该对象的引用。

如果问题消失了,那么Python的垃圾收集器就会在您处理完对象之前吃掉它。闻起来很像这个bug (应该已经修复了):https://bugzilla.gnome.org/show_bug.cgi?id=92955

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13321448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档