473,770 Members | 4,443 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Generator inside a class prevent __del__ ??

Hi,

I run across this problem, and couldn't find any solution (python 2.2.2)
:

Code :
===========
from __future__ import generators
class titi: def __init__(self):
print "init"
def __del__(self):
print "del"
def Gen(self):
yield 1
c = titi() init c = [] del
==============
Here, everything is normal...
But creating a generator :

Code :
===========
class toto: def __init__(self):
print "init"
self.Coroutine = self.Gen()
def __del__(self):
print "del"
def Gen(self):
yield 1
a = toto() init c = []

<--- Nothing there !!!
==============

I can't understand why the destructor is not called when a generator is
created, and what I should do to have a "correct" behavior.
(perhaps I missed something obvious, but I can't find it )
Thank you for any help,

Emmanuel


Jul 18 '05 #1
13 2033

"Emmanuel" <ea*****@free.f r> wrote in message
news:40******** *******@free.fr ...
I run across this problem, and couldn't find any solution (python 2.2.2) .... Here, everything is normal...
But creating a generator :
You both defined generator function and called it to create generator
iterator.

Code :
===========
class toto: def __init__(self):
print "init"
self.Coroutine = self.Gen()
This creates a reference loop. Delete this (and correct typo below) and
'problem' will disappear.
def __del__(self):
print "del"
def Gen(self):
If you do not really use self in the resulting iterator, define this
outside of the class without self as a parameter, and problem will
disappear.
yield 1
a = toto()

did you mean 'c = toto()'?
init c = []

<--- Nothing there !!!
==============

I can't understand why the destructor is not called when a generator is
created, and what I should do to have a "correct" behavior.


Either do not create reference loop or break it with del c.Coroutine.

Terry J. Reedy

Jul 18 '05 #2
In article <40************ ***@free.fr>, Emmanuel <ea*****@free.f r>
wrote:
class toto: def __init__(self):
print "init"
self.Coroutine = self.Gen()
def __del__(self):
print "del"
def Gen(self):
yield 1
a = toto() init c = [] <--- Nothing there !!!


First of all, "a" is still referencing your toto object. I think you
meant "a = []" here. But even if you did "a = []", the destructor
still isn't called. There must still be a reference to the object. My
guess is that the generator (directly or indirectly) is referencing the
object, creating a self referential loop.

Consider the following modification that merely references a function,
and does not create a generator:
class tata: .... def __init__(self):
.... print "init"
.... self.Coroutine = self.Gen
.... def __del__(self):
.... print "del"
.... def Gen(self):
.... pass
.... a=tata() init a=[]

Here's how to break that loop:
b=tata() init b.Coroutine=Non e
b=[] del


-Mark
Jul 18 '05 #3
Mark Day wrote:
still isn't called. There must still be a reference to the object. My
guess is that the generator (directly or indirectly) is referencing the
object, creating a self referential loop.


Python has a garbage collector that will try to find these objects with
cyclic references.

from test import *
a = toto() init a = None
import gc
gc.garbage [] gc.collect() 4 gc.garbage [<test.toto instance at 0x81cb78c>]


I checked out the documentation for that gc.garbage list and it says
that the collector can't free objects in cycles if the cyles have
objects that have __del__ methods. So it puts them in this list.

I wonder what other garbage collectors do in this situation? Anyone
know? Java?

Rob

Jul 18 '05 #4
Rob Nikander <rn************ *@adelphia.net> wrote in
news:kN******** ************@ad elphia.com:
I checked out the documentation for that gc.garbage list and it says
that the collector can't free objects in cycles if the cyles have
objects that have __del__ methods. So it puts them in this list.

I wonder what other garbage collectors do in this situation? Anyone
know? Java?


Most garbage collectors will do peculiar things if you have destructors or
finalizers in the objects. The problem is that if two objects with
finalizers reference each other there is no correct order to release the
objects that will guarantee that the other object still exists, so the
system either has to choose an arbitrary order, or refuse to call the
finalizers.

The .Net garbage collector is typical. Objects may have finalizers, and
these finalizers are called as part of the garbage collection. The system
guarantees that any finalizer is called exactly 0 or more times --- usually
it is called once when the object is garbage collected, but if the object
is never collected it may not be called at all, and if the object
resurrects itself (e.g. during the finalizer it assigns itself to a global
variable) the finalizer could be called more than once.

A separate thread pool is used for finalizers, so your finalizer could be
called while a user thread is executing a method on the object, and two
objects which refer to each other could have their finalizers called in any
order, or even simultaneously on separate threads. Effectively, this makes
finalizers useless in all but the most obscure situations.

When resources need to be released you should try to do it explicitly. In
..Net this is handled by the Dispose() method, and the finalizer can then
either try calling Dispose() if it has not yet been called, or could try
logging an error although even that may be problematic from a finalizer.
Jul 18 '05 #5


Terry Reedy a écrit :
"Emmanuel" <ea*****@free.f r> wrote in message
news:40******** *******@free.fr ...
I run across this problem, and couldn't find any solution (python 2.2.2) ...
Here, everything is normal...
But creating a generator :


You both defined generator function and called it to create generator
iterator.


Yes, I don't have all the generators vocabulary yet...


Code :
===========
>> class toto: def __init__(self):
print "init"
self.Coroutine = self.Gen()


This creates a reference loop. Delete this (and correct typo below) and
'problem' will disappear.

def __del__(self):
print "del"
def Gen(self):
If you do not really use self in the resulting iterator, define this
outside of the class without self as a parameter, and problem will
disappear.


I didn't use self in order to provide a simple example. In my real class, self
is used...

yield 1
>> a = toto()

did you mean 'c = toto()'?


Yes, sorry for that...

init
>> c = []

<--- Nothing there !!!
==============

I can't understand why the destructor is not called when a generator is
created, and what I should do to have a "correct" behavior.


Either do not create reference loop or break it with del c.Coroutine.

Terry J. Reedy


Thank you very much for your answer, but I'm still not sure I understand it.
If I understand your words right, creating self.Coroutine as an iterator on
the generator function will create a reference on self, so if I want to use a
generator in a class ( and I really want to ), I must delete explicitly the
iterator before I destroy the object.

Trouble is, I _would_ like not to care about the lifetime of the object, and I
don't know where it will be destroyed.
Should I encapsulate this object in another one, like this :

import toto

class TotoCapsule:
def __init__( self ):
self.toto = toto.toto()
def __del__(self):
del self.toto.Corou tine
self.toto = None

And use TotoCapsule ?
But it means I have to write a lot of more code to access toto's method.
Is there a pattern I missed to dea l with that ?

Thanks a lot,

Emmanuel

Jul 18 '05 #6

"Emmanuel" <ea*****@free.f r> wrote in message
news:40******** *******@free.fr ...


Terry Reedy a écrit :
>>> class toto:
def __init__(self):
print "init"
self.Coroutine = self.Gen()


This creates a reference loop. Delete this (and correct typo below) and 'problem' will disappear.


To amplify: the usual idiom for an instance-associated generator is to name
the generator function (method) __iter__ (with one param, self) and to
create and get a reference to the generator via iter() or let the for loop
mechanism do so for you.

c = C(*args)
cgen =iter(c)

Then there is no reference loop. And you can pass around the cgen object
just like any other. If you only need the instance after initialization to
get the generator and you only need one generator for the instance, then
combine the two lines into

cgen = iter(C(*args))

and the *only* reference to the instance is the one in the generator, which
will disappear at the end of a for loop or with an explicit 'del cgen'.

There is also the question whether you actually *need* to get rid of the
object while the program is still running instead of just letting the
program finish and clean up.

Terry J. Reedy

Jul 18 '05 #7
On Wed, Apr 21, 2004 at 02:53:33PM +0200, Emmanuel wrote:

Trouble is, I _would_ like not to care about the lifetime of the object, and I
don't know where it will be destroyed.


Then don't use __del__. Python can and will automatically collect cycles
when the objects *don't* define __del__ methods.

Out of curiousity, why are you defining __del__ anyway?

-Andrew.
Jul 18 '05 #8


Andrew Bennetts a écrit :
On Wed, Apr 21, 2004 at 02:53:33PM +0200, Emmanuel wrote:

Trouble is, I _would_ like not to care about the lifetime of the object, and I
don't know where it will be destroyed.


Then don't use __del__. Python can and will automatically collect cycles
when the objects *don't* define __del__ methods.

Out of curiousity, why are you defining __del__ anyway?

-Andrew.


I don't want to use __del__, but I suspected I had an issue with the destruction of
my objects, and used a log in __del__ to monitor the destruction.

But defining __del__ has also a lot of valuable utilisation, or so I think...

Emmanuel
Jul 18 '05 #9
In article <40************ ***@free.fr>, Emmanuel wrote:
Thank you very much for your answer, but I'm still not sure I understand it.
If I understand your words right, creating self.Coroutine as an iterator on
the generator function will create a reference on self, so if I want to use a
generator in a class ( and I really want to ), I must delete explicitly the
iterator before I destroy the object.

Trouble is, I _would_ like not to care about the lifetime of the object, and I
don't know where it will be destroyed.


Try looking up "weakref". (I've never used them myself, so I don't know
the exact syntax.)

Joe
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
2442
by: Andrae Muys | last post by:
Found myself needing serialised access to a shared generator from multiple threads. Came up with the following def serialise(gen): lock = threading.Lock() while 1: lock.acquire() try: next = gen.next() finally:
1
4814
by: Rajorshi | last post by:
Hi, I have two classes, say, Base1 and Base2. Now Derv is a class derived from both like class Derv(Base1,Base2)..... In the destructor of the derived class, if I write something like this def __del__(self): for b in self.__class__.__bases__: b.__del__(self)
4
2344
by: Wai Yip Tung | last post by:
I'm attempting to turn some process than uses callback to return result into a more user friendly generator. I'm hitting some road block so any pointer would be appriciated. Let say there is an existing method producer(x, cb). It calls the supplied cb() every time when there is data available. The definititon of cb should be: def cb(data)
45
3047
by: Joh | last post by:
hello, i'm trying to understand how i could build following consecutive sets from a root one using generator : l = would like to produce : , , , ,
4
6540
by: Baoqiu Cui | last post by:
Today I was playing with a small Python program using Python 2.4 on Cygwin (up-to-date version, on Windows XP), but ran into a strange error on the following small program (named bug.py): ------------------------------- #!/usr/bin/python class Person: population = 0 def __del__(self):
2
27973
by: Kiran | last post by:
Hi, We would like to develop a product in VB.Net. This is the first time I'm involving in such type of practice. Can any one please provide the information about the fallowing??? 1. How to generate Licence Key(s) for the product? Are there any components available to do so? 2. Since the product is distributed thru CDs, what is the process to provide licence keys for the clients? Please help.
11
1750
by: vbgunz | last post by:
I am afraid that this is the first time in which I would probably need something explained to me as if I were a little child. I am having a hard time getting this through my thick skull. What in the world is wrong with this!? ''' ########################################################### ''' def generatorFunction(sequence=): for item in sequence: yield item
10
3191
by: Max Yuzhakov | last post by:
Hello! It is correct behaviour for python to call __del__ on some identity of a class object more than once? In brief I shall describe a situation. Sorry for my english. For debugin purposes I'm put in my module global counters for counting __init__ and __del__ calls.
2
2132
by: Spes | last post by:
Hi, I have this simple code: | #!/usr/bin/python | import codecs | import re | from copy import deepcopy | | class MyClass(object): | def __del__(self):
0
10237
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10071
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10017
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8905
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6690
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5326
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5467
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3589
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2832
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.