Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #16967 > unrolled thread
| Started by | Roy Smith <roy@panix.com> |
|---|---|
| First post | 2011-12-10 15:47 -0500 |
| Last post | 2011-12-13 10:15 +0100 |
| Articles | 20 on this page of 27 — 12 participants |
Back to article view | Back to comp.lang.python
Overriding a global Roy Smith <roy@panix.com> - 2011-12-10 15:47 -0500
Re: Overriding a global MRAB <python@mrabarnett.plus.com> - 2011-12-10 21:07 +0000
Re: Overriding a global Roy Smith <roy@panix.com> - 2011-12-10 16:10 -0500
Re: Overriding a global Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-12-12 12:13 +0100
Re: Overriding a global Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-12 21:28 +0000
Re: Overriding a global Dave Angel <d@davea.name> - 2011-12-12 16:43 -0500
Re: Overriding a global Ben Finney <ben+python@benfinney.id.au> - 2011-12-13 09:27 +1100
Re: Overriding a global Dave Angel <d@davea.name> - 2011-12-12 20:46 -0500
Re: Overriding a global Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-13 01:48 +0000
Re: Overriding a global Ian Kelly <ian.g.kelly@gmail.com> - 2011-12-12 22:50 -0700
Re: Overriding a global Joshua Landau <joshua.landau.ws@gmail.com> - 2011-12-13 08:34 +0000
Re: Overriding a global Ian Kelly <ian.g.kelly@gmail.com> - 2011-12-13 12:34 -0700
Re: Overriding a global Ian Kelly <ian.g.kelly@gmail.com> - 2011-12-13 12:54 -0700
Re: Overriding a global Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-12-13 10:54 +0100
Re: Overriding a global Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-13 11:15 +0000
Re: Overriding a global Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-12-13 14:30 +0100
Re: Overriding a global Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-12-14 11:14 +0100
Re: Overriding a global Chris Angelico <rosuav@gmail.com> - 2011-12-14 21:32 +1100
Re: Overriding a global Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-12-14 13:05 +0100
Re: Overriding a global Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-14 12:53 +0000
Re: Overriding a global Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-12-14 14:35 +0100
Re: Overriding a global Chris Angelico <rosuav@gmail.com> - 2011-12-14 23:21 +1100
Re: Overriding a global Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-12-14 18:06 +0100
Re: Overriding a global Terry Reedy <tjreedy@udel.edu> - 2011-12-10 19:14 -0500
Re: Overriding a global Terry Reedy <tjreedy@udel.edu> - 2011-12-10 19:19 -0500
Re: Overriding a global Peter Otten <__peter__@web.de> - 2011-12-11 09:14 +0100
Re: Overriding a global Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2011-12-13 10:15 +0100
Page 1 of 2 [1] 2 Next page →
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2011-12-10 15:47 -0500 |
| Subject | Overriding a global |
| Message-ID | <roy-B236C9.15475310122011@news.panix.com> |
I've got a code pattern I use a lot. In each module, I create a logger
for the entire module and log to it all over:
logger = logging.getLogger('my.module.name')
class Foo:
def function(self):
logger.debug('stuff')
logger.debug('other stuff')
and so on. This works, but every once in a while I decide that a
particular function needs a more specific logger, so I can adjust the
logging level for that function independent of the rest of the module.
What I really want to do is:
def function(self):
logger = logger.getChild('function')
logger.debug('stuff')
logger.debug('other stuff')
which lets me not have to change any lines of code other than inserting
the one to redefine logger. Unfortunately, that's not legal Python (it
leads to "UnboundLocalError: local variable 'logger' referenced before
assignment").
Any ideas on the best way to implement this?
[toc] | [next] | [standalone]
| From | MRAB <python@mrabarnett.plus.com> |
|---|---|
| Date | 2011-12-10 21:07 +0000 |
| Message-ID | <mailman.3500.1323551240.27778.python-list@python.org> |
| In reply to | #16967 |
On 10/12/2011 20:47, Roy Smith wrote:
> I've got a code pattern I use a lot. In each module, I create a logger
> for the entire module and log to it all over:
>
> logger = logging.getLogger('my.module.name')
>
> class Foo:
> def function(self):
> logger.debug('stuff')
> logger.debug('other stuff')
>
> and so on. This works, but every once in a while I decide that a
> particular function needs a more specific logger, so I can adjust the
> logging level for that function independent of the rest of the module.
> What I really want to do is:
>
> def function(self):
> logger = logger.getChild('function')
> logger.debug('stuff')
> logger.debug('other stuff')
>
> which lets me not have to change any lines of code other than inserting
> the one to redefine logger. Unfortunately, that's not legal Python (it
> leads to "UnboundLocalError: local variable 'logger' referenced before
> assignment").
>
> Any ideas on the best way to implement this?
You could use a different name:
def function(self):
logger2 = logger.getChild('function')
logger2.debug('stuff')
logger2.debug('other stuff')
or use 'globals':
def function(self):
logger = globals()['logger'].getChild('function')
logger.debug('stuff')
logger.debug('other stuff')
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2011-12-10 16:10 -0500 |
| Message-ID | <roy-EC9997.16105310122011@news.panix.com> |
| In reply to | #16968 |
MRAB <python@mrabarnett.plus.com> wrote:
> or use 'globals':
>
> def function(self):
> logger = globals()['logger'].getChild('function')
> logger.debug('stuff')
> logger.debug('other stuff')
Ah-ha! That's precisely what I was looking for. Much appreciated.
[toc] | [prev] | [next] | [standalone]
| From | Jean-Michel Pichavant <jeanmichel@sequans.com> |
|---|---|
| Date | 2011-12-12 12:13 +0100 |
| Message-ID | <mailman.3542.1323688423.27778.python-list@python.org> |
| In reply to | #16969 |
Roy Smith wrote:
> MRAB <python@mrabarnett.plus.com> wrote:
>
>
>> or use 'globals':
>>
>> def function(self):
>> logger = globals()['logger'].getChild('function')
>> logger.debug('stuff')
>> logger.debug('other stuff')
>>
>
> Ah-ha! That's precisely what I was looking for. Much appreciated.
>
Using the same name for 2 different objects is a bad idea in general.
In debug mode, i.e. the logger is configured with the debug level, you
could simply write down the filename and the line number on your log
events.
formatter = logging.Formatter('%(name)s : %(filename)s %(lineno)s
%(message)s')
So you can easily see who logged what (if I'm not wrong, that's what
you're trying to do)
JM
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-12-12 21:28 +0000 |
| Message-ID | <4ee671f6$0$29979$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #17030 |
On Mon, 12 Dec 2011 12:13:33 +0100, Jean-Michel Pichavant wrote: > Using the same name for 2 different objects is a bad idea in general. We have namespaces precisely so you don't need to care about making names globally unique. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Dave Angel <d@davea.name> |
|---|---|
| Date | 2011-12-12 16:43 -0500 |
| Message-ID | <mailman.3569.1323726243.27778.python-list@python.org> |
| In reply to | #17082 |
On 12/12/2011 04:28 PM, Steven D'Aprano wrote:
> On Mon, 12 Dec 2011 12:13:33 +0100, Jean-Michel Pichavant wrote:
>
>> Using the same name for 2 different objects is a bad idea in general.
> We have namespaces precisely so you don't need to care about making names
> globally unique.
>
>
True, but in this code, the function is trying to both use the global
value, but also a local that deliberately has the same name, but a
different meaning and "value". The CPython compiler doesn't make this
easy, and I think the globals() technique is unnecessarily obscure, as
is the default-argument trick.
If a function knows of the presence of a global, it's not asking too
much for it to not re-use the same name in local scope.
Since it seems to be in vogue to propose language changes, how about a
new place for 'as' ?
def myfunc():
global logger as g_logger
logger = g_logger.debug('stuff').getChild('function')
--
DaveA
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2011-12-13 09:27 +1100 |
| Message-ID | <87k4611l4y.fsf@benfinney.id.au> |
| In reply to | #17083 |
Dave Angel <d@davea.name> writes: > True, but in this code, the function is trying to both use the global > value, but also a local that deliberately has the same name, but a > different meaning and "value". The CPython compiler doesn't make this > easy, and I think the globals() technique is unnecessarily obscure, as > is the default-argument trick. I disagree. The language makes it difficult, and it *should* be difficult to do what you describe. The tricks to achieve it are obscure and ugly, which is a good thing IMO: they're a code smell that the design of the code needs changing. Or, in brief: they're not unnecessarily obscure, they're as obscure as they need to be. > If a function knows of the presence of a global, it's not asking too > much for it to not re-use the same name in local scope. Yes. -- \ “Airports are ugly. Some are very ugly. Some attain a degree of | `\ ugliness that can only be the result of a special effort.” | _o__) —Douglas Adams, _The Long Dark Tea-Time Of The Soul_ | Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Dave Angel <d@davea.name> |
|---|---|
| Date | 2011-12-12 20:46 -0500 |
| Message-ID | <mailman.3575.1323740790.27778.python-list@python.org> |
| In reply to | #17086 |
On 12/12/2011 06:48 PM, Joshua Landau wrote: >>> If a function knows of the presence of a global, it's not asking too >>> much for it to not re-use the same name in local scope. >> Yes. > > It's just a function wanting to act as-if it were in a different > environment than its default. By that same reasoning you could state that > "If a function knows of the presence of a built-in, it's not asking > too much for it to not re-use the same name in local scope." > <SNIP> It's entirely different. It's only the same if the function actually tries to call the built-in, then also wants a local variable with a different purpose. Think a little about what I mean that the function "knows of the presence." I did not say the programmer knows of the presence. -- DaveA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-12-13 01:48 +0000 |
| Message-ID | <4ee6aefa$0$11091$c3e8da3@news.astraweb.com> |
| In reply to | #17086 |
On Tue, 13 Dec 2011 09:27:09 +1100, Ben Finney wrote:
> Dave Angel <d@davea.name> writes:
>
>> True, but in this code, the function is trying to both use the global
>> value, but also a local that deliberately has the same name, but a
>> different meaning and "value". The CPython compiler doesn't make this
>> easy, and I think the globals() technique is unnecessarily obscure, as
>> is the default-argument trick.
>
> I disagree. The language makes it difficult, and it *should* be
> difficult to do what you describe.
>
> The tricks to achieve it are obscure and ugly, which is a good thing
> IMO: they're a code smell that the design of the code needs changing.
Devil's Advocate: perhaps not. Think of local and global names as
analogous to instance and class attributes. There are good use cases for
making something a class attribute, while allowing instances to override
that name with an instance attribute. I see a reasonable case for saying
"use this global, unless a local overrides it".
Similarly, globals override built-ins with the same name; while
monkeypatching needs to be used with care, it is a legitimate technique.
To a human reader, the following pseudocode might be ambiguous, but
either case makes sense:
x = 1
def spam():
print x # prints 1
x = 2 # does this create a new local x, or modify the old global x?
print x # unambiguously prints 2
print x # prints 1 or 2
Python doesn't allow this, but another language might; in Python, a
reasonable way to get similar behaviour might be:
x = 1
def spam():
print globals()['x']
x = 2 # unambiguously creates a new local x
print x # unambiguously prints 2
print x # unambiguously prints 1
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-12-12 22:50 -0700 |
| Message-ID | <mailman.3579.1323755476.27778.python-list@python.org> |
| In reply to | #17086 |
On Mon, Dec 12, 2011 at 4:48 PM, Joshua Landau <joshua.landau.ws@gmail.com> wrote: > Rebinding logger locally in a function is really no > different to a subclass rebinding a variable from its main class using that > class' value. The only difference is that, in that case, you have an > alternate binding to the original value. No, there is another difference, the reason for rebinding the name. In a subclass, you would rebind a class attribute because that particular attribute, which you need to change, is used and expected by external code, either in the base class or in code that uses its API (or both). Local variables in functions, on the other hand, are not externally visible, so there is no need to do this in order to conform to the expectations of external code. All it does in that case is to sow potential confusion.
[toc] | [prev] | [next] | [standalone]
| From | Joshua Landau <joshua.landau.ws@gmail.com> |
|---|---|
| Date | 2011-12-13 08:34 +0000 |
| Message-ID | <mailman.3580.1323765301.27778.python-list@python.org> |
| In reply to | #17086 |
On 13/12/2011, Ian Kelly <ian.g.kelly@gmail.com> wrote: > On Mon, Dec 12, 2011 at 4:48 PM, Joshua Landau > <joshua.landau.ws@gmail.com> wrote: >> Rebinding logger locally in a function is really no >> different to a subclass rebinding a variable from its main class using >> that >> class' value. The only difference is that, in that case, you have an >> alternate binding to the original value. > > No, there is another difference, the reason for rebinding the name. > In a subclass, you would rebind a class attribute because that > particular attribute, which you need to change, is used and expected > by external code, either in the base class or in code that uses its > API (or both). Local variables in functions, on the other hand, are > not externally visible, so there is no need to do this in order to > conform to the expectations of external code. All it does in that > case is to sow potential confusion. > So you're saying you should never extend methods or attributes that aren't meant to be used as part of of the API? Because I can claim guilty on this point. I'd make this longer, but I've got class now :(
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-12-13 12:34 -0700 |
| Message-ID | <mailman.3615.1323804914.27778.python-list@python.org> |
| In reply to | #17086 |
On Tue, Dec 13, 2011 at 1:34 AM, Joshua Landau <joshua.landau.ws@gmail.com> wrote: >> No, there is another difference, the reason for rebinding the name. >> In a subclass, you would rebind a class attribute because that >> particular attribute, which you need to change, is used and expected >> by external code, either in the base class or in code that uses its >> API (or both). Local variables in functions, on the other hand, are >> not externally visible, so there is no need to do this in order to >> conform to the expectations of external code. All it does in that >> case is to sow potential confusion. >> > So you're saying you should never extend methods or attributes that > aren't meant to be used as part of of the API? Because I can claim > guilty on this point. No, I'm only saying that replacing attributes in subclasses is accepted because it is necessary due to external dependencies, and that local variables in functions don't have that excuse.
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-12-13 12:54 -0700 |
| Message-ID | <mailman.3618.1323806080.27778.python-list@python.org> |
| In reply to | #17086 |
On Tue, Dec 13, 2011 at 12:43 PM, Joshua Landau <joshua.landau.ws@gmail.com> wrote: > On 13 December 2011 19:34, Ian Kelly <ian.g.kelly@gmail.com> wrote: >> >> On Tue, Dec 13, 2011 at 1:34 AM, Joshua Landau >> <joshua.landau.ws@gmail.com> wrote: >> >> No, there is another difference, the reason for rebinding the name. >> >> In a subclass, you would rebind a class attribute because that >> >> particular attribute, which you need to change, is used and expected >> >> by external code, either in the base class or in code that uses its >> >> API (or both). Local variables in functions, on the other hand, are >> >> not externally visible, so there is no need to do this in order to >> >> conform to the expectations of external code. All it does in that >> >> case is to sow potential confusion. >> >> >> > So you're saying you should never extend methods or attributes that >> > aren't meant to be used as part of of the API? Because I can claim >> > guilty on this point. >> >> No, I'm only saying that replacing attributes in subclasses is >> accepted because it is necessary due to external dependencies, and >> that local variables in functions don't have that excuse. > > > But they aren't needed due to external dependencies if they're > implementation-specific and not part of the API, no? By "external dependencies" I mean anything that's not specifically part of the subclass. This includes the base class. If they're not part of the API, then the base class presumably uses them for something, and by replacing them, you change the behavior of that base functionality. That's an external dependency.
[toc] | [prev] | [next] | [standalone]
| From | Jean-Michel Pichavant <jeanmichel@sequans.com> |
|---|---|
| Date | 2011-12-13 10:54 +0100 |
| Message-ID | <mailman.3583.1323770094.27778.python-list@python.org> |
| In reply to | #17082 |
Steven D'Aprano wrote: > On Mon, 12 Dec 2011 12:13:33 +0100, Jean-Michel Pichavant wrote: > > >> Using the same name for 2 different objects is a bad idea in general. >> > > We have namespaces precisely so you don't need to care about making names > globally unique. > > > I don't get your point, namespaced names are unique, by definition. foo.aname <> bar.aname The OP showed a code where there was a confusion between a global name and a local one. There's no namespace involved. Having a local name identical to a global one is a bad idea, def. JM
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-12-13 11:15 +0000 |
| Message-ID | <4ee733d4$0$29979$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #17116 |
On Tue, 13 Dec 2011 10:54:51 +0100, Jean-Michel Pichavant wrote:
> Steven D'Aprano wrote:
>> On Mon, 12 Dec 2011 12:13:33 +0100, Jean-Michel Pichavant wrote:
>>
>>
>>> Using the same name for 2 different objects is a bad idea in general.
>>>
>>>
>> We have namespaces precisely so you don't need to care about making
>> names globally unique.
>>
>>
>>
> I don't get your point, namespaced names are unique, by definition.
>
> foo.aname <> bar.aname
Assuming foo and bar are not names for the same object, there are at
least three namespaces here: the local namespace, where foo and bar can
be found, the foo.__dict__ namespace, and the bar.__dict__ namespace.
> The OP showed a code where there was a confusion between a global name
> and a local one. There's no namespace involved. Having a local name
> identical to a global one is a bad idea, def.
Of course there are namespaces involved. There is the global namespace,
and the local namespace. That's how you can have x inside a function
without it overwriting global x outside of it, because they are different
namespaces. Which is my point.
When I write this:
x = 1
def spam():
x = 2
def ham():
x = 3
The three x's don't clash because they are in three separate namespaces.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Jean-Michel Pichavant <jeanmichel@sequans.com> |
|---|---|
| Date | 2011-12-13 14:30 +0100 |
| Message-ID | <mailman.3596.1323783056.27778.python-list@python.org> |
| In reply to | #17123 |
Steven D'Aprano wrote:
> On Tue, 13 Dec 2011 10:54:51 +0100, Jean-Michel Pichavant wrote:
>
>
>> Steven D'Aprano wrote:
>>
>>> On Mon, 12 Dec 2011 12:13:33 +0100, Jean-Michel Pichavant wrote:
>>>
>>>
>>>
>>>> Using the same name for 2 different objects is a bad idea in general.
>>>>
>>>>
>>>>
>>> We have namespaces precisely so you don't need to care about making
>>> names globally unique.
>>>
>>>
>>>
>>>
>> I don't get your point, namespaced names are unique, by definition.
>>
>> foo.aname <> bar.aname
>>
>
> Assuming foo and bar are not names for the same object, there are at
> least three namespaces here: the local namespace, where foo and bar can
> be found, the foo.__dict__ namespace, and the bar.__dict__ namespace.
>
>
>
>> The OP showed a code where there was a confusion between a global name
>> and a local one. There's no namespace involved. Having a local name
>> identical to a global one is a bad idea, def.
>>
>
> Of course there are namespaces involved. There is the global namespace,
> and the local namespace. That's how you can have x inside a function
> without it overwriting global x outside of it, because they are different
> namespaces. Which is my point.
>
> When I write this:
>
> x = 1
>
> def spam():
> x = 2
>
> def ham():
> x = 3
>
> The three x's don't clash because they are in three separate namespaces.
>
>
I know that, why do I have the feel this is juste a semantic issue ?
Aren't you/I/we confusion namespaces & scopes ?
Anyway, semantic is not what we're interested in here.
writing
x = 1
def spam():
x = 2
is in general a bad idea. That was my point.
JM
[toc] | [prev] | [next] | [standalone]
| From | Jean-Michel Pichavant <jeanmichel@sequans.com> |
|---|---|
| Date | 2011-12-14 11:14 +0100 |
| Message-ID | <mailman.3631.1323857696.27778.python-list@python.org> |
| In reply to | #17123 |
Joshua Landau wrote:
> On 13 December 2011 13:30, Jean-Michel Pichavant
> <jeanmichel@sequans.com <mailto:jeanmichel@sequans.com>> wrote:
>
> writing
>
> x = 1
>
> def spam():
> x = 2
>
> is in general a bad idea. That was my point.
>
>
> Why? I have a few (probably wrong) guesses.
>
> Because you expect it to be the same every time you use it?
> Well, then this should be "in general a bad idea":
> x = 1; print(x); x = 2; print(x)
you're changing the value of x, that's fine. In the example above, the
assignement is not the problem. The problem is that you create 2
different 'x', one in globals(), and one in locals(). Using the same
name within 2 implicit namespaces is a bad idead in general because it
can be difficult to know which one is used.
If you want to have fun, try this code, prepared to be amazed. There's
something funny with the global statement, it's applied on the whole
block no matter where it is stated in the block.
x=1 # global
def spam():
x = 2 # local (or so you may think)
print x
global x # I need to use the global one now
print x
print locals()
For more fun you could create a 'x' name in __builtin__ and import it so
that people never know which x you are using.
> Even though it makes total sense to me.
>
> Is it because it's used to different purpose between similarly-looking
> functions?
> This looks fine, though:
> def func1(): x=1; print(x)
> def func2(): x=2; print(x)
>
> Is it because it looks like a reassignment of the more global x?
> I don't have an example here but, simply put, I don't believe this. We
> can use "id" as our own local variable without thinking that we're
> tampering with "__builtins__.id". I don't see it as much of a leap
> from builtin to global (except that you /*can*/ do "dir = 1; del dir;
> dir" without error).
>
> That said, I'm sorta' just guessing the reason you might think it's a
> bad idea.
The problem makes little sense when using names like x or func1. Besides
namespace issues, naming 2 *different objects* with the same meaningful
name is usually a bad idea and points the fact that your names are no
that meaningful. To go back to the original post, having a 'logger' that
may name 2 different logger object during the execution is a bad idea.
One quick way to fix it is to name the logger 'currentLogger', this way
you warn the reader that the logger named by curentLogger may change
over time.
As someone sugggested in this thread one other option is to use a
different name for the second logger.
JM
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-12-14 21:32 +1100 |
| Message-ID | <mailman.3633.1323859064.27778.python-list@python.org> |
| In reply to | #17123 |
On Wed, Dec 14, 2011 at 9:14 PM, Jean-Michel Pichavant <jeanmichel@sequans.com> wrote: > The problem makes little sense when using names like x or func1. Besides > namespace issues, naming 2 *different objects* with the same meaningful name > is usually a bad idea and points the fact that your names are no that > meaningful. So... it's a bad idea for me to use 'i' many times in my code, with the same name having different meanings in different places? In languages with infinitely-nesting scopes (one of Python's great lacks, imho), I've often had three different variables with the same names, all perfectly valid, and all doing what they should. It's not just loop indices - I used to have a piece of code in which 'res' was a MySQL resource being processed in a loop, and I had three nested loops. Each time I referenced 'res', it used the innermost available resource, which was precisely what I wanted. If I'd arbitrarily had to guarantee that all variable names were unique, I would have had completely unnecessary fiddling around. Python wouldn't let you do that with three nested 'res'es in one function, but you can perfectly reasonably have a global and a local. It makes perfect sense... which is a good reason for keeping it legal. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Jean-Michel Pichavant <jeanmichel@sequans.com> |
|---|---|
| Date | 2011-12-14 13:05 +0100 |
| Message-ID | <mailman.3638.1323864323.27778.python-list@python.org> |
| In reply to | #17123 |
Chris Angelico wrote:
> On Wed, Dec 14, 2011 at 9:14 PM, Jean-Michel Pichavant
> <jeanmichel@sequans.com> wrote:
>
>> The problem makes little sense when using names like x or func1. Besides
>> namespace issues, naming 2 *different objects* with the same meaningful name
>> is usually a bad idea and points the fact that your names are no that
>> meaningful.
>>
>
> So... it's a bad idea for me to use 'i' many times in my code, with
> the same name having different meanings in different places? In
> languages with infinitely-nesting scopes (one of Python's great lacks,
> imho), I've often had three different variables with the same names,
> all perfectly valid, and all doing what they should. It's not just
> loop indices - I used to have a piece of code in which 'res' was a
> MySQL resource being processed in a loop, and I had three nested
> loops. Each time I referenced 'res', it used the innermost available
> resource, which was precisely what I wanted. If I'd arbitrarily had to
> guarantee that all variable names were unique, I would have had
> completely unnecessary fiddling around.
>
> Python wouldn't let you do that with three nested 'res'es in one
> function, but you can perfectly reasonably have a global and a local.
> It makes perfect sense... which is a good reason for keeping it legal.
>
> ChrisA
>
Bad ideas :
i = 5
def spam():
for i,v in enumerate([1,2,3,4]):
for i,v in enumerate(['a','b', 'c']):
print i, v
print i,v # bad surprise
good ideas :
# global
nameThatWillNotBeUsedlocally = 'foo'
def spam():
for qtyIndex, quantity in enumerate([5,6,3,1]):
for fruitIndex, fruit in enumerate(['orange', 'banana']):
print fruitIndex, fruit
print qtyIndex, quantity
While a lot of people still use i,j,k,v to handler values and indexes, I
think it's a bad idea. I'm just stating an opinion from my personnal
python experience. I know some people can successfully use the hard way.
JM
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-12-14 12:53 +0000 |
| Message-ID | <4ee89c41$0$29979$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #17200 |
On Wed, 14 Dec 2011 13:05:19 +0100, Jean-Michel Pichavant wrote: > Bad ideas : > > i = 5 > > def spam(): > for i,v in enumerate([1,2,3,4]): > for i,v in enumerate(['a','b', 'c']): > print i, v > print i,v # bad surprise The bad surprise happens because you are using the same name twice in *one* namespace, the local scope. This example has nothing to do with local/global name clashes: the existence of global i is irrelevant. Python's scoping rules work correctly, and global i is not affected by the local i. Programming languages use multiple namespaces so that you don't need to make your variable names globally unique. There are languages that don't distinguish between local and global. Python is not one of them. The programmer should feel free to use local names without worrying too much if they accidentally use a global name. Having said that, re-using names isn't *entirely* risk free, because if you use a global name locally, and then try to *also* access the global name, you will fail. This is called shadowing, and the problem with shadowing is when you do it by accident. (Newbies are particularly prone to this, especially when they call variables "str", "list", etc.) But it is the "by accident" part that is dangerous: there is nothing wrong with shadowing globals or builtins when you do it by design. > good ideas : > > # global > nameThatWillNotBeUsedlocally = 'foo' Oh please. Names can be too long as well as too short. > def spam(): > for qtyIndex, quantity in enumerate([5,6,3,1]): > for fruitIndex, fruit in enumerate(['orange', 'banana']): > print fruitIndex, fruit > print qtyIndex, quantity More sensible naming conventions are to be encouraged, but verbose names just for the sake of verbosity is not. spam() is a five line function; if the programmer can't keep track of the meaning of loop variables i and j over five lines, perhaps they should consider a change of career and get a job more suited to their intellectual prowess. I hear McDonalds is hiring. If spam() were larger and more complex, then more expressive names would be valuable. But in the simple example you give, it just adds noise. -- Steven
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web