Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #49801 > unrolled thread

Default scope of variables

Started bySteven D'Aprano <steve+comp.lang.python@pearwood.info>
First post2013-07-04 03:27 +0000
Last post2013-07-08 17:58 +0100
Articles 20 on this page of 60 — 13 participants

Back to article view | Back to comp.lang.python


Contents

  Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-04 03:27 +0000
    Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-04 14:07 +1000
      Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-04 05:32 +0000
        Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-04 15:47 +1000
          Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-04 16:38 +0000
            Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-05 02:58 +1000
            Re: Default scope of variables Wayne Werner <wayne@waynewerner.com> - 2013-07-07 08:13 -0500
            Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-07 23:43 +1000
              Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-07 16:03 +0000
                Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-08 10:46 +1000
              Re: Default scope of variables alex23 <wuwei23@gmail.com> - 2013-07-09 14:52 +1000
                Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-09 15:07 +1000
                  Re: Default scope of variables alex23 <wuwei23@gmail.com> - 2013-07-09 16:08 +1000
                    Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-09 16:13 +1000
                    Re: Default scope of variables "Frank Millman" <frank@chagford.com> - 2013-07-09 09:35 +0200
                    Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-09 17:45 +1000
                    Re: Default scope of variables Ian Kelly <ian.g.kelly@gmail.com> - 2013-07-09 01:56 -0600
                    Re: Default scope of variables "Frank Millman" <frank@chagford.com> - 2013-07-09 10:22 +0200
                    Re: Default scope of variables "Frank Millman" <frank@chagford.com> - 2013-07-09 10:38 +0200
                    Re: Default scope of variables Ethan Furman <ethan@stoneleaf.us> - 2013-07-09 09:07 -0700
                    Re: Default scope of variables Ian Kelly <ian.g.kelly@gmail.com> - 2013-07-09 10:44 -0600
                    Re: Default scope of variables Ethan Furman <ethan@stoneleaf.us> - 2013-07-09 10:23 -0700
                    Re: Default scope of variables Ian Kelly <ian.g.kelly@gmail.com> - 2013-07-09 12:41 -0600
                    Re: Default scope of variables Ethan Furman <ethan@stoneleaf.us> - 2013-07-09 12:19 -0700
                    Re: Default scope of variables "Frank Millman" <frank@chagford.com> - 2013-07-10 07:54 +0200
                    Re: Default scope of variables Ian Kelly <ian.g.kelly@gmail.com> - 2013-07-10 09:42 -0600
                    Re: Default scope of variables Ethan Furman <ethan@stoneleaf.us> - 2013-07-10 08:29 -0700
                    Re: Default scope of variables "Frank Millman" <frank@chagford.com> - 2013-07-11 07:52 +0200
            Re: Default scope of variables Ethan Furman <ethan@stoneleaf.us> - 2013-07-07 09:52 -0700
            Re: Default scope of variables Ethan Furman <ethan@stoneleaf.us> - 2013-07-07 11:59 -0700
            Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-08 10:48 +1000
              Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-08 02:23 +0000
                Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-08 13:11 +1000
                  Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-08 05:00 +0000
                    Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-08 15:14 +1000
        Re: Default scope of variables Peter Otten <__peter__@web.de> - 2013-07-04 08:48 +0200
        Re: Default scope of variables Ian Kelly <ian.g.kelly@gmail.com> - 2013-07-04 01:12 -0600
        Re: Default scope of variables Dave Angel <davea@davea.name> - 2013-07-04 03:06 -0400
          Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-04 15:52 +0000
          Re: Default scope of variables Rotwang <sg552@hotmail.co.uk> - 2013-07-04 17:54 +0100
            Re: Default scope of variables Peter Otten <__peter__@web.de> - 2013-07-04 20:36 +0200
            Re: Default scope of variables Joshua Landau <joshua.landau.ws@gmail.com> - 2013-07-05 01:04 +0100
            Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-05 01:24 +0000
              Re: Default scope of variables Dave Angel <davea@davea.name> - 2013-07-04 22:03 -0400
              Re: Default scope of variables Joshua Landau <joshua.landau.ws@gmail.com> - 2013-07-05 03:29 +0100
              Re: Default scope of variables Joshua Landau <joshua.landau.ws@gmail.com> - 2013-07-05 03:27 +0100
              Re: Default scope of variables Rotwang <sg552@hotmail.co.uk> - 2013-07-05 07:28 +0100
          Re: Default scope of variables Neil Cerutti <neilc@norwich.edu> - 2013-07-05 13:24 +0000
            Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-05 23:43 +1000
              Re: Default scope of variables Neil Cerutti <neilc@norwich.edu> - 2013-07-05 15:36 +0000
            Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-07 16:08 +0000
              Re: Default scope of variables Neil Cerutti <neilc@norwich.edu> - 2013-07-08 11:54 +0000
                Re: Default scope of variables Joshua Landau <joshua.landau.ws@gmail.com> - 2013-07-08 14:14 +0100
        Re: Default scope of variables Lele Gaifax <lele@metapensiero.it> - 2013-07-04 14:43 +0200
        Re: Default scope of variables Wayne Werner <wayne@waynewerner.com> - 2013-07-04 10:45 -0500
    Re: Default scope of variables Joshua Landau <joshua.landau.ws@gmail.com> - 2013-07-04 05:30 +0100
      Re: Default scope of variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-04 05:45 +0000
    Re: Default scope of variables Chris Angelico <rosuav@gmail.com> - 2013-07-04 14:36 +1000
    Re: Default scope of variables Joshua Landau <joshua.landau.ws@gmail.com> - 2013-07-04 06:09 +0100
    Re: Default scope of variables Joshua Landau <joshua.landau.ws@gmail.com> - 2013-07-08 17:58 +0100

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#50262

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-07-09 10:44 -0600
Message-ID<mailman.4462.1373388305.3114.python-list@python.org>
In reply to#50209
On Tue, Jul 9, 2013 at 10:07 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
> You could also do it like this:
>
>     def updating(self):
>         self.transaction_active = True
>         return self

Yes, that would be simpler.  I was all set to point out why this
doesn't work, and then I noticed that the location of the
"transaction_active" attribute is not consistent in the original code.
 The DbSession class places it on self, and then the example usage
places it on the connection object (which I had based my version on).
Since that seems to be a source of confusion, it demonstrates another
reason why factoring this out is a good thing.

[toc] | [prev] | [next] | [standalone]


#50267

FromEthan Furman <ethan@stoneleaf.us>
Date2013-07-09 10:23 -0700
Message-ID<mailman.4466.1373392017.3114.python-list@python.org>
In reply to#50209
On 07/09/2013 09:44 AM, Ian Kelly wrote:
> On Tue, Jul 9, 2013 at 10:07 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
>> You could also do it like this:
>>
>>      def updating(self):
>>          self.transaction_active = True
>>          return self
>
> Yes, that would be simpler.  I was all set to point out why this
> doesn't work, and then I noticed that the location of the
> "transaction_active" attribute is not consistent in the original code.
>   The DbSession class places it on self, and then the example usage
> places it on the connection object

It looks like DbSession has a conn object, and in the example he has DbSession() named as conn -- ironic, considering 
this is a variable scoping thread.  ;)

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#50269

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-07-09 12:41 -0600
Message-ID<mailman.4467.1373395321.3114.python-list@python.org>
In reply to#50209
On Tue, Jul 9, 2013 at 11:23 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
> On 07/09/2013 09:44 AM, Ian Kelly wrote:
>>
>> On Tue, Jul 9, 2013 at 10:07 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
>>>
>>> You could also do it like this:
>>>
>>>      def updating(self):
>>>          self.transaction_active = True
>>>          return self
>>
>>
>> Yes, that would be simpler.  I was all set to point out why this
>> doesn't work, and then I noticed that the location of the
>> "transaction_active" attribute is not consistent in the original code.
>>   The DbSession class places it on self, and then the example usage
>> places it on the connection object
>
>
> It looks like DbSession has a conn object, and in the example he has
> DbSession() named as conn -- ironic, considering this is a variable scoping
> thread.  ;)

The object returned by __enter__ is the conn object, not the
DbSession, so naming it "conn" is correct.

[toc] | [prev] | [next] | [standalone]


#50271

FromEthan Furman <ethan@stoneleaf.us>
Date2013-07-09 12:19 -0700
Message-ID<mailman.4469.1373399640.3114.python-list@python.org>
In reply to#50209
On 07/09/2013 11:41 AM, Ian Kelly wrote:
> On Tue, Jul 9, 2013 at 11:23 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
>> On 07/09/2013 09:44 AM, Ian Kelly wrote:
>>>
>>> On Tue, Jul 9, 2013 at 10:07 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
>>>>
>>>> You could also do it like this:
>>>>
>>>>       def updating(self):
>>>>           self.transaction_active = True
>>>>           return self
>>>
>>>
>>> Yes, that would be simpler.  I was all set to point out why this
>>> doesn't work, and then I noticed that the location of the
>>> "transaction_active" attribute is not consistent in the original code.
>>>    The DbSession class places it on self, and then the example usage
>>> places it on the connection object
>>
>>
>> It looks like DbSession has a conn object, and in the example he has
>> DbSession() named as conn -- ironic, considering this is a variable scoping
>> thread.  ;)
>
> The object returned by __enter__ is the conn object, not the
> DbSession, so naming it "conn" is correct.


Huh.  I didn't realize a different object could be returned by __enter__ without affecting which object's __exit__ gets 
called.  Thanks for the lesson!  :)

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#50299

From"Frank Millman" <frank@chagford.com>
Date2013-07-10 07:54 +0200
Message-ID<mailman.4486.1373435673.3114.python-list@python.org>
In reply to#50209
"Ian Kelly" <ian.g.kelly@gmail.com> wrote in message 
news:CALwzidnf3Obe0eNf3xTHLj5a40K8HxVThVEipECQ8+34ZxyLxw@mail.gmail.com...
> On Tue, Jul 9, 2013 at 10:07 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
>> You could also do it like this:
>>
>>     def updating(self):
>>         self.transaction_active = True
>>         return self
>
> Yes, that would be simpler.  I was all set to point out why this
> doesn't work, and then I noticed that the location of the
> "transaction_active" attribute is not consistent in the original code.
> The DbSession class places it on self, and then the example usage
> places it on the connection object (which I had based my version on).
> Since that seems to be a source of confusion, it demonstrates another
> reason why factoring this out is a good thing.

You had me worried there for a moment, as that is obviously an error.

Then I checked my actual code, and I find that I mis-transcribed it. It 
actually looks like this -

    with db_session as conn:
        db_session.transaction_active = True
        conn.cur.execute(...)

I am still not quite sure what your objection is to this. It feels 
straightforward to me.

Here is one possible answer. Whenever I want to commit a transaction I have 
to add the extra line. There is a danger that I could mis-spell 
'transaction_active', in which case it would not raise an error, but would 
not commit the transaction, which could be a hard-to-trace bug. Using your 
approach, if I mis-spelled 'db_session.connect()', it would immediately 
raise an error.

Is that your concern, or are there other issues?

Frank


[toc] | [prev] | [next] | [standalone]


#50364

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-07-10 09:42 -0600
Message-ID<mailman.4526.1373470972.3114.python-list@python.org>
In reply to#50209
On Tue, Jul 9, 2013 at 11:54 PM, Frank Millman <frank@chagford.com> wrote:
> You had me worried there for a moment, as that is obviously an error.
>
> Then I checked my actual code, and I find that I mis-transcribed it. It
> actually looks like this -
>
>     with db_session as conn:
>         db_session.transaction_active = True
>         conn.cur.execute(...)
>
> I am still not quite sure what your objection is to this. It feels
> straightforward to me.
>
> Here is one possible answer. Whenever I want to commit a transaction I have
> to add the extra line. There is a danger that I could mis-spell
> 'transaction_active', in which case it would not raise an error, but would
> not commit the transaction, which could be a hard-to-trace bug. Using your
> approach, if I mis-spelled 'db_session.connect()', it would immediately
> raise an error.
>
> Is that your concern, or are there other issues?

Yes, that is one concern.  Another is that since you mistakenly typed
"conn" instead of "db_session" once, you might make the same mistake
again in actual code, with the same effect (unless the conn object
doesn't allow arbitrary attributes, which is a possibility).  Another
is that the code adheres better to the DRY principle if you don't need
to copy that line all over the place.

[toc] | [prev] | [next] | [standalone]


#50368

FromEthan Furman <ethan@stoneleaf.us>
Date2013-07-10 08:29 -0700
Message-ID<mailman.4529.1373471632.3114.python-list@python.org>
In reply to#50209
On 07/09/2013 10:54 PM, Frank Millman wrote:
>
> "Ian Kelly" <ian.g.kelly@gmail.com> wrote in message
> news:CALwzidnf3Obe0eNf3xTHLj5a40K8HxVThVEipECQ8+34ZxyLxw@mail.gmail.com...
>> On Tue, Jul 9, 2013 at 10:07 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
>>> You could also do it like this:
>>>
>>>      def updating(self):
>>>          self.transaction_active = True
>>>          return self
>>
>> Yes, that would be simpler.  I was all set to point out why this
>> doesn't work, and then I noticed that the location of the
>> "transaction_active" attribute is not consistent in the original code.
>> The DbSession class places it on self, and then the example usage
>> places it on the connection object (which I had based my version on).
>> Since that seems to be a source of confusion, it demonstrates another
>> reason why factoring this out is a good thing.
>
> You had me worried there for a moment, as that is obviously an error.
>
> Then I checked my actual code, and I find that I mis-transcribed it. It
> actually looks like this -
>
>      with db_session as conn:
>          db_session.transaction_active = True
>          conn.cur.execute(...)
>
> I am still not quite sure what your objection is to this. It feels
> straightforward to me.
>
> Here is one possible answer. Whenever I want to commit a transaction I have
> to add the extra line. There is a danger that I could mis-spell
> 'transaction_active', in which case it would not raise an error, but would
> not commit the transaction, which could be a hard-to-trace bug. Using your
> approach, if I mis-spelled 'db_session.connect()', it would immediately
> raise an error.
>
> Is that your concern, or are there other issues?

That concern is big enough.  I've been bitten by that type of thing enough in my own code to want to avoid it where 
possible.  Plus the `with db_session.updating() as conn:` saves keystrokes.  ;)

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#50416

From"Frank Millman" <frank@chagford.com>
Date2013-07-11 07:52 +0200
Message-ID<mailman.4567.1373522000.3114.python-list@python.org>
In reply to#50209
"Ian Kelly" <ian.g.kelly@gmail.com> wrote in message 
news:CALwzidk2+b5bYM5B+XVtoZ8LHeyVHcos4v58F8Z2o1Jb6sAzog@mail.gmail.com...
> On Tue, Jul 9, 2013 at 11:54 PM, Frank Millman <frank@chagford.com> wrote:
>> You had me worried there for a moment, as that is obviously an error.
>>
>> Then I checked my actual code, and I find that I mis-transcribed it. It
>> actually looks like this -
>>
>>     with db_session as conn:
>>         db_session.transaction_active = True
>>         conn.cur.execute(...)
>>
>> I am still not quite sure what your objection is to this. It feels
>> straightforward to me.
>>
>> Here is one possible answer. Whenever I want to commit a transaction I 
>> have
>> to add the extra line. There is a danger that I could mis-spell
>> 'transaction_active', in which case it would not raise an error, but 
>> would
>> not commit the transaction, which could be a hard-to-trace bug. Using 
>> your
>> approach, if I mis-spelled 'db_session.connect()', it would immediately
>> raise an error.
>>
>> Is that your concern, or are there other issues?
>
> Yes, that is one concern.  Another is that since you mistakenly typed
> "conn" instead of "db_session" once, you might make the same mistake
> again in actual code, with the same effect (unless the conn object
> doesn't allow arbitrary attributes, which is a possibility).  Another
> is that the code adheres better to the DRY principle if you don't need
> to copy that line all over the place.

Thanks to you and Ethan - that does make sense.

I have reviewed my code base to see how many occurrences there are, and 
there are just three.

All database objects inherit from a DbOject class. The class has a save() 
method and a delete() method. Each of these requires a commit, so I use my 
technique there. All database updates are activated by calling save() or 
delete().

I have an init.py script to 'bootstrap' a brand new installation, which 
requires populating an empty database with some basic structures up front. 
DbObject cannot be used here as the required plumbing is not in place, so I 
use my technique here as well.

However, this does not invalidate your general point, so I will keep it in 
mind.

Thanks

Frank


[toc] | [prev] | [next] | [standalone]


#50107

FromEthan Furman <ethan@stoneleaf.us>
Date2013-07-07 09:52 -0700
Message-ID<mailman.4358.1373217388.3114.python-list@python.org>
In reply to#49885
On 07/07/2013 06:43 AM, Chris Angelico wrote:
> On Sun, Jul 7, 2013 at 11:13 PM, Wayne Werner <wayne@waynewerner.com> wrote:
>> Which you would then use like:
>>
>>
>> conn = create_conn()
>> with new_transaction(conn) as tran:
>>       rows_affected = do_query_stuff(tran)
>>       if rows_affected == 42:
>>            tran.commit()
>
> Yep. There's a problem, though, when you bring in subtransactions. The
> logic wants to be like this:

Is there some reason you can't simply do this?

  with new_transaction(conn) as tran1:
       tran1.query("blah")
       with tran1.subtransaction() as tran2:
           tran2.query("blah")
           with tran2.subtransaction() as tran3:
               tran3.query("blah")
               # roll this subtransaction back
           tran2.query("blah")
           tran2.commit()
       tran1.query("blah")
       tran1.commit()

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#50108

FromEthan Furman <ethan@stoneleaf.us>
Date2013-07-07 11:59 -0700
Message-ID<mailman.4359.1373224898.3114.python-list@python.org>
In reply to#49885
On 07/07/2013 06:43 AM, Chris Angelico wrote:
>
> The 'with' statement doesn't allow this. I would need to use some kind
> of magic to rebind the old transaction to the name, or else use a list
> that gets magically populated:
>
> with new_transaction(conn) as tran:
>      tran[-1].query("blah")
>      with subtransaction(tran):
>          tran[-1].query("blah")
>          with subtransaction(tran):
>              tran[-1].query("blah")
>              # roll this subtransaction back
>          tran[-1].query("blah")
>          tran[-1].commit()
>      tran[-1].query("blah")
>      tran[-1].commit()

The other option is to build the magic into the new_transaction class, then your code will look like:

  with new_transaction(conn) as tran:
       tran.query("blah")
       with tran.subtransaction():
           tran.query("blah")
           with tran.subtransaction():
               tran.query("blah")
               # roll this subtransaction back
           tran.query("blah")
           tran.commit()
       tran.query("blah")
       tran.commit()

This would definitely make more sense in a loop.  ;)

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#50112

FromChris Angelico <rosuav@gmail.com>
Date2013-07-08 10:48 +1000
Message-ID<mailman.4361.1373244492.3114.python-list@python.org>
In reply to#49885
On Mon, Jul 8, 2013 at 2:52 AM, Ethan Furman <ethan@stoneleaf.us> wrote:
> On 07/07/2013 06:43 AM, Chris Angelico wrote:
>>
>> On Sun, Jul 7, 2013 at 11:13 PM, Wayne Werner <wayne@waynewerner.com>
>> wrote:
>>>
>>> Which you would then use like:
>>>
>>>
>>> conn = create_conn()
>>> with new_transaction(conn) as tran:
>>>       rows_affected = do_query_stuff(tran)
>>>       if rows_affected == 42:
>>>            tran.commit()
>>
>>
>> Yep. There's a problem, though, when you bring in subtransactions. The
>> logic wants to be like this:
>
>
> Is there some reason you can't simply do this?
>
>  with new_transaction(conn) as tran1:
>       tran1.query("blah")
>       with tran1.subtransaction() as tran2:
>           tran2.query("blah")
>           with tran2.subtransaction() as tran3:
>               tran3.query("blah")
>
>               # roll this subtransaction back
>           tran2.query("blah")
>           tran2.commit()
>       tran1.query("blah")
>       tran1.commit()

That means that I, as programmer, have to keep track of the nesting
level of subtransactions. Extremely ugly. A line of code can't be
moved around without first checking which transaction object to work
with.

ChrisA

[toc] | [prev] | [next] | [standalone]


#50114

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-07-08 02:23 +0000
Message-ID<51da2294$0$6512$c3e8da3$5496439d@news.astraweb.com>
In reply to#50112
On Mon, 08 Jul 2013 10:48:03 +1000, Chris Angelico wrote:
[...]
> That means that I, as programmer, have to keep track of the nesting
> level of subtransactions. Extremely ugly. A line of code can't be moved
> around without first checking which transaction object to work with.

I feel your pain, but I wonder why we sometimes accept "a line of code 
can't be moved around" as an issue to be solved by the language. After 
all, in general most lines of code can't be moved around.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#50115

FromChris Angelico <rosuav@gmail.com>
Date2013-07-08 13:11 +1000
Message-ID<mailman.4363.1373253106.3114.python-list@python.org>
In reply to#50114
On Mon, Jul 8, 2013 at 12:23 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> On Mon, 08 Jul 2013 10:48:03 +1000, Chris Angelico wrote:
> [...]
>> That means that I, as programmer, have to keep track of the nesting
>> level of subtransactions. Extremely ugly. A line of code can't be moved
>> around without first checking which transaction object to work with.
>
> I feel your pain, but I wonder why we sometimes accept "a line of code
> can't be moved around" as an issue to be solved by the language. After
> all, in general most lines of code can't be moved around.

It's not something to be solved by the language, but it's often
something to be solved by the program's design. Two lines of code that
achieve the same goal should normally look the same. This is why
Python's policy is "one obvious way to do something" rather than
"spell it five different ways in the same file to make a nightmare for
other people coming after you". Why should database queries be spelled
"trans1.query()" in one place, and "trans2.query()" in another?
Similarly, if I want to call another function and that function needs
to use the database, why should I pass it trans3 and have that come
out as trans1 on the other side? Unnecessarily confusing. Makes much
more sense to use the same name everywhere.

ChrisA

[toc] | [prev] | [next] | [standalone]


#50116

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-07-08 05:00 +0000
Message-ID<51da4780$0$6512$c3e8da3$5496439d@news.astraweb.com>
In reply to#50115
On Mon, 08 Jul 2013 13:11:37 +1000, Chris Angelico wrote:

> On Mon, Jul 8, 2013 at 12:23 PM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
>> On Mon, 08 Jul 2013 10:48:03 +1000, Chris Angelico wrote: [...]
>>> That means that I, as programmer, have to keep track of the nesting
>>> level of subtransactions. Extremely ugly. A line of code can't be
>>> moved around without first checking which transaction object to work
>>> with.
>>
>> I feel your pain, but I wonder why we sometimes accept "a line of code
>> can't be moved around" as an issue to be solved by the language. After
>> all, in general most lines of code can't be moved around.
> 
> It's not something to be solved by the language, but it's often
> something to be solved by the program's design. Two lines of code that
> achieve the same goal should normally look the same. This is why
> Python's policy is "one obvious way to do something" rather than "spell
> it five different ways in the same file to make a nightmare for other
> people coming after you". Why should database queries be spelled
> "trans1.query()" in one place, and "trans2.query()" in another?

Is that a trick question? They probably shouldn't. But it's a big leap 
from that to "...and therefore `for` and `while` should introduce their 
own scope".


> Similarly, if I want to call another function and that function needs to
> use the database, why should I pass it trans3 and have that come out as
> trans1 on the other side? Unnecessarily confusing. Makes much more sense
> to use the same name everywhere.

"Is your name not Bruce? That's going to cause a little confusion."

http://www.youtube.com/watch?v=_f_p0CgPeyA



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#50117

FromChris Angelico <rosuav@gmail.com>
Date2013-07-08 15:14 +1000
Message-ID<mailman.4364.1373260454.3114.python-list@python.org>
In reply to#50116
On Mon, Jul 8, 2013 at 3:00 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> On Mon, 08 Jul 2013 13:11:37 +1000, Chris Angelico wrote:
>> It's not something to be solved by the language, but it's often
>> something to be solved by the program's design. Two lines of code that
>> achieve the same goal should normally look the same. This is why
>> Python's policy is "one obvious way to do something" rather than "spell
>> it five different ways in the same file to make a nightmare for other
>> people coming after you". Why should database queries be spelled
>> "trans1.query()" in one place, and "trans2.query()" in another?
>
> Is that a trick question? They probably shouldn't. But it's a big leap
> from that to "...and therefore `for` and `while` should introduce their
> own scope".

No, it's not a trick question; I was responding to Ethan's suggestion
as well as yours, and he was saying pretty much that.

BruceA
(maybe that'll reduce the confusion?)

[toc] | [prev] | [next] | [standalone]


#49819

FromPeter Otten <__peter__@web.de>
Date2013-07-04 08:48 +0200
Message-ID<mailman.4209.1372920514.3114.python-list@python.org>
In reply to#49813
Steven D'Aprano wrote:

> Well, if I ever have more than 63,000,000 variables[1] in a function,
> I'll keep that in mind. Until then, I'm pretty sure you can trivially
> avoid name clashes with globals that you wish to avoid clashing with.

> [1] Based on empirical evidence that Python supports names with length at
> least up to one million characters long, and assuming that each character
> can be an ASCII letter, digit or underscore.

That would be 63**10**6. Or 53*63**999999 if I were to nitpick... 

[toc] | [prev] | [next] | [standalone]


#49820

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-07-04 01:12 -0600
Message-ID<mailman.4210.1372921992.3114.python-list@python.org>
In reply to#49813
On Wed, Jul 3, 2013 at 11:32 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
>> Python lets you do that across but not within functions.
>>
>> But Javascript/ECMAScript/whatever doesn't give you that. A var
>> declaration makes it function-local, no matter where the declaration is.
>> That's pointless. C++, on the other hand, lets you do this:
>>
>> void somefunc() {
>>     for (int i=0;i<10;++i) {
>>         // do something with outer i
>>         for (int i=0;i<4;++i) {
>>             // do something with inner i
>>         }
>>         // outer i is visible again
>>     }
>>     // neither i is visible
>> }
>
> That's truly horrible. If the cost of this "flexibility" is that I'll
> have to read, and debug, other people's code with this sort of thing, I'm
> happy to be less flexible. For what possible reason other than "because I
> can" would you want to use the same loop variable name in two nested
> loops?

It's interesting to note that while Java and C# also allow reuse of
local variable names, they do not allow local variables declared in
inner scopes to shadow variables declared in enclosing scopes, as in
the example above.  But the following would be perfectly legal:

void somefunc() {
    for (int i = 0; i < a.size; ++i) {
        // do something with a[i]
    }
    for (int i = 0; i < b.size; ++i) {
        // do something with b[i]
    }
}

And the two i's are treated as completely separate variables here, as
arguably they should be since they're used for two distinct purposes.

[toc] | [prev] | [next] | [standalone]


#49822

FromDave Angel <davea@davea.name>
Date2013-07-04 03:06 -0400
Message-ID<mailman.4211.1372924504.3114.python-list@python.org>
In reply to#49813
On 07/04/2013 01:32 AM, Steven D'Aprano wrote:
>
       <SNIP>
>
> Well, if I ever have more than 63,000,000 variables[1] in a function,
> I'll keep that in mind.
>
     <SNIP>
>
> [1] Based on empirical evidence that Python supports names with length at
> least up to one million characters long, and assuming that each character
> can be an ASCII letter, digit or underscore.
>

Well, the number wouldn't be 63,000,000.  Rather it'd be 63**1000000

I probably have it wrong, but I think that looks like:

859,122,207,646,748,720,415,212,786,780,258,721,683,540,870,960,267,706,738,947,655,539,422,295,787,680,882,091,181,482,626,114,653,152,637,456,091,641,990,601,474,111,018,521,295,858,424,750,289,461,372,414,431,396,326,232,796,267,104,001

variables.  (The number has 180 digits)

--
DaveA

[toc] | [prev] | [next] | [standalone]


#49880

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-07-04 15:52 +0000
Message-ID<51d59a36$0$29999$c3e8da3$5496439d@news.astraweb.com>
In reply to#49822
On Thu, 04 Jul 2013 03:06:25 -0400, Dave Angel wrote:

> On 07/04/2013 01:32 AM, Steven D'Aprano wrote:
>>
>        <SNIP>
>>
>> Well, if I ever have more than 63,000,000 variables[1] in a function,
>> I'll keep that in mind.
>>
>      <SNIP>
>>
>> [1] Based on empirical evidence that Python supports names with length
>> at least up to one million characters long, and assuming that each
>> character can be an ASCII letter, digit or underscore.
>>
>>
> Well, the number wouldn't be 63,000,000.  Rather it'd be 63**1000000
> 
> I probably have it wrong, but I think that looks like:
> 
> 
859,122,207,646,748,720,415,212,786,780,258,721,683,540,870,960,267,706,738,947,655,539,422,295,787,680,882,091,181,482,626,114,653,152,637,456,091,641,990,601,474,111,018,521,295,858,424,750,289,461,372,414,431,396,326,232,796,267,104,001
> 
> variables.  (The number has 180 digits)


I think that's more than 63,000,000 :-)


Thanks Dave and Peter for the correction.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#49886

FromRotwang <sg552@hotmail.co.uk>
Date2013-07-04 17:54 +0100
Message-ID<kr491h$g2t$1@dont-email.me>
In reply to#49822
Sorry to be OT, but this is sending my pedantry glands haywire:

On 04/07/2013 08:06, Dave Angel wrote:
> On 07/04/2013 01:32 AM, Steven D'Aprano wrote:
>>
>        <SNIP>
>>
>> Well, if I ever have more than 63,000,000 variables[1] in a function,
>> I'll keep that in mind.
>>
>      <SNIP>
>>
>> [1] Based on empirical evidence that Python supports names with length at
>> least up to one million characters long, and assuming that each character
>> can be an ASCII letter, digit or underscore.
>>
>
> Well, the number wouldn't be 63,000,000.  Rather it'd be 63**1000000
>
> I probably have it wrong, but I think that looks like:
>
> 859,122,[etc.]
>
>
> variables.  (The number has 180 digits)

That's 63**100. Note that 10**1000000 has 1000001 digits, and is 
somewhat smaller than 63**1000000.

Anyway, none of the calculations that has been given takes into account 
the fact that names can be /less/ than one million characters long. The 
actual number of non-empty strings of length at most 1000000 characters, 
that consist only of ascii letters, digits or underscores, and that 
don't start with a digit, is

sum(53*63**i for i in range(1000000)) == 53*(63**1000000 - 1)//62


It's perhaps worth mentioning that some non-ascii characters are allowed 
in identifiers in Python 3, though I don't know which ones.

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.python


csiph-web