473,396 Members | 2,011 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

why is self not passed to id()?


Hello!

Executing following little program gives me an TypeError.

What makes me wonder is that foo does get an argument passed while bar
doesn't. Can anyone explain why??????

Thanks
Ruediger

class foo(list):
__hash__ = lambda x: id(x)

class bar(list):
__hash__ = id

_s_ = set()
_s_.add(foo())
_s_.add(bar())

rue@linux:~python test01.py
Traceback (most recent call last):
File "test01.py", line 9, in <module>
_s_.add(bar())
TypeError: id() takes exactly one argument (0 given)

Sep 4 '08 #1
13 1670
On Sep 4, 3:26*pm, Ruediger <larud...@freenet.dewrote:
Hello!

Executing following little program gives me an TypeError.

What makes me wonder is that foo does get an argument passed while bar
doesn't. Can anyone explain why??????

Thanks
Ruediger

class foo(list):
* * __hash__ = lambda x: id(x)

class bar(list):
* * __hash__ = id

_s_ = set()
_s_.add(foo())
_s_.add(bar())

rue@linux:~python test01.py
Traceback (most recent call last):
* File "test01.py", line 9, in <module>
* * _s_.add(bar())
TypeError: id() takes exactly one argument (0 given)
The answer is fairly technical. For member functions to be bound to
instances, they are required to have a __get__ method (which takes
instance and owner as parameters). 'id' does not.

(Why does 'id' not have a __get__ method?)

By contrast,
>>set.add
<method 'add' of 'set' objects>
>>dir(_)
['__call__', '__class__', '__delattr__', '__doc__', '__get__',
'__getattribute__
', '__hash__', '__init__', '__name__', '__new__', '__objclass__',
'__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__']

'set.add' does.
Sep 4 '08 #2
Ruediger wrote:
Executing following little program gives me an TypeError.

What makes me wonder is that foo does get an argument passed while bar
doesn't. Can anyone explain why??????
>>id
<built-in function id>
>>lambda x: id(x)
<function <lambdaat 0x00C07C30>

any special reason why you're not using Python to write Python programs,
btw?

</F>

Sep 4 '08 #3
castironpi wrote:
>
The answer is fairly technical. For member functions to be bound to
instances, they are required to have a __get__ method (which takes
instance and owner as parameters). 'id' does not.

(Why does 'id' not have a __get__ method?)

By contrast,
>>>set.add
<method 'add' of 'set' objects>
>>>dir(_)
['__call__', '__class__', '__delattr__', '__doc__', '__get__',
'__getattribute__
', '__hash__', '__init__', '__name__', '__new__', '__objclass__',
'__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__']

'set.add' does.
Thank you for the quick response.

However it gives me less hope that the little performance hack I had in mind
will ever work.
Sep 4 '08 #4
Le Thursday 04 September 2008 22:26:53 Ruediger, vous avez écrit*:
Hello!
Hello,
Executing following little program gives me an TypeError.

What makes me wonder is that foo does get an argument passed while bar
doesn't. Can anyone explain why??????
Because id is a builtin written in the core language and doesn't subscribe to
the descritpor protocol python functions has.
>
class foo(list):
__hash__ = lambda x: id(x)
Wow ! You are really going on trouble with this, believe me there is a real
good reason for list not to be hashable. A dictionnary or set containing some
of your foo is virtually inconsistent, read carefully the manual about
prerequesites for dict keys, they *need* to be immutable.

class bar(list):
__hash__ = id

_s_ = set()
_s_.add(foo())
_s_.add(bar())

rue@linux:~python test01.py
Traceback (most recent call last):
File "test01.py", line 9, in <module>
_s_.add(bar())
TypeError: id() takes exactly one argument (0 given)

--
http://mail.python.org/mailman/listinfo/python-list


--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 4 26 88 00 97
Mobile: +33 6 32 77 00 21
Sep 4 '08 #5
Fredrik Lundh wrote:
>
>>id
<built-in function id>
>>lambda x: id(x)
<function <lambdaat 0x00C07C30>

any special reason why you're not using Python to write Python programs,
btw?

</F>
I am aware that id is a built in function why shouldn't i use it?

Replaceing lambda with id was intended as an performance hack. Profiling
proofed that lambda itself takes more than twice as much cpu time than id
alone. (profile shortened)

3610503 function calls in 22.451 CPU seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)

960096 4.593 0.000 6.702 0.000 test14.py:33(<lambda>)
1 0.003 0.003 22.451 22.451 {execfile}
960096 2.109 0.000 2.109 0.000 {id}

However using lambda seemed useless to me since id already took an argument
and wrapping it in an python function simply has no real purpose.

Sep 4 '08 #6
Maric Michaud wrote:
Le Thursday 04 September 2008 22:26:53 Ruediger, vous avez écrit :
>class foo(list):
__hash__ = lambda x: id(x)

Wow ! You are really going on trouble with this, believe me there is a real
good reason for list not to be hashable. A dictionnary or set containing some
of your foo is virtually inconsistent, read carefully the manual about
prerequesites for dict keys, they *need* to be immutable.
Well, that's not entirely true. They need to be not mutated while they are in
the dictionary, certainly. At least not in ways that affect equality testing. In
this case, one would also have to override list.__eq__ to also compare by
identity, too. Then you could mutate the lists to your heart's content and the
dictionary wouldn't care.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Sep 4 '08 #7
Robert Kern wrote:
Well, that's not entirely true. They need to be not mutated while they
are in the dictionary, certainly. At least not in ways that affect
equality testing. In this case, one would also have to override
list.__eq__ to also compare by identity, too. Then you could mutate the
lists to your heart's content and the dictionary wouldn't care.
at which point you'd start wondering if it wouldn't be more efficient to
wrap the list in a light-weight class, instead of using subclassing.

</F>

Sep 4 '08 #8


Maric Michaud wrote:
Le Thursday 04 September 2008 22:26:53 Ruediger, vous avez écrit :
>class foo(list):
__hash__ = lambda x: id(x)

Wow ! You are really going on trouble with this, believe me there is a real
good reason for list not to be hashable. A dictionnary or set containing some
of your foo is virtually inconsistent, read carefully the manual about
prerequesites for dict keys, they *need* to be immutable.
No, the id comparison needs to be immutable -- which it is by default
for object()s, being based on id. Mutable instances of classes derived
from object work fine as keys as long as they keep default __eq__ and
__hash__. List over-rides the default, so foo needs to reverse that
override:
def __eq__(self, other):
return id(self) == id(other)

This means, of course, that foo loses value-based equality comparison.

Sep 4 '08 #9
Fredrik Lundh wrote:
Robert Kern wrote:
>Well, that's not entirely true. They need to be not mutated while they
are in the dictionary, certainly. At least not in ways that affect
equality testing. In this case, one would also have to override
list.__eq__ to also compare by identity, too. Then you could mutate
the lists to your heart's content and the dictionary wouldn't care.

at which point you'd start wondering if it wouldn't be more efficient to
wrap the list in a light-weight class, instead of using subclassing.
Fair point.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Sep 4 '08 #10
Le Thursday 04 September 2008 23:35:18 Terry Reedy, vous avez écrit*:
Maric Michaud wrote:
Le Thursday 04 September 2008 22:26:53 Ruediger, vous avez écrit :
class foo(list):
* * __hash__ = lambda x: id(x)
Wow ! You are really going on trouble with this, believe me there is a
real good reason for list not to be hashable. A dictionnary or set
containing some of your foo is virtually inconsistent, read carefully the
manual about prerequesites for dict keys, they *need* to be immutable.

No, the id comparison needs to be immutable -- which it is by default
for object()s, being based on id. *Mutable instances of classes derived
from object work fine as keys as long as they keep default __eq__ and
__hash__. *List over-rides the default, so foo needs to reverse that
override:
* *def __eq__(self, other):
* * *return id(self) == id(other)

This means, of course, that foo loses value-based equality comparison.
Yes, so what's the point of using lists as keys. "class a : pass" already do
this.

--
_____________

Maric Michaud
Sep 4 '08 #11


Ruediger wrote:
I am aware that id is a built in function why shouldn't i use it?
I consider this a sensible thing to have tried, but I an not too
surprised it does not work because I am aware that built-in functions do
not have all the features of Python function.

I have asked about this case on Py-dev.
Subject: Can/should built-in functions get __get__?
Replaceing lambda with id was intended as an performance hack. Profiling
proofed that lambda itself takes more than twice as much cpu time than id
alone. (profile shortened)

3610503 function calls in 22.451 CPU seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)

960096 4.593 0.000 6.702 0.000 test14.py:33(<lambda>)
1 0.003 0.003 22.451 22.451 {execfile}
960096 2.109 0.000 2.109 0.000 {id}

However using lambda seemed useless to me since id already took an argument
and wrapping it in an python function simply has no real purpose.
Ironically, such simple wrappings are usually considered bad form.

There *is* a third alternative, which works in this case, and which
should be closer in speed to id. I will leave you to do a speed test.
>>class bang(list):
__hash__ = object.__hash__
>>s=set()
s.add(bang())
s
{[]}

__eq__ = object.__eq__ should also work instead of the Python
implementation I gave in my response to another response.

Terry Jan Reedy

Sep 5 '08 #12

I found following solution to the problem.

Instead of assigning id directly to __hash__ it has to be wrapped with an
instancemethod object. It is somehow strange that this doesn't happen
automatically and it is also strange that instancemethod isn't exposed in
the type module. However it can easily be done and is speeding things up
by almost an factor of 2.

Thank's again for all the help.

Rüdiger

************************************************** ****************

class foo(list):
__hash__ = lambda x: id(x)

instancemethod = type(foo.__hash__)

class bar(list):
pass
bar.__hash__ = instancemethod(id, None, bar)

def test0( obj ):
_s_ = set()
_s_add = _s_.add
_s_pop = _s_.pop
for _i_ in xrange(1000000):
_s_add(obj())
_s_pop()

def test1():
return test0(foo)
def test2():
return test0(bar)

if __name__ == '__main__':
test1()
test2()
pass

************************************************** ****************
python -m cProfile test01.py

6000010 function calls in 30.547 CPU seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 30.547 30.547 <string>:1(<module>)
1 0.000 0.000 30.547 30.547 test01.py:1(<module>)
1 0.000 0.000 0.000 0.000 test01.py:1(foo)
2 10.784 5.392 30.547 15.273 test01.py:10(test0)
1 0.000 0.000 19.543 19.543 test01.py:18(test1)
1000000 4.554 0.000 6.700 0.000 test01.py:2(<lambda>)
1 0.000 0.000 11.003 11.003 test01.py:20(test2)
1 0.000 0.000 0.000 0.000 test01.py:6(bar)
1 0.001 0.001 30.547 30.547 {execfile}
1000000 2.146 0.000 2.146 0.000 {id}
2000000 8.626 0.000 15.327 0.000 {method 'add' of 'set'objects}
2000000 4.436 0.000 4.436 0.000 {method 'pop' of 'set'objects}

Sep 6 '08 #13


Ruediger wrote:
I found following solution to the problem.

Instead of assigning id directly to __hash__ it has to be wrapped with an
instancemethod object. It is somehow strange that this doesn't happen
automatically and it is also strange that instancemethod isn't exposed in
the type module.
There are several internal implementation types not exposed in types
because they are subject to change from version to version In 3.0, your
code does not work. Instancemethod may to added to 3.0 or 3.1 as a
built-in function.
************************************************** ****************

class foo(list):
__hash__ = lambda x: id(x)
type
instancemethod = type(foo.__hash__)
In 2.x, this gives you 'instancemethod'. In 3.0, you get 'function' as
unbound methods are no longer wrapped when the underlying function is a
'function' (resulting from def or lambda abbreviation).
class bar(list):
pass
bar.__hash__ = instancemethod(id, None, bar)
Calling a 'function' with those parameters will not work.
Did you miss the following from my previous response?

"There *is* a third alternative, which works in this case, and which
should be closer in speed to id. I will leave you to do a speed test.
>>class bang(list):
__hash__ = object.__hash__
>>s=set()
s.add(bang())
s
{[]}

__eq__ = object.__eq__ should also work instead of the Python
implementation I gave in my response to another response."

I would expect the already-wrapped id should work in 2.x also.

Terry Jan Reedy

Sep 6 '08 #14

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

Similar topics

3
by: James Stroud | last post by:
Hello All, I did this: py> class bob(object): .... def __init__(self,**kwargs): .... for fname,func in kwargs.items(): .... setattr(self, fname, lambda *args : func(*args)) .......
18
by: Ralf W. Grosse-Kunstleve | last post by:
My initial proposal (http://cci.lbl.gov/~rwgk/python/adopt_init_args_2005_07_02.html) didn't exactly get a warm welcome... And Now for Something Completely Different: class autoinit(object):...
4
by: bala | last post by:
hi gurus have a employee table which consist of the normal employee related fields which the fields empid and supervisor mainly related to this question. have to create a single (the question...
20
by: Wayne Sutton | last post by:
OK, I'm a newbie... I'm trying to learn Python & have had fun with it so far. But I'm having trouble following the many code examples with the object "self." Can someone explain this usage in...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...
0
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...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
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,...

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.