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号