Python论坛  - 讨论区

标题:Re: [python-chinese] 类与对象的方法(教程中的代码偶执行出错,请那位有空的大大看看)

2006年02月24日 星期五 20:03

ajax chelsea ajaxchelsea at gmail.com
Fri Feb 24 20:03:01 HKT 2006

(翻了一下旧信件)

这个问题不知道是不是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

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2006年02月26日 星期日 21:01

Robert Chen search.pythoner at gmail.com
Sun Feb 26 21:01:24 HKT 2006

这个问题的根源在于在销毁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

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2006年02月26日 星期日 21:26

Robert Chen search.pythoner at gmail.com
Sun Feb 26 21:26:06 HKT 2006

呵呵,更正一下:
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

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2006年02月27日 星期一 11:20

ajax chelsea ajaxchelsea at gmail.com
Mon Feb 27 11:20:57 HKT 2006

看来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

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2006年02月27日 星期一 11:48

Robert Chen search.pythoner at gmail.com
Mon Feb 27 11:48:55 HKT 2006

呵呵,没错,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

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2025

    京ICP备05028076号