2006年02月24日 星期五 20:03
(翻了一下旧信件) 这个问题不知道是不是Python不保证对象的析构顺序造成的呢?如果显式del就没问题 # Filename: objvar.py class Person: '''Represents a person.''' population = 0 def __init__(self,name): '''Initializes the person's data.''' self.name = name print '(Initializing %s)' % self.name Person.population += 1 def __del__(self): '''I am dying.''' print '%s says bye.' % self.name Person.population -= 1 if Person.population == 0: print 'I am the last one.' else: print 'There are still %d people left.' % Person.population def sayHi(self): '''Greeting by the person. Really, that's all it does.''' print 'Hi, my name is %s.' % self.name def howMany(self): '''Prints the current population.''' if Person.population == 1: print 'I am the only person here.' else: print 'We have %d persons here.' % Person.population lzh = Person('lzh') lzh.sayHi() lzh.howMany() lds = Person('lds') lds.sayHi() lds.howMany() lzh.sayHi() lzh.howMany() #此时Person类对象本身尚未被delete del lzh del lds #此时有可能Person类对象本身先于实例对象被delete 在05-12-21,l zh <lzhlds at gmail.com> 写道: > > # Filename: objvar.py > > class Person: > '''Represents a person.''' > population = 0 > > def __init__(self,name): > '''Initializes the person's data.''' > self.name = name > print '(Initializing %s)' % self.name > Person.population += 1 > > def __del__(self): > '''I am dying.''' > print '%s says bye.' % self.name > Person.population -= 1 > > if Person.population == 0: > print 'I am the last one.' > else: > print 'There are still %d people left.' % Person.population > > def sayHi(self): > '''Greeting by the person. > > Really, that's all it does.''' > print 'Hi, my name is %s.' % self.name > def howMany(self): > '''Prints the current population.''' > if Person.population == 1: > print 'I am the only person here.' > else: > print 'We have %d persons here.' % Person.population > > lzh = Person('lzh') > lzh.sayHi() > lzh.howMany() > > lds = Person('lds') > lds.sayHi() > lds.howMany() > lzh.sayHi() > lzh.howMany() > > > _________________________________输出_______________________________________________________ > > (Initializing lzh) > Hi, my name is lzh. > I am the only person here. > (Initializing lds) > Hi, my name is lds. > We have 2 persons here. > Hi, my name is lzh. > We have 2 persons here. > lds says bye. > Exception exceptions.AttributeError: "'NoneType' object has no attribute > 'population'" in<__main__.Person instance > at 0x00B14210>> ignored > lzh says bye. > Exception exceptions.AttributeError : "'NoneType' object has no attribute > 'population'" in<__main__.Person instance > at 0x00B141E8>> ignored > > > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060224/75e2cd93/attachment-0001.html
2006年02月26日 星期日 21:01
这个问题的根源在于在销毁Person的实例lds时,Person类对象自身已经被销毁了,所以访问Person.population当然失败,导致抛出异常。 把代码简化一下,并添加一些打印信息 class Person: population = 0 def __init__(self,name): Person.population += 1 def __del__(self): Person.population -= 1 lzh = Person('lzh') lds = Person('lds') print dir() print print '*************** print lzh ***************' print lzh print print '*************** print lds ***************' print lds print 输出为: ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'lds', 'lzh'] *************** print lzh *************** <__main__.Person instance at 0x00B33760> *************** print lds *************** <__main__.Person instance at 0x00B33C38> Exception exceptions.AttributeError: "'NoneType' object has no attribute 'popula tion'" in<__main__.Person instance at 0x00B33C3 8>> ignored Exception exceptions.AttributeError: "'NoneType' object has no attribute 'popula tion'" in <__main__.Person instance at 0x00B3376 0>> ignored 在Python执行完所有的字节码指令之后,Python会销毁自身的运行时环境,在这个过程中,会进入到import.c的PyImport_Cleanup中, 在这个函数中,会按照输出的第一行所示的顺序销毁对象,即Person类对象是第一个被销毁的。这一点可以从下面得到印证,在异常 的信息中,可以看到,第一个异常出现在对象0x00B33C38上,第二个异常发生在对象0x00B33760上,从输出的结果我们可以看到, 对象0x00B33C38正是lds,而对象0x00B33760是lzh。 如果显式调用del,则del将会产生字节码指令,Python对lds,lzh的销毁动作会在执行这些字节指令时发生,显然这早于Python销毁自身运行时 环境的动作,所以是安全的。 On 2/24/06, ajax chelsea <ajaxchelsea at gmail.com> wrote: > (翻了一下旧信件) > > 这个问题不知道是不是Python不保证对象的析构顺序造成的呢?如果显式del就没问题 > > > # Filename: objvar.py > > class Person: > '''Represents a person.''' > population = 0 > > def __init__(self,name): > '''Initializes the person's data.''' > self.name = name > print '(Initializing %s)' % self.name > Person.population += 1 > > def __del__(self): > '''I am dying.''' > print '%s says bye.' % self.name > Person.population -= 1 > > if Person.population == 0: > print 'I am the last one.' > else: > print 'There are still %d people left.' % Person.population > > def sayHi(self): > '''Greeting by the person. > > Really, that's all it does.''' > print 'Hi, my name is %s.' % self.name > def howMany(self): > '''Prints the current population.''' > if Person.population == 1: > print 'I am the only person here.' > else: > print 'We have %d persons here.' % Person.population > > lzh = Person('lzh') > lzh.sayHi() > lzh.howMany() > > lds = Person('lds') > lds.sayHi() > lds.howMany() > lzh.sayHi() > lzh.howMany() > > > #此时Person类对象本身尚未被delete > del lzh > del lds > #此时有可能Person类对象本身先于实例对象被delete > > > > 在05-12-21,l zh <lzhlds at gmail.com> 写道: > > > > # Filename: objvar.py > > > > class Person: > > '''Represents a person.''' > > population = 0 > > > > def __init__(self,name): > > '''Initializes the person's data.''' > > self.name = name > > print '(Initializing %s)' % self.name > > Person.population += 1 > > > > def __del__(self): > > '''I am dying.''' > > print '%s says bye.' % self.name > > Person.population -= 1 > > > > if Person.population == 0: > > print 'I am the last one.' > > else: > > print 'There are still %d people left.' % Person.population > > > > def sayHi(self): > > '''Greeting by the person. > > > > Really, that's all it does.''' > > print 'Hi, my name is %s.' % self.name > > def howMany(self): > > '''Prints the current population.''' > > if Person.population == 1: > > print 'I am the only person here.' > > else: > > print 'We have %d persons here.' % Person.population > > > > lzh = Person('lzh') > > lzh.sayHi() > > lzh.howMany() > > > > lds = Person('lds') > > lds.sayHi() > > lds.howMany() > > lzh.sayHi() > > lzh.howMany() > > > > > > _________________________________输出_______________________________________________________ > > > > (Initializing lzh) > > Hi, my name is lzh. > > I am the only person here. > > (Initializing lds) > > Hi, my name is lds. > > We have 2 persons here. > > Hi, my name is lzh. > > We have 2 persons here. > > lds says bye. > > Exception exceptions.AttributeError: "'NoneType' object has no attribute > > 'population'" in <__main__.Person instance > > at 0x00B14210>> ignored > > lzh says bye. > > Exception exceptions.AttributeError : "'NoneType' object has no > > attribute 'population'" in <__main__.Person > > instance at 0x00B141E8>> ignored > > > > > > > > _______________________________________________ > > python-chinese > > Post: send python-chinese at lists.python.cn > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > Unsubscribe: send unsubscribe to > > python-chinese-request at lists.python.cn > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -- Robert Python源码剖析――http://blog.donews.com/lemur/ -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060226/c801a76e/attachment.htm
2006年02月26日 星期日 21:26
呵呵,更正一下: 1、错误的真正根源在_PyModule_Clear中 2、Python在销毁运行时环境时,其顺序并非是由dir()显示的那个顺序。因为如果把你的两个变量名由lzh, lds改为a, b,则就没有异常产生了。 通过修改Python源代码,添加输出信息,可以对比一下这两种情况: 1. 变量名为a, b [修改source code的输出结果] ***************** Enter _PyModule_Clear************** [dict] : [a b __builtins__ __file__ Person __name__ __doc__ ] [Delete] : clear a [Delete] : clear b [Delete] : clear __file__ [Delete] : clear Person [Delete] : clear __name__ [Delete] : clear __doc__ ***************** Exit _PyModule_Clear************** [print dir() 的输出结果] ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'a', 'b'] 2. 变量名为lzh, lds [修改source code的输出结果] ***************** Enter _PyModule_Clear************** [dict] : [Person __builtins__ __file__ lds lzh __name__ __doc__ ] [Delete] : clear Person [Delete] : clear __file__ [Delete] : clear lds Exception exceptions.AttributeError: "'NoneType' object has no attribute 'popula tion'" in<__main__.Person instance at 0x00B4307 8>> ignored [Delete] : clear lzh Exception exceptions.AttributeError: "'NoneType' object has no attribute 'popula tion'" in <__main__.Person instance at 0x00B4303 8>> ignored [Delete] : clear __name__ [Delete] : clear __doc__ ***************** Exit _PyModule_Clear ************** [print dir() 的输出结果] ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'lds', 'lzh'] On 2/26/06, Robert Chen <search.pythoner at gmail.com> wrote: > > > 这个问题的根源在于在销毁Person的实例lds时,Person类对象自身已经被销毁了,所以访问Person.population当然失败,导致抛出异常。 > > 把代码简化一下,并添加一些打印信息 > > class Person: > population = 0 > > def __init__(self,name): > Person.population += 1 > > def __del__(self): > Person.population -= 1 > > lzh = Person('lzh') > lds = Person('lds') > print dir() > print > print '*************** print lzh ***************' > print lzh > print > print '*************** print lds ***************' > print lds > print > 输出为: > > ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'lds', > 'lzh'] > > *************** print lzh *************** > <__main__.Person instance at 0x00B33760> > > *************** print lds *************** > <__main__.Person instance at 0x00B33C38> > > Exception exceptions.AttributeError: "'NoneType' object has no attribute > 'popula > tion'" in <__main__.Person instance at > 0x00B33C3 > 8>> ignored > Exception exceptions.AttributeError : "'NoneType' object has no attribute > 'popula > tion'" in <__main__.Person instance at > 0x00B3376 > 0>> ignored > > 在Python执行完所有的字节码指令之后,Python会销毁自身的运行时环境,在这个过程中,会进入到import.c的PyImport_Cleanup中, > 在这个函数中,会按照输出的第一行所示的顺序销毁对象,即Person类对象是第一个被销毁的。这一点可以从下面得到印证,在异常 > 的信息中,可以看到,第一个异常出现在对象0x00B33C38上,第二个异常发生在对象0x00B33760上,从输出的结果我们可以看到, > 对象0x00B33C38正是lds,而对象0x00B33760是lzh。 > > > 如果显式调用del,则del将会产生字节码指令,Python对lds,lzh的销毁动作会在执行这些字节指令时发生,显然这早于Python销毁自身运行时 > 环境的动作,所以是安全的。 > > On 2/24/06, ajax chelsea <ajaxchelsea at gmail.com> wrote: > > > (翻了一下旧信件) > > > > 这个问题不知道是不是Python不保证对象的析构顺序造成的呢?如果显式del就没问题 > > > > > > # Filename: objvar.py > > > > class Person: > > '''Represents a person.''' > > population = 0 > > > > def __init__(self,name): > > '''Initializes the person's data.''' > > self.name = name > > print '(Initializing %s)' % self.name > > Person.population += 1 > > > > def __del__(self): > > '''I am dying.''' > > print '%s says bye.' % self.name > > Person.population -= 1 > > > > if Person.population == 0: > > print 'I am the last one.' > > else: > > print 'There are still %d people left.' % Person.population > > > > def sayHi(self): > > '''Greeting by the person. > > > > Really, that's all it does.''' > > print 'Hi, my name is %s.' % self.name > > def howMany(self): > > '''Prints the current population.''' > > if Person.population == 1: > > print 'I am the only person here.' > > else: > > print 'We have %d persons here.' % Person.population > > > > lzh = Person('lzh') > > lzh.sayHi() > > lzh.howMany() > > > > lds = Person('lds') > > lds.sayHi() > > lds.howMany() > > lzh.sayHi() > > lzh.howMany() > > > > > > #此时Person类对象本身尚未被delete > > del lzh > > del lds > > #此时有可能Person类对象本身先于实例对象被delete > > > > > > > > 在05-12-21,l zh <lzhlds at gmail.com> 写道: > > > > > > # Filename: objvar.py > > > > > > class Person: > > > '''Represents a person.''' > > > population = 0 > > > > > > def __init__(self,name): > > > '''Initializes the person's data.''' > > > self.name = name > > > print '(Initializing %s)' % self.name > > > Person.population += 1 > > > > > > def __del__(self): > > > '''I am dying.''' > > > print '%s says bye.' % self.name > > > Person.population -= 1 > > > > > > if Person.population == 0: > > > print 'I am the last one.' > > > else: > > > print 'There are still %d people left.' % > > > Person.population > > > > > > def sayHi(self): > > > '''Greeting by the person. > > > > > > Really, that's all it does.''' > > > print 'Hi, my name is %s.' % self.name > > > def howMany(self): > > > '''Prints the current population.''' > > > if Person.population == 1: > > > print 'I am the only person here.' > > > else: > > > print 'We have %d persons here.' % Person.population > > > > > > lzh = Person('lzh') > > > lzh.sayHi() > > > lzh.howMany() > > > > > > lds = Person('lds') > > > lds.sayHi() > > > lds.howMany() > > > lzh.sayHi() > > > lzh.howMany() > > > > > > > > > _________________________________输出_______________________________________________________ > > > > > > (Initializing lzh) > > > Hi, my name is lzh. > > > I am the only person here. > > > (Initializing lds) > > > Hi, my name is lds. > > > We have 2 persons here. > > > Hi, my name is lzh. > > > We have 2 persons here. > > > lds says bye. > > > Exception exceptions.AttributeError: "'NoneType' object has no > > > attribute 'population'" in <__main__.Person > > > instance at 0x00B14210>> ignored > > > lzh says bye. > > > Exception exceptions.AttributeError : "'NoneType' object has no > > > attribute 'population'" in <__main__.Person > > > instance at 0x00B141E8>> ignored > > > > > > > > > > > > _______________________________________________ > > > python-chinese > > > Post: send python-chinese at lists.python.cn > > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > > Unsubscribe: send unsubscribe to > > > python-chinese-request at lists.python.cn > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > > > > _______________________________________________ > > python-chinese > > Post: send python-chinese at lists.python.cn > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > -- > Robert > Python源码剖析――http://blog.donews.com/lemur/ -- Robert Python源码剖析――http://blog.donews.com/lemur/ -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060226/97b4d21c/attachment-0001.htm
2006年02月27日 星期一 11:20
看来Python仅对析构顺序提供有限的保证: when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__()method may already have been deleted. For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called. 在06-2-26,Robert Chen <search.pythoner at gmail.com> 写道: > > 呵呵,更正一下: > 1、错误的真正根源在_PyModule_Clear中 > 2、Python在销毁运行时环境时,其顺序并非是由dir()显示的那个顺序。因为如果把你的两个变量名由lzh, lds改为a, > b,则就没有异常产生了。 > > 通过修改Python源代码,添加输出信息,可以对比一下这两种情况: > 1. 变量名为a, b > [修改source code的输出结果] > > ***************** Enter _PyModule_Clear************** > [dict] : [a b __builtins__ __file__ Person __name__ __doc__ ] > [Delete] : clear a > [Delete] : clear b > [Delete] : clear __file__ > [Delete] : clear Person > [Delete] : clear __name__ > [Delete] : clear __doc__ > ***************** Exit _PyModule_Clear************** > > [print dir() 的输出结果] > > ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'a', 'b'] > > > > 2. 变量名为lzh, lds > > [修改source code的输出结果] > > ***************** Enter _PyModule_Clear************** > [dict] : [Person __builtins__ __file__ lds lzh __name__ __doc__ ] > [Delete] : clear Person > [Delete] : clear __file__ > [Delete] : clear lds > Exception exceptions.AttributeError : "'NoneType' object has no attribute > 'popula > tion'" in<__main__.Person instance at > 0x00B4307 > 8>> ignored > [Delete] : clear lzh > Exception exceptions.AttributeError : "'NoneType' object has no attribute > 'popula > tion'" in<__main__.Person instance at > 0x00B4303 > 8>> ignored > [Delete] : clear __name__ > [Delete] : clear __doc__ > ***************** Exit _PyModule_Clear ************** > > [print dir() 的输出结果] > > ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'lds', > 'lzh'] > > > > On 2/26/06, Robert Chen <search.pythoner at gmail.com> wrote: > > > > > > 这个问题的根源在于在销毁Person的实例lds时,Person类对象自身已经被销毁了,所以访问Person.population当然失败,导致抛出异常。 > > > > 把代码简化一下,并添加一些打印信息 > > > > class Person: > > population = 0 > > > > def __init__(self,name): > > Person.population += 1 > > > > def __del__(self): > > Person.population -= 1 > > > > lzh = Person('lzh') > > lds = Person('lds') > > print dir() > > print > > print '*************** print lzh ***************' > > print lzh > > print > > print '*************** print lds ***************' > > print lds > > print > > 输出为: > > > > ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'lds', > > 'lzh'] > > > > *************** print lzh *************** > > <__main__.Person instance at 0x00B33760> > > > > *************** print lds *************** > > <__main__.Person instance at 0x00B33C38> > > > > Exception exceptions.AttributeError: "'NoneType' object has no attribute > > 'popula > > tion'" in<__main__.Person instance at > > 0x00B33C3 > > 8>> ignored > > Exception exceptions.AttributeError : "'NoneType' object has no > > attribute 'popula > > tion'" in<__main__.Person instance at > > 0x00B3376 > > 0>> ignored > > > > 在Python执行完所有的字节码指令之后,Python会销毁自身的运行时环境,在这个过程中,会进入到import.c的PyImport_Cleanup中, > > 在这个函数中,会按照输出的第一行所示的顺序销毁对象,即Person类对象是第一个被销毁的。这一点可以从下面得到印证,在异常 > > 的信息中,可以看到,第一个异常出现在对象0x00B33C38上,第二个异常发生在对象0x00B33760上,从输出的结果我们可以看到, > > 对象0x00B33C38正是lds,而对象0x00B33760是lzh。 > > > > > > 如果显式调用del,则del将会产生字节码指令,Python对lds,lzh的销毁动作会在执行这些字节指令时发生,显然这早于Python销毁自身运行时 > > 环境的动作,所以是安全的。 > > > > On 2/24/06, ajax chelsea <ajaxchelsea at gmail.com > wrote: > > > > > (翻了一下旧信件) > > > > > > 这个问题不知道是不是Python不保证对象的析构顺序造成的呢?如果显式del就没问题 > > > > > > > > > # Filename: objvar.py > > > > > > class Person: > > > '''Represents a person.''' > > > population = 0 > > > > > > def __init__(self,name): > > > '''Initializes the person's data.''' > > > self.name = name > > > print '(Initializing %s)' % self.name > > > Person.population += 1 > > > > > > def __del__(self): > > > '''I am dying.''' > > > print '%s says bye.' % self.name > > > Person.population -= 1 > > > > > > if Person.population == 0: > > > print 'I am the last one.' > > > else: > > > print 'There are still %d people left.' % > > > Person.population > > > > > > def sayHi(self): > > > '''Greeting by the person. > > > > > > Really, that's all it does.''' > > > print 'Hi, my name is %s.' % self.name > > > def howMany(self): > > > '''Prints the current population.''' > > > if Person.population == 1: > > > print 'I am the only person here.' > > > else: > > > print 'We have %d persons here.' % Person.population > > > > > > lzh = Person('lzh') > > > lzh.sayHi() > > > lzh.howMany() > > > > > > lds = Person('lds') > > > lds.sayHi() > > > lds.howMany() > > > lzh.sayHi() > > > lzh.howMany() > > > > > > > > > #此时Person类对象本身尚未被delete > > > del lzh > > > del lds > > > #此时有可能Person类对象本身先于实例对象被delete > > > > > > > > > > > > 在05-12-21,l zh <lzhlds at gmail.com> 写道: > > > > > > > > # Filename: objvar.py > > > > > > > > class Person: > > > > '''Represents a person.''' > > > > population = 0 > > > > > > > > def __init__(self,name): > > > > '''Initializes the person's data.''' > > > > self.name = name > > > > print '(Initializing %s)' % self.name > > > > Person.population += 1 > > > > > > > > def __del__(self): > > > > '''I am dying.''' > > > > print '%s says bye.' % self.name > > > > Person.population -= 1 > > > > > > > > if Person.population == 0: > > > > print 'I am the last one.' > > > > else: > > > > print 'There are still %d people left.' % > > > > Person.population > > > > > > > > def sayHi(self): > > > > '''Greeting by the person. > > > > > > > > Really, that's all it does.''' > > > > print 'Hi, my name is %s.' % self.name > > > > def howMany(self): > > > > '''Prints the current population.''' > > > > if Person.population == 1: > > > > print 'I am the only person here.' > > > > else: > > > > print 'We have %d persons here.' % Person.population > > > > > > > > lzh = Person('lzh') > > > > lzh.sayHi() > > > > lzh.howMany() > > > > > > > > lds = Person('lds') > > > > lds.sayHi() > > > > lds.howMany() > > > > lzh.sayHi() > > > > lzh.howMany() > > > > > > > > > > > > _________________________________输出_______________________________________________________ > > > > > > > > (Initializing lzh) > > > > Hi, my name is lzh. > > > > I am the only person here. > > > > (Initializing lds) > > > > Hi, my name is lds. > > > > We have 2 persons here. > > > > Hi, my name is lzh. > > > > We have 2 persons here. > > > > lds says bye. > > > > Exception exceptions.AttributeError: "'NoneType' object has no > > > > attribute 'population'" in<__main__.Person > > > > instance at 0x00B14210>> ignored > > > > lzh says bye. > > > > Exception exceptions.AttributeError : "'NoneType' object has no > > > > attribute 'population'" in<__main__.Person > > > > instance at 0x00B141E8>> ignored > > > > > > > > > > > > > > > > _______________________________________________ > > > > python-chinese > > > > Post: send python-chinese at lists.python.cn > > > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > > > Unsubscribe: send unsubscribe to > > > > python-chinese-request at lists.python.cn > > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > > > > > > > > _______________________________________________ > > > python-chinese > > > Post: send python-chinese at lists.python.cn > > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > > > > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > > > > > > -- > > Robert > > Python源码剖析――http://blog.donews.com/lemur/ > > > > > -- > Robert > Python源码剖析――http://blog.donews.com/lemur/ > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060227/582357cb/attachment-0001.htm
2006年02月27日 星期一 11:48
呵呵,没错,Python销毁一个Module中的所有对象时,采用的销毁次序依赖于PyStringObject对象所采用的散列函数以及PyDictObject对象的结构,顺序是不可保证的,所以应该尽量减小在__del__()中的外部依赖。 On 2/27/06, ajax chelsea <ajaxchelsea at gmail.com> wrote: > > 看来Python仅对析构顺序提供有限的保证: > > when __del__() is invoked in response to a module being deleted (e.g., > when execution of the program is done), other globals referenced by the > __del__() method may already have been deleted. For this reason, __del__()methods should do the absolute minimum needed to maintain external > invariants. Starting with version 1.5, Python guarantees that globals > whose name begins with a single underscore are deleted from their module > before other globals are deleted; if no other references to such globals > exist, this may help in assuring that imported modules are still available > at the time when the __del__() method is called. > > > 在06-2-26,Robert Chen <search.pythoner at gmail.com> 写道: > > > > 呵呵,更正一下: > > 1、错误的真正根源在_PyModule_Clear中 > > 2、Python在销毁运行时环境时,其顺序并非是由dir()显示的那个顺序。因为如果把你的两个变量名由lzh, lds改为a, > > b,则就没有异常产生了。 > > > > 通过修改Python源代码,添加输出信息,可以对比一下这两种情况: > > 1. 变量名为a, b > > [修改source code的输出结果] > > > > ***************** Enter _PyModule_Clear************** > > [dict] : [a b __builtins__ __file__ Person __name__ __doc__ ] > > [Delete] : clear a > > [Delete] : clear b > > [Delete] : clear __file__ > > [Delete] : clear Person > > [Delete] : clear __name__ > > [Delete] : clear __doc__ > > ***************** Exit _PyModule_Clear************** > > > > [print dir() 的输出结果] > > > > ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'a', 'b'] > > > > > > > > 2. 变量名为lzh, lds > > > > [修改source code的输出结果] > > > > ***************** Enter _PyModule_Clear************** > > [dict] : [Person __builtins__ __file__ lds lzh __name__ __doc__ ] > > [Delete] : clear Person > > [Delete] : clear __file__ > > [Delete] : clear lds > > Exception exceptions.AttributeError : "'NoneType' object has no > > attribute 'popula > > tion'" in<__main__.Person instance at > > 0x00B4307 > > 8>> ignored > > [Delete] : clear lzh > > Exception exceptions.AttributeError : "'NoneType' object has no > > attribute 'popula > > tion'" in<__main__.Person instance at > > 0x00B4303 > > 8>> ignored > > [Delete] : clear __name__ > > [Delete] : clear __doc__ > > ***************** Exit _PyModule_Clear ************** > > > > [print dir() 的输出结果] > > > > ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'lds', > > 'lzh'] > > > > > > > > On 2/26/06, Robert Chen <search.pythoner at gmail.com > wrote: > > > > > > > > > 这个问题的根源在于在销毁Person的实例lds时,Person类对象自身已经被销毁了,所以访问Person.population当然失败,导致抛出异常。 > > > > > > 把代码简化一下,并添加一些打印信息 > > > > > > class Person: > > > population = 0 > > > > > > def __init__(self,name): > > > Person.population += 1 > > > > > > def __del__(self): > > > Person.population -= 1 > > > > > > lzh = Person('lzh') > > > lds = Person('lds') > > > print dir() > > > print > > > print '*************** print lzh ***************' > > > print lzh > > > print > > > print '*************** print lds ***************' > > > print lds > > > print > > > 输出为: > > > > > > ['Person', '__builtins__', '__doc__', '__file__', '__name__', 'lds', > > > 'lzh'] > > > > > > *************** print lzh *************** > > > <__main__.Person instance at 0x00B33760> > > > > > > *************** print lds *************** > > > <__main__.Person instance at 0x00B33C38> > > > > > > Exception exceptions.AttributeError: "'NoneType' object has no > > > attribute 'popula > > > tion'" in<__main__.Person instance at > > > 0x00B33C3 > > > 8>> ignored > > > Exception exceptions.AttributeError : "'NoneType' object has no > > > attribute 'popula > > > tion'" in<__main__.Person instance at > > > 0x00B3376 > > > 0>> ignored > > > > > > 在Python执行完所有的字节码指令之后,Python会销毁自身的运行时环境,在这个过程中,会进入到import.c的PyImport_Cleanup中, > > > 在这个函数中,会按照输出的第一行所示的顺序销毁对象,即Person类对象是第一个被销毁的。这一点可以从下面得到印证,在异常 > > > 的信息中,可以看到,第一个异常出现在对象0x00B33C38上,第二个异常发生在对象0x00B33760上,从输出的结果我们可以看到, > > > 对象0x00B33C38正是lds,而对象0x00B33760是lzh。 > > > > > > > > > 如果显式调用del,则del将会产生字节码指令,Python对lds,lzh的销毁动作会在执行这些字节指令时发生,显然这早于Python销毁自身运行时 > > > 环境的动作,所以是安全的。 > > > > > > On 2/24/06, ajax chelsea <ajaxchelsea at gmail.com > wrote: > > > > > > > (翻了一下旧信件) > > > > > > > > 这个问题不知道是不是Python不保证对象的析构顺序造成的呢?如果显式del就没问题 > > > > > > > > > > > > # Filename: objvar.py > > > > > > > > class Person: > > > > '''Represents a person.''' > > > > population = 0 > > > > > > > > def __init__(self,name): > > > > '''Initializes the person's data.''' > > > > self.name = name > > > > print '(Initializing %s)' % self.name > > > > Person.population += 1 > > > > > > > > def __del__(self): > > > > '''I am dying.''' > > > > print '%s says bye.' % self.name > > > > Person.population -= 1 > > > > > > > > if Person.population == 0: > > > > print 'I am the last one.' > > > > else: > > > > print 'There are still %d people left.' % > > > > Person.population > > > > > > > > def sayHi(self): > > > > '''Greeting by the person. > > > > > > > > Really, that's all it does.''' > > > > print 'Hi, my name is %s.' % self.name > > > > def howMany(self): > > > > '''Prints the current population.''' > > > > if Person.population == 1: > > > > print 'I am the only person here.' > > > > else: > > > > print 'We have %d persons here.' % Person.population > > > > > > > > lzh = Person('lzh') > > > > lzh.sayHi() > > > > lzh.howMany() > > > > > > > > lds = Person('lds') > > > > lds.sayHi() > > > > lds.howMany() > > > > lzh.sayHi() > > > > lzh.howMany() > > > > > > > > > > > > #此时Person类对象本身尚未被delete > > > > del lzh > > > > del lds > > > > #此时有可能Person类对象本身先于实例对象被delete > > > > > > > > > > > > > > > > 在05-12-21,l zh <lzhlds at gmail.com> 写道: > > > > > > > > > > # Filename: objvar.py > > > > > > > > > > class Person: > > > > > '''Represents a person.''' > > > > > population = 0 > > > > > > > > > > def __init__(self,name): > > > > > '''Initializes the person's data.''' > > > > > self.name = name > > > > > print '(Initializing %s)' % self.name > > > > > Person.population += 1 > > > > > > > > > > def __del__(self): > > > > > '''I am dying.''' > > > > > print '%s says bye.' % self.name > > > > > Person.population -= 1 > > > > > > > > > > if Person.population == 0: > > > > > print 'I am the last one.' > > > > > else: > > > > > print 'There are still %d people left.' % > > > > > Person.population > > > > > > > > > > def sayHi(self): > > > > > '''Greeting by the person. > > > > > > > > > > Really, that's all it does.''' > > > > > print 'Hi, my name is %s.' % self.name > > > > > def howMany(self): > > > > > '''Prints the current population.''' > > > > > if Person.population == 1: > > > > > print 'I am the only person here.' > > > > > else: > > > > > print 'We have %d persons here.' % Person.population > > > > > > > > > > lzh = Person('lzh') > > > > > lzh.sayHi() > > > > > lzh.howMany() > > > > > > > > > > lds = Person('lds') > > > > > lds.sayHi() > > > > > lds.howMany() > > > > > lzh.sayHi() > > > > > lzh.howMany() > > > > > > > > > > > > > > > _________________________________输出_______________________________________________________ > > > > > > > > > > (Initializing lzh) > > > > > Hi, my name is lzh. > > > > > I am the only person here. > > > > > (Initializing lds) > > > > > Hi, my name is lds. > > > > > We have 2 persons here. > > > > > Hi, my name is lzh. > > > > > We have 2 persons here. > > > > > lds says bye. > > > > > Exception exceptions.AttributeError: "'NoneType' object has no > > > > > attribute 'population'" in<__main__.Person > > > > > instance at 0x00B14210>> ignored > > > > > lzh says bye. > > > > > Exception exceptions.AttributeError : "'NoneType' object has no > > > > > attribute 'population'" in<__main__.Person > > > > > instance at 0x00B141E8>> ignored > > > > > > > > > > > > > > > > > > > > _______________________________________________ > > > > > python-chinese > > > > > Post: send python-chinese at lists.python.cn > > > > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > > > > > > > > > Unsubscribe: send unsubscribe to > > > > > python-chinese-request at lists.python.cn > > > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > > > > > > > > > > > > _______________________________________________ > > > > python-chinese > > > > Post: send python-chinese at lists.python.cn > > > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > > > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > > > > > > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > > > > > > > > > > > -- > > > Robert > > > Python源码剖析――http://blog.donews.com/lemur/ > > > > > > > > > > -- > > Robert > > Python源码剖析――http://blog.donews.com/lemur/ > > > > _______________________________________________ > > python-chinese > > Post: send python-chinese at lists.python.cn > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -- Robert Python源码剖析――http://blog.donews.com/lemur/ -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060227/f7d589d5/attachment-0001.html
Zeuux © 2025
京ICP备05028076号