From: Christian Heimes on
> Inheriting from "int" is not too helpful, because you can't assign
> to the value of the base class. "self=1" won't do what you want.

It's useful if you remember that you can set the default value by
overwriting __new__.

>>> class int1(int):
.... def __new__(cls, value=1):
.... return super(int1, cls).__new__(cls, value)
....
>>> int1()
1
>>> int1(1)
1
>>> int1(2)
2
>>> int1(0)
0

From: Steven D'Aprano on
On Thu, 29 Jul 2010 21:43:05 +0300, Nick Raptis wrote:

> On 07/29/2010 09:12 PM, wheres pythonmonks wrote:
>> How do I build an "int1" type that has a default value of 1?
> You mean something like:
> >>> x = int()
> >>> x
> 0
> >>> def myint(value=1):
> ... return int(value)
> ...
> >>> myint()
> 1
> >>>
> >>>
> That's ugly on so many levels..

Why do you think it's ugly? It's a function that returns an int, and it
provides a default value which is different from the default value of the
int constructor. It's a really simple function, and it has an equally
simple implementation, and it's an obvious way to do it. Not the *one*
obvious way, because subclassing int is equally obvious, but still
obvious.



--
Steven
From: Peter Otten on
wheres pythonmonks wrote:

> How do I build an "int1" type that has a default value of 1?
> [Hopefully no speed penalty.]
> I am thinking about applications with collections.defaultdict.

>>> from collections import defaultdict
>>> d = defaultdict(1 .conjugate)
>>> d["x"] += 2
>>> d["x"]
3

Isn't that beautiful? Almost like home;)

It is also fast:

$ python -m timeit -s"one = lambda: 1" "one()"
1000000 loops, best of 3: 0.213 usec per loop
$ python -m timeit -s"one = 1 .conjugate" "one()"
10000000 loops, best of 3: 0.0972 usec per loop

Micro-optimisation, the best excuse for ugly code...

Peter
From: Peter Otten on
Duncan Booth wrote:

> Peter Otten <__peter__(a)web.de> wrote:
>
>>>>> from collections import defaultdict
>>>>> d = defaultdict(1 .conjugate)
>>>>> d["x"] += 2
>>>>> d["x"]
>> 3
>>
>> Isn't that beautiful? Almost like home;)
>>
>> It is also fast:
>>
>> $ python -m timeit -s"one = lambda: 1" "one()"
>> 1000000 loops, best of 3: 0.213 usec per loop
>> $ python -m timeit -s"one = 1 .conjugate" "one()"
>> 10000000 loops, best of 3: 0.0972 usec per loop
>>
>> Micro-optimisation, the best excuse for ugly code...
>>
>
> Nice one, but if you are going to micro-optimise why not save a few
> keystrokes while you're at it and use '1 .real' instead?

>>> 1 .real
1
>>> 1 .conjugate
<built-in method conjugate of int object at 0x1734298>
>>> 1 .conjugate()

real is a property, not a method. conjugate() was the first one that worked
that was not __special__. I think it has the added benefit that it's likely
to confuse the reader...

Peter
From: Steven D'Aprano on
On Fri, 30 Jul 2010 07:59:52 -0400, wheres pythonmonks wrote:

> Instead of defaultdict for hash of lists, I have seen something like:
>
>
> m={}; m.setdefault('key', []).append(1)
>
> Would this be preferred in some circumstances?

Sure, why not? Whichever you prefer.

setdefault() is a venerable old technique, dating back to Python 2.0, and
not a newcomer like defaultdict.


> Also, is there a way to upcast a defaultdict into a dict?

"Upcast"? Surely it is downcasting. Or side-casting. Or type-casting.
Whatever. *wink*

Whatever it is, the answer is Yes:

>>> from collections import defaultdict as dd
>>> x = dd(int)
>>> x[1] = 'a'
>>> x
defaultdict(<type 'int'>, {1: 'a'})
>>> dict(x)
{1: 'a'}



> I have also heard some people use
> exceptions on dictionaries to catch key existence, so passing in a
> defaultdict (I guess) could be hazardous to health. Is this true?

Yes, it is true that some people use exceptions on dicts to catch key
existence. The most common reason to do so is to catch the non-existence
of a key so you can add it:

try:
mydict[x] = mydict[x] + 1
except KeyError:
mydict[x] = 1


If mydict is a defaultdict with the appropriate factory, then the change
is perfectly safe because mydict[x] will not raise an exception when x is
missing, but merely return 0, so it will continue to work as expected and
all is good.

Of course, if you pass it an defaultdict with an *inappropriate* factory,
you'll get an error. So don't do that :) Seriously, you can't expect to
just randomly replace a variable with some arbitrarily different variable
and expect it to work. You need to know what the code is expecting, and
not break those expectations too badly.

And now you have at least three ways of setting missing values in a dict.
And those wacky Perl people say that Python's motto is "only one way to
do it" :)



--
Steven