classification
Title: A subclass of set doesn't always have __init__ called.
Type: Stage:
Components: Library (Lib) Versions: Python 3.0
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: dbenbenn, georg.brandl, rhettinger
Priority: normal Keywords: patch

Created on 2007-05-19 14:03 by dbenbenn, last changed 2008-11-16 11:47 by rhettinger. This issue is now closed.

Files
File name Uploaded Description Edit
set.diff rhettinger, 2008-03-22 12:14
set.diff rhettinger, 2008-11-16 11:15 Patch to setobject.c
Messages (8)
msg32076 - (view) Author: David Benbennick (dbenbenn) Date: 2007-05-19 14:03
Consider the following code:

>>> class foo(set):
...     def __init__(self, iter):
...         print "foo.__init__"
...         set.__init__(self, iter)
... 
>>> x = foo([1,2])
foo.__init__
>>> y = foo([2,3])
foo.__init__
>>> x & y
foo([2])

As you can see, the foo.__and__ method creates a new foo object without calling foo.__init__.

The problem is in Objects/setobject.c:make_new_set().
msg32077 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2007-05-19 16:11
Wasn't that fixed some time ago?

@OP: what Python version do you use?
msg32078 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2007-05-19 16:25
Sorry, this is just the way Python works.  Given that the __and__ operation has no way of knowing the signature of your subclass contructor, it will produce a new set from your two foo inputs.  This design prevades the language (for example list and int have similar behaviors).  Recommend closing this as not-a-bug:

>>> class foo(list):
	def __init__(self, iter):
		print 'foo.__init__'
		list.__init__(self, iter)

		
>>> x = foo([1,2])
foo.__init__
>>> y = foo([2,3])
foo.__init__
>>> x + y
[1, 2, 2, 3]
>>> type(_)
<type 'list'>
>>> 
>>> class foo(int): 
        pass

>>> foo(1) + foo(2)
3
>>> type(_)
<type 'int'>
msg32079 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2007-05-19 16:32
There is a difference: in the list and int case, the new object is of the base type.
In the set case, the new object is of type foo.

But the constructor signature argument is a valid one.
msg32080 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2007-05-19 16:40
Hmm, that's a bummer.
It is probably going to have to change.  
Will look it and fix it when I get a chance.
msg64319 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2008-03-22 12:14
Attaching a possible fix (untested).
msg75932 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2008-11-16 11:15
Improved solution attached.
msg75933 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2008-11-16 11:47
Fixed in r67232.

Don't think this should be backported to the 2.x series as it may break
working code relying on the old behavior.
History
Date User Action Args
2012-09-07 16:44:39amaury.forgeotdarclinkissue15879 superseder
2008-11-16 11:47:30rhettingersetstatus: open -> closed
resolution: fixed
messages: + msg75933
versions: + Python 3.0, - Python 2.5
2008-11-16 11:15:26rhettingersetfiles: + set.diff
messages: + msg75932
2008-03-22 12:14:20rhettingersetfiles: + set.diff
keywords: + patch
messages: + msg64319
2007-05-19 14:03:55dbenbenncreate