[Tutor] The trap of the year

Karim karim.liateni at free.fr
Wed Jan 26 02:17:19 CET 2011


After one 2 months of python intensive development. I made this init 
defaults error in my db classes constructors...
Shame on me :-[ Steven !

Your example shows me obvious.

Regards
Karim


On 01/26/2011 12:33 AM, Steven D'Aprano wrote:
> Karim wrote:
>>
>> Hello All,
>>
>> Just to share on rageous bug I encounter where 2 lists which "should" 
>> to be different (same id) because hold by different instances of the 
>> same class are not in fact DIFFERENT, see below:
>
> I think you are confused. If the two lists have the same ID, they 
> should be the same, not different.
>
>
>> >>> class Device():
>> ...     def __init__(self, parameters=[]):
>> ...         self.parameters = parameters
>
> This creates a list ONCE, when the method is created, and then uses 
> that same list over and over again.
>
> Consider this:
>
> >>> import time
> >>> now = time.ctime()
> >>> now
> 'Wed Jan 26 10:05:31 2011'
> >>> def test(t=now):
> ...     print(t)
> ...
> >>> test()
> Wed Jan 26 10:05:31 2011
> >>> time.sleep(60); test()
> Wed Jan 26 10:05:31 2011
>
>
> Are you surprised that time.ctime() only gets called *once*? I hope 
> not -- I would expect that you consider this example obvious and not 
> surprising.
>
> How about this instead?
>
> >>> def test2(t=time.ctime()):
> ...     print(t)
> ...
> >>> test2()
> Wed Jan 26 10:09:10 2011
> >>> time.sleep(60); test2()
> Wed Jan 26 10:09:10 2011
>
>
> I hope that this also will not be surprising. time.ctime() is called 
> once, when the function is created, and the result used as often as 
> needed.
>
> It is no different when the default value is a list like []. The list 
> is created once, and used each time the function is called.
>
>
> > When I discovered that I was puzzled because at the prompt:
>>
>> >>> a = []
>> >>> b = []
>> >>> id(a)
>> 140559202956496
>> >>> id(b)
>> 140559202957000
>
> But this test is completely different. You create TWO lists, not one. 
> A better test would be:
>
> >>> a = []
> >>> b = a
> >>> id(a), id(b)
> (3083146668, 3083146668)
>
>
>> I am not really understanding why my init in the class made it refers 
>> to the same list object.
>
> Because it only creates one list, when the method is defined, not each 
> time the method is called.
>
> Only the *inside* of the method is executed each time the method is 
> called, not the method definition. If you want something to be 
> executed each time the method is called, you have to put it in the 
> body of the method:
>
>
> >>> def test3(t=None):
> ...     if t is None: t = time.ctime()
> ...     print(t)
> ...
> >>> test3()
> Wed Jan 26 10:18:33 2011
> >>> time.sleep(60); test3()
> Wed Jan 26 10:19:37 2011
>
>
>



More information about the Tutor mailing list