[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