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


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

"Don't rebind built-in names*" - it confuses readers

Started byTerry Jan Reedy <tjreedy@udel.edu>
First post2013-06-10 20:14 -0400
Last post2013-06-12 03:32 +1000
Articles 20 on this page of 21 — 9 participants

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


Contents

  "Don't rebind built-in names*" - it confuses readers Terry Jan Reedy <tjreedy@udel.edu> - 2013-06-10 20:14 -0400
    Re: "Don't rebind built-in names*" - it confuses readers rusi <rustompmody@gmail.com> - 2013-06-10 19:36 -0700
      Re: "Don't rebind built-in names*" - it confuses readers Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-11 03:02 +0000
        Re: "Don't rebind built-in names*" - it confuses readers rusi <rustompmody@gmail.com> - 2013-06-10 20:30 -0700
          Re: "Don't rebind built-in names*" - it confuses readers Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-11 05:52 +0000
          Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-11 17:20 +1000
        Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-11 13:57 +1000
        Re: "Don't rebind built-in names*" - it confuses readers Serhiy Storchaka <storchaka@gmail.com> - 2013-06-11 18:55 +0300
        Re: "Don't rebind built-in names*" - it confuses readers Mark Janssen <dreamingforward@gmail.com> - 2013-06-12 17:04 -0700
          Re: "Don't rebind built-in names*" - it confuses readers Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-13 01:01 +0000
        Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-13 10:08 +1000
          Re: "Don't rebind built-in names*" - it confuses readers Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-13 01:08 +0000
            Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-13 11:30 +1000
        Re: "Don't rebind built-in names*" - it confuses readers Skip Montanaro <skip@pobox.com> - 2013-06-12 19:18 -0500
        Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-13 10:33 +1000
        Re: "Don't rebind built-in names*" - it confuses readers Ethan Furman <ethan@stoneleaf.us> - 2013-06-12 17:30 -0700
    Re: "Don't rebind built-in names*" - it confuses readers Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-11 02:56 +0000
      Re: "Don't rebind built-in names*" - it confuses readers Terry Jan Reedy <tjreedy@udel.edu> - 2013-06-11 02:06 -0400
      Re: "Don't rebind built-in names*" - it confuses readers Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-11 08:22 -0700
        Re: "Don't rebind built-in names*" - it confuses readers Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-11 16:59 +0000
        Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-12 03:32 +1000

Page 1 of 2  [1] 2  Next page →


#47622 — "Don't rebind built-in names*" - it confuses readers

FromTerry Jan Reedy <tjreedy@udel.edu>
Date2013-06-10 20:14 -0400
Subject"Don't rebind built-in names*" - it confuses readers
Message-ID<mailman.3001.1370909708.3114.python-list@python.org>
Many long-time posters have advised "Don't rebind built-in names*.

* Unless you really mean to mask it, or more likely wrap it, such as 
wrapping print to modify some aspect of its operation than one cannot do 
with its keyword parameters. The point for this post is that such 
wrapping modify or extend the basic meaning of the builtin, but do not 
abolish it.

Reasons have been given in various related forms: 'my long experience 
tells me its bad', 'you may need the builtin later', 'you may forget 
that you rebound the builtin, 'it can lead to subtle bugs, etc.

Leaving aside the code writer and code operation, I recently discovered 
that it is not nice for readers, whether humans or programs.

For instance, open Lib/idlelib/GrepDialog.py in an editor that colorizes 
Python syntax, such as Idle's editor, jump down to the bottom and read 
up, and (until it is patched) find
                     list.append(fn)
with 'list' colored as a builtin. Stop. That looks wrong. List.append 
needs two arguments: a list instance and an object to append to the 
list. The 'solution' is in a previous line
         list = []
Reading further, one sees that the function works with two lists, a list 
of file names, unfortunately called 'list', and a list of 
subdirectories, more sensibly call 'subdirs'. I was initially confused 
and reading the code still takes a small bit of extra mental energy. 
Idle stays confused and will wrongly color the list instance name until 
it is changed. Calling the file list 'fnames' or 'filenames' would have 
been clearer to both me and Idle.

--
Terry Jan Reedy

[toc] | [next] | [standalone]


#47629

Fromrusi <rustompmody@gmail.com>
Date2013-06-10 19:36 -0700
Message-ID<dffd70ad-4e9a-45cd-914b-7f1388ded5a2@a9g2000pbq.googlegroups.com>
In reply to#47622
On Jun 11, 5:14 am, Terry Jan Reedy <tjre...@udel.edu> wrote:
> Many long-time posters have advised "Don't rebind built-in names*.
>
> * Unless you really mean to mask it, or more likely wrap it, such as
> wrapping print to modify some aspect of its operation than one cannot do
> with its keyword parameters. The point for this post is that such
> wrapping modify or extend the basic meaning of the builtin, but do not
> abolish it.
>
> Reasons have been given in various related forms: 'my long experience
> tells me its bad', 'you may need the builtin later', 'you may forget
> that you rebound the builtin, 'it can lead to subtle bugs, etc.
>
> Leaving aside the code writer and code operation, I recently discovered
> that it is not nice for readers, whether humans or programs.
>
> For instance, open Lib/idlelib/GrepDialog.py in an editor that colorizes
> Python syntax, such as Idle's editor, jump down to the bottom and read
> up, and (until it is patched) find
>                      list.append(fn)
> with 'list' colored as a builtin. Stop. That looks wrong. List.append
> needs two arguments: a list instance and an object to append to the
> list. The 'solution' is in a previous line
>          list = []
> Reading further, one sees that the function works with two lists, a list
> of file names, unfortunately called 'list', and a list of
> subdirectories, more sensibly call 'subdirs'. I was initially confused
> and reading the code still takes a small bit of extra mental energy.
> Idle stays confused and will wrongly color the list instance name until
> it is changed. Calling the file list 'fnames' or 'filenames' would have
> been clearer to both me and Idle.
>
> --
> Terry Jan Reedy

Pascal introduced the idea of block structure -- introduce a name at
one level, override it at a lower level. [Ok ALgol introduced, Pascal
popularized].
This has caused more trouble than it has solved. And so languages
nowadays tend to 'protect' against this feature.

Here is Erlang's 'sticky' feature
http://books.google.co.in/books?id=Qr_WuvfTSpEC&pg=PA181&lpg=PA181&dq=erlang+sticky+directory&source=bl&ots=aLZCjwzUFb&sig=DQiiQgzHCt5EtE5H3WY3bCWh4eM&hl=en&sa=X&ei=gYu2UbD6DMOMrQeNh4HYDA&ved=0CEAQ6AEwAw#v=onepage&q=erlang%20sticky%20directory&f=false
that prevents a programmer from overriding a builtin module unless he
explicitly asks for that.

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


#47633

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-06-11 03:02 +0000
Message-ID<51b69332$0$29997$c3e8da3$5496439d@news.astraweb.com>
In reply to#47629
On Mon, 10 Jun 2013 19:36:44 -0700, rusi wrote:

> Pascal introduced the idea of block structure -- introduce a name at one
> level, override it at a lower level. [Ok ALgol introduced, Pascal
> popularized].
> This has caused more trouble than it has solved.

I take it you have never programmed in a programming language with a 
single, flat, global namespace? :-)


> And so languages nowadays tend to 'protect' against this feature.

Apart from Erlang, got any other examples? Because it seems to me that in 
languages with nested scopes or namespaces, shadowing higher levels is 
exactly the right thing to do. Certainly it would be a PITA, and defeat 
the purpose of having nested scopes, if inner names had to be globally 
unique. Wouldn't it be absolutely horrible if adding a global variable 
"foo"[1] suddenly meant that all your functions that used "foo" as a 
local variable stopped working?




[1] For some value of "foo".


-- 
Steven

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


#47634

Fromrusi <rustompmody@gmail.com>
Date2013-06-10 20:30 -0700
Message-ID<c4d6d80f-291e-43bc-b75e-ba8eb9bfee3a@li6g2000pbb.googlegroups.com>
In reply to#47633
On Jun 11, 8:02 am, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:
> On Mon, 10 Jun 2013 19:36:44 -0700, rusi wrote:
> > Pascal introduced the idea of block structure -- introduce a name at one
> > level, override it at a lower level. [Ok ALgol introduced, Pascal
> > popularized].
> > This has caused more trouble than it has solved.
>
> > And so languages nowadays tend to 'protect' against this feature.
>
> Apart from Erlang, got any other examples? Because it seems to me that in
> languages with nested scopes or namespaces, shadowing higher levels is
> exactly the right thing to do.

This is just opening up the definition of block-structure and saying
its a good thing.

> Certainly it would be a PITA, and defeat
> the purpose of having nested scopes, if inner names had to be globally
> unique. Wouldn't it be absolutely horrible if adding a global variable
> "foo"[1] suddenly meant that all your functions that used "foo" as a
> local variable stopped working?
>
> [1] For some value of "foo".

Your opinion.

Not so convincing if the sequence of composing the program was the
other-way-round:
if I have a global variable, say errno, and 'lose' it by introducing a
local variable errno.

And in fact for a reader of a program, the order of its writing should
not matter.
Which brings us pat into Terry's example.  [Also notice that changing
from a 'parametric-semantic' name like foo to a more 'fixed-semantic'
name like 'errno' or 'list' changes the desirability of this feature.

>
> I take it you have never programmed in a programming language with a
> single, flat, global namespace? :-)

Well Ive used Basic and Assembler -- which are fun in the way that
childhood and mountaineering respectively are fun.

What it seems you are not getting about Erlang's outlook about block-
structure is this: There are two separable aspects to it:
1. Names can be created in local scopes which dont leak into (more)
global scopes -- a desirable feature

2. Names in local scopes can override names in global scope -- a
dangerous feature [BTW which is what this thread is about].  And
Erlang's approach seems to be the most nuanced -- you can do it if you
go out of your way to say: "unstick the global namespace".

This is somewhat analogous to gotos in Pascal. For Pascal goto was a
sufficiently undesirable feature that using it was not completely
easy.  However if you did surely want it, you had to declare the goto
label.

Or by example:

def foo(x)...
def bar(x,y)...
there is no reason to confuse the two xes.

Whereas

x = ...
def foo(x)...
Now there is!

The first should be encouraged, the second discouraged.

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


#47638

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-06-11 05:52 +0000
Message-ID<51b6bb00$0$11095$c3e8da3@news.astraweb.com>
In reply to#47634
On Mon, 10 Jun 2013 20:30:41 -0700, rusi wrote:

>> Certainly it would be a PITA, and defeat the purpose of having nested
>> scopes, if inner names had to be globally unique. Wouldn't it be
>> absolutely horrible if adding a global variable "foo"[1] suddenly meant
>> that all your functions that used "foo" as a local variable stopped
>> working?
>>
>> [1] For some value of "foo".
> 
> Your opinion.

Well duh :-)

Mind you, I don't hear very many people *defending* the idea that local 
variables should be globally unique, or designing languages where this is 
the case. So if it's just an opinion, it's an opinion shared by the 
majority of programmers and language designers.


> Not so convincing if the sequence of composing the program was the
> other-way-round:
> if I have a global variable, say errno, and 'lose' it by introducing a
> local variable errno.

The consequences of inadvertent local-shadows-global are *much* less than 
the other way around. Any harm is local to the one function.

If you've shadowed a global with a local, there are two possibilities:

- You intended to shadow the global, in which case, good for you. I'm not 
going to past judgement and say you mustn't do this, so long as you're 
aware of what you're doing and have your reasons.

- You didn't intend to shadow the global, in which case you've just made 
a bug, and you'll soon find out and fix it.


> And in fact for a reader of a program, the order of its writing should
> not matter.

It doesn't. However, edits to working code can make it become non-
working. That's part of the business of being a programmer. Consider two 
scenarios:

- Add a local variable, and suddenly the function which you were editing 
stops working? Painful, but business as usual. At least you know that the 
bug exists within the function you just edited.

- Add a global variable, and suddenly dozens of functions all over the 
place stop working? Or worse, only a small handful of functions stop 
working, and you don't find out for a while. It's a lot harder to fix a 
bug caused by a new global shadowing your local when you might not even 
know that global exists.


> Which brings us pat into Terry's example.  [Also notice that changing
> from a 'parametric-semantic' name like foo to a more 'fixed-semantic'
> name like 'errno' or 'list' changes the desirability of this feature.

Absolutely! It makes the ability to shadow globals *more desirable*.

def myfunc(arg, list=list):
    do_this()
    do_that()
    return list(arg)


Now you have a nicely localised, safe, tame monkey-patch, without 
compromising on the best name for "list".


>> I take it you have never programmed in a programming language with a
>> single, flat, global namespace? :-)
> 
> Well Ive used Basic and Assembler -- which are fun in the way that
> childhood and mountaineering respectively are fun.
> 
> What it seems you are not getting about Erlang's outlook about block-
> structure is this: There are two separable aspects to it: 1. Names can
> be created in local scopes which dont leak into (more) global scopes --
> a desirable feature

I can see that it is desirable, although I don't know how this works in 
practice in Erland. If you have a global x, and a local x, how do you 
refer to them both?

x = x 

Which one is which?


> 2. Names in local scopes can override names in global scope -- a
> dangerous feature [BTW which is what this thread is about].  And
> Erlang's approach seems to be the most nuanced -- you can do it if you
> go out of your way to say: "unstick the global namespace".

I can see that this is also desirable, especially in a more "bondage and 
discipline" language that makes you ask permission before doing anything. 
I don't think it is desirable *in Python*, which is a lot more laisse 
faire.


> This is somewhat analogous to gotos in Pascal. For Pascal goto was a
> sufficiently undesirable feature that using it was not completely easy. 
> However if you did surely want it, you had to declare the goto label.
> 
> Or by example:
> 
> def foo(x)...
> def bar(x,y)...
> there is no reason to confuse the two xes.
> 
> Whereas
> 
> x = ...
> def foo(x)...
> Now there is!
> 
> The first should be encouraged, the second discouraged.

Discouraging it means telling people that every time they need a local 
variable, they should consider the entire global environment before 
choosing a name. I call that bogus. Why shouldn't I call a local variable 
"id" if that's the best name for it, just because there's a global "id" 
that hardly anyone ever uses? If there's a global "x", and my function 
doesn't use it, why shouldn't it reuse "x" for a local if "x" is the best 
name in context?

Shadowing has both uses and abuses, pros and cons, and there's no doubt 
that it can be confusing to beginners. There are arguments against it, 
and I agree with them. But there are also arguments in favour, and I 
agree with them too. A good programmer[1] will weigh up the pros and cons 
of "use the most readable, descriptive name for the variable" versus 
"shadow a global or built-in with the same name" and decide on the merits 
of the specific case in question -- should I use a less-appropriate name 
("mylist", blah) in the interest of not confusing some readers, or the 
right name but risk shadowing a name in a higher scope?

Python takes a very hands-off approach to this. Other languages are more 
in-your-face. There is room in the world for both philosophies.



[1] In my opinion of good *wink*


-- 
Steven

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


#47791

FromChris Angelico <rosuav@gmail.com>
Date2013-06-11 17:20 +1000
Message-ID<mailman.3097.1371040064.3114.python-list@python.org>
In reply to#47634
On Tue, Jun 11, 2013 at 1:30 PM, rusi <rustompmody@gmail.com> wrote:
> Or by example:
>
> def foo(x)...
> def bar(x,y)...
> there is no reason to confuse the two xes.
>
> Whereas
>
> x = ...
> def foo(x)...
> Now there is!
>
> The first should be encouraged, the second discouraged.

Again, there can be good reason for it, such as snapshotting globals:

qwer=123
def asdf(qwer=qwer):
	print("qwer",qwer)

asdf()
qwer=234
asdf()

Done for performance (avoiding lookups), could also be done for
stability (as depicted here) though I've never seen it needed for
that.

ChrisA

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


#47635

FromChris Angelico <rosuav@gmail.com>
Date2013-06-11 13:57 +1000
Message-ID<mailman.3007.1370923032.3114.python-list@python.org>
In reply to#47633
On Tue, Jun 11, 2013 at 1:02 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Apart from Erlang, got any other examples? Because it seems to me that in
> languages with nested scopes or namespaces, shadowing higher levels is
> exactly the right thing to do. Certainly it would be a PITA, and defeat
> the purpose of having nested scopes, if inner names had to be globally
> unique.

I agree, and it's one of the reasons that I like the explicitness of
C's variable declarations. Sure, Python makes it easier to write code;
but it's easier to figure out what's a global and what's not when
locals are all declared. (Yes, it's not that hard for a human to
recognize when a name is being rebound as opposed to merely used, but
it's extra work for a lexer/syntax highlighter.)

ChrisA

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


#47670

FromSerhiy Storchaka <storchaka@gmail.com>
Date2013-06-11 18:55 +0300
Message-ID<mailman.3025.1370966138.3114.python-list@python.org>
In reply to#47633
11.06.13 06:02, Steven D'Aprano написав(ла):
> On Mon, 10 Jun 2013 19:36:44 -0700, rusi wrote:
>> And so languages nowadays tend to 'protect' against this feature.
>
> Apart from Erlang, got any other examples?

C#? At least local variable can't shadow other local variable in outer 
scope (and it looks reasonable). I'm not sure about globals and instance 
fields.

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


#47863

FromMark Janssen <dreamingforward@gmail.com>
Date2013-06-12 17:04 -0700
Message-ID<mailman.3143.1371081895.3114.python-list@python.org>
In reply to#47633
>> This has caused more trouble than it has solved.
>
> I take it you have never programmed in a programming language with a
> single, flat, global namespace? :-)

Hey, the purpose a programming language (i.e. a language which has a
consistent lexical specification), is to provide some modicum of
structure.  Yes, that implies that you're implicitly following a
language designers tacit philosophy (their "ObjectArchitecture") for
relating data to computers, but that's fine.  People always have the
option of going back to assembly and starting over.

> Apart from Erlang, got any other examples? Because it seems to me that in
> languages with nested scopes or namespaces, shadowing higher levels is
> exactly the right thing to do.

Really?

>>> int="five"
>>> [int(i) for i in ["1","2","3"]]
TypeError:  str is not callable

Now how are you going to get the original int type back?

> Certainly it would be a PITA, and defeat
> the purpose of having nested scopes, if inner names had to be globally
> unique. Wouldn't it be absolutely horrible if adding a global variable
> "foo"[1] suddenly meant that all your functions that used "foo" as a
> local variable stopped working?

Not necessarily, but this is what I'm talking about in defining a
ObjectArchitecture (or in some circles a "type system").
-- 
MarkJ
Tacoma, Washington

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


#47875

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-06-13 01:01 +0000
Message-ID<51b919d7$0$29997$c3e8da3$5496439d@news.astraweb.com>
In reply to#47863
On Wed, 12 Jun 2013 17:04:48 -0700, Mark Janssen wrote:

>> Apart from Erlang, got any other examples? Because it seems to me that
>> in languages with nested scopes or namespaces, shadowing higher levels
>> is exactly the right thing to do.
> 
> Really?
> 
>>>> int="five"
>>>> [int(i) for i in ["1","2","3"]]
> TypeError:  str is not callable

Yes, really. Not for the example shown above, of course, that's pretty 
useless. But one might define a custom int() function, or more common, 
you want to define a local variable x without caring whether or not there 
is a global variable x.

If you, the programmer, have a good reason for re-defining int as the 
string "five", then presumably you *wanted* to get that TypeError. If 
not, then it's simply a bug, like any other bug: that you get when you 
use the wrong name:

x = 23  # I want x to equal 23, always and forever.
x = 42  # I don't actually want to rebind x, but I can't help myself.
assert x == 23  # This now fails, because I am an idiot.

Should we conclude that, because somebody might accidentally assign a 
value to a name without considering the consequences, that assigning 
values to names should be forbidden? No, of course not. The solution is 
to think before you code, or fix the bug afterwards.

Shadowing builtins is confusing to newbies, I get that. But anyone with 
even a modicum of experience will be able to deal with such errors 
trivially. If you (generic you) cannot work out what is going on, then 
you're not a Python programmer. You're a Python dabbler.


> Now how are you going to get the original int type back?

Trivial. Here are three ways:

py> int = "five"
py> int
'five'
py> del int
py> int("42")
42


Or:

py> int = "five"
py> int
'five'
py> type(5)("42")
42


Or:

py> int = "five"
py> import builtins  # Use __builtin__ in Python 2.
py> builtins.int("42")
42



-- 
Steven

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


#47865

FromChris Angelico <rosuav@gmail.com>
Date2013-06-13 10:08 +1000
Message-ID<mailman.3145.1371082102.3114.python-list@python.org>
In reply to#47633
On Thu, Jun 13, 2013 at 10:04 AM, Mark Janssen
<dreamingforward@gmail.com> wrote:
> Really?
>
>>>> int="five"
>>>> [int(i) for i in ["1","2","3"]]
> TypeError:  str is not callable
>
> Now how are you going to get the original int type back?

Either del it from your module namespace, or use the qualified name:

>>> int="five"
>>> [__builtins__.int(i) for i in ["1","2","3"]]
[1, 2, 3]
>>> del int
>>> [int(i) for i in ["1","2","3"]]
[1, 2, 3]

It's shadowed, not overwritten.

ChrisA

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


#47877

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-06-13 01:08 +0000
Message-ID<51b91b89$0$29997$c3e8da3$5496439d@news.astraweb.com>
In reply to#47865
On Thu, 13 Jun 2013 10:08:14 +1000, Chris Angelico wrote:

>>>> int="five"
>>>> [__builtins__.int(i) for i in ["1","2","3"]]

Don't use __builtins__, it's an implementation detail.

In Python 2.x, there is __builtins__ with an "s" in the global namespace 
if you are running CPython, but not necessarily other implementations. 
There is __builtin__ with no "s" which is defined by the language, but 
you have to import it first.

In Python 3.x, you just import builtins with an "s" and no underscores, 
no matter what implementation you use.


> It's shadowed, not overwritten.

But even if you override it, you can get it back:


py> import builtins
py> builtins.int = "five"  # My monkey has a patch.
py> int("42")  # Oh-oh, trouble ahead
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
py> builtins.int = type(5)
py> int("42")
42


It may not be quite so simple to recover from *all* such monkey-patches, 
but you can always exit Python, edit your code, and start it up again. 
It's not like you've patched the actual compiler.



-- 
Steven

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


#47882

FromChris Angelico <rosuav@gmail.com>
Date2013-06-13 11:30 +1000
Message-ID<mailman.3151.1371087004.3114.python-list@python.org>
In reply to#47877
On Thu, Jun 13, 2013 at 11:08 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> On Thu, 13 Jun 2013 10:08:14 +1000, Chris Angelico wrote:
>
>>>>> int="five"
>>>>> [__builtins__.int(i) for i in ["1","2","3"]]
>
> Don't use __builtins__, it's an implementation detail.
>
> In Python 2.x, there is __builtins__ with an "s" in the global namespace
> if you are running CPython, but not necessarily other implementations.
> There is __builtin__ with no "s" which is defined by the language, but
> you have to import it first.
>
> In Python 3.x, you just import builtins with an "s" and no underscores,
> no matter what implementation you use.

Oh, sorry, my bad. I tend to just whip something up in IDLE and see if
it works, rather than actually check the spec. Listen to Steven, he
knows what he's about!

ChrisA

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


#47867

FromSkip Montanaro <skip@pobox.com>
Date2013-06-12 19:18 -0500
Message-ID<mailman.3146.1371082709.3114.python-list@python.org>
In reply to#47633
>>> int="five"
>>> [int(i) for i in ["1","2","3"]]
TypeError:  str is not callable

> Now how are you going to get the original int type back?

Magic. :-)

>>> int = "five"
>>> int("a")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> from __builtin__ import int as _int
>>> _int("5")
5

Not sure of the magic necessary in Python 3.  This is definitely
something you don't want to make a habit of...

S

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


#47872

FromChris Angelico <rosuav@gmail.com>
Date2013-06-13 10:33 +1000
Message-ID<mailman.3149.1371083614.3114.python-list@python.org>
In reply to#47633
On Thu, Jun 13, 2013 at 10:18 AM, Skip Montanaro <skip@pobox.com> wrote:
> Magic. :-)
>
>>>> int = "five"
>>>> int("a")
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: 'str' object is not callable
>>>> from __builtin__ import int as _int
>>>> _int("5")
> 5
>
> Not sure of the magic necessary in Python 3.  This is definitely
> something you don't want to make a habit of...

Same thing works but with a different name:

from builtins import int as _int

ChrisA

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


#47876

FromEthan Furman <ethan@stoneleaf.us>
Date2013-06-12 17:30 -0700
Message-ID<mailman.3150.1371084703.3114.python-list@python.org>
In reply to#47633
On 06/12/2013 05:04 PM, Mark Janssen wrote:
> Steven D'Aprono wrote:
>>
>> Apart from Erlang, got any other examples? Because it seems to me that in
>> languages with nested scopes or namespaces, shadowing higher levels is
>> exactly the right thing to do.
>
> Really?
>
>--> int="five"
>--> [int(i) for i in ["1","2","3"]]
> TypeError:  str is not callable
>
> Now how are you going to get the original int type back?

--> del int

Mark Janssen*, you would increase your credibility if you actually *learned* Python.

--
~Ethan~

*full name used to distinguish from at least one other Mark on the list.

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


#47632

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-06-11 02:56 +0000
Message-ID<51b691ea$0$29997$c3e8da3$5496439d@news.astraweb.com>
In reply to#47622
On Mon, 10 Jun 2013 20:14:55 -0400, Terry Jan Reedy wrote:

> For instance, open Lib/idlelib/GrepDialog.py in an editor that colorizes
> Python syntax, such as Idle's editor, jump down to the bottom and read
> up, and (until it is patched) find
>                      list.append(fn)
> with 'list' colored as a builtin. Stop. That looks wrong. List.append
> needs two arguments: a list instance and an object to append to the
> list. The 'solution' is in a previous line
>          list = []
> Reading further, one sees that the function works with two lists, a list
> of file names, unfortunately called 'list', and a list of
> subdirectories, more sensibly call 'subdirs'. 

Yes, that is a poor choice of names.

But sometimes you are dealing with a generic list, and calling it 
"filenames" would be equally inappropriate :-)


> I was initially confused
> and reading the code still takes a small bit of extra mental energy.
> Idle stays confused and will wrongly color the list instance name until
> it is changed. Calling the file list 'fnames' or 'filenames' would have
> been clearer to both me and Idle.

Correct. The downside of editors that colourise text is that sometimes 
they colourise it wrong. In this case, how is the editor supposed to know 
that list no longer refers to the built-in list?

This is yet another good argument for being cautious about shadowing 
built-ins.



-- 
Steven

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


#47639

FromTerry Jan Reedy <tjreedy@udel.edu>
Date2013-06-11 02:06 -0400
Message-ID<mailman.3008.1370930788.3114.python-list@python.org>
In reply to#47632
On 6/10/2013 10:56 PM, Steven D'Aprano wrote:

>> I was initially confused
>> and reading the code still takes a small bit of extra mental energy.
>> Idle stays confused and will wrongly color the list instance name until
>> it is changed. Calling the file list 'fnames' or 'filenames' would have
>> been clearer to both me and Idle.
>
> Correct. The downside of editors that colourise text is that sometimes
> they colourise it wrong. In this case, how is the editor supposed to know
> that list no longer refers to the built-in list?
>
> This is yet another good argument for being cautious about shadowing
> built-ins.

After posting I remembered that there are also colorized text blocks on 
web pages. Each person will have to decide for themselves whether the 
convenience of reusing a builtin name is worth having their code 
mis-colorized. As a reader, I decided that it is not.

tjr


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


#47664

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-06-11 08:22 -0700
Message-ID<1c2d7554-b7f0-4576-9169-3427a876bb5e@googlegroups.com>
In reply to#47632
On Monday, June 10, 2013 9:56:43 PM UTC-5, Steven D'Aprano wrote:
> On Mon, 10 Jun 2013 20:14:55 -0400, Terry Jan Reedy wrote:
> > For instance, open Lib/idlelib/GrepDialog.py in an editor that colorizes
> > Python syntax, such as Idle's editor, jump down to the bottom and read
> > up, and (until it is patched) find
> >                      list.append(fn)
> > with 'list' colored as a builtin. Stop. That looks wrong. List.append
> > needs two arguments: a list instance and an object to append to the
> > list. The 'solution' is in a previous line
> >          list = []
> > Reading further, one sees that the function works with two lists, a list
> > of file names, unfortunately called 'list', and a list of
> > subdirectories, more sensibly call 'subdirs'. 
> Yes, that is a poor choice of names. But sometimes you are
> dealing with a generic list, and calling it "filenames"
> would be equally inappropriate :-)

I agree, however hopefully you're joking, because in the past you've argued that programmers should never use variables as generic as "list", "string", "integer", "float", etc... even though there are instances when all you need to know is what type your working with.

> > I was initially confused
> > and reading the code still takes a small bit of extra mental energy.
> > Idle stays confused and will wrongly color the list instance name until
> > it is changed. Calling the file list 'fnames' or 'filenames' would have
> > been clearer to both me and Idle.
> Correct. The downside of editors that colourise text is
> that sometimes they colourise it wrong. 

One of the most important side-effects of using an editor with colorizing capabilities is to show you that you're using a built-in or keyword as a variable! I love when people comment on subjects they have no direct experience with, like for instance, you commenting on colonizers or GUI's -- LOL!

> In this case, how is the editor supposed to know that list
> no longer refers to the built-in list? 

Colonizers should ALWAYS colorize built-in (as built-in symbols) symbols EXCEPT when that symbol is part of a string or comment. 

> This is yet another good argument for being cautious about
> shadowing built- ins.

In a language designed like Python, yes. Unfortunately Python not only decided to expose built-in functions for constructing types instead of class identifiers, they also stole the best generic names! 

Sometimes all you need to know is the type of an object, not what it contains. I remember someone *cough-steven* talking about duck typing and how great it was to just treat a duck like a duck. Well, here we find ourselves treating a list like a list and your taking the opposite argument... why am i not surprised?

PS: Is that "D" in last name short for "DevilsAdvocate"? Steven "DevilsAdvocate" Prano.

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


#47679

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-06-11 16:59 +0000
Message-ID<51b75782$0$29997$c3e8da3$5496439d@news.astraweb.com>
In reply to#47664
On Tue, 11 Jun 2013 08:22:19 -0700, Rick Johnson wrote:

> On Monday, June 10, 2013 9:56:43 PM UTC-5, Steven D'Aprano wrote:
>> On Mon, 10 Jun 2013 20:14:55 -0400, Terry Jan Reedy wrote:

>> > Reading further, one sees that the function works with two lists, a
>> > list of file names, unfortunately called 'list', and a list of
>> > subdirectories, more sensibly call 'subdirs'.
>>
>> Yes, that is a poor choice of names. But sometimes you are dealing with
>> a generic list, and calling it "filenames" would be equally
>> inappropriate :-)
> 
> I agree, however hopefully you're joking, because in the past you've
> argued that programmers should never use variables as generic as "list",
> "string", "integer", "float", etc... even though there are instances
> when all you need to know is what type your working with.

Do you have a reference for me saying that one should NEVER use generic 
names? That doesn't sound like something I would say. Sometimes you're 
writing a generic function that operates on a generic variable in a 
generic fashion, so of course you should use a generic name.


> One of the most important side-effects of using an editor with
> colorizing capabilities is to show you that you're using a built-in or
> keyword as a variable! 

I wouldn't exactly call it a "side-effect", since distinguishing tokens 
in your source code by category is the whole purpose of colouring source 
code in the first place.


> I love when people comment on subjects they have
> no direct experience with, like for instance, you commenting on
> colonizers or GUI's -- LOL!

I must admit I have no experience with colonizers, although of course I 
do have a colon of my very own. It works away absorbing water and 
nutrients without my active supervision.


-- 
Steven

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


Page 1 of 2  [1] 2  Next page →

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


csiph-web