Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #86592 > unrolled thread
| Started by | Travis Griggs <travisgriggs@gmail.com> |
|---|---|
| First post | 2015-02-27 13:21 -0800 |
| Last post | 2015-03-01 13:29 +1300 |
| Articles | 20 on this page of 27 — 15 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Python Worst Practices Travis Griggs <travisgriggs@gmail.com> - 2015-02-27 13:21 -0800
Re: Python Worst Practices Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-02-28 12:09 +1100
Re: Python Worst Practices sohcahtoa82@gmail.com - 2015-02-27 17:32 -0800
Re: Python Worst Practices Chris Angelico <rosuav@gmail.com> - 2015-02-28 12:44 +1100
Re: Python Worst Practices Christian Gollwitzer <auriocus@gmx.de> - 2015-03-03 09:51 +0100
Re: Python Worst Practices Chris Angelico <rosuav@gmail.com> - 2015-03-03 22:12 +1100
Re: Python Worst Practices Christian Gollwitzer <auriocus@gmx.de> - 2015-03-03 23:46 +0100
Re: Python Worst Practices Chris Angelico <rosuav@gmail.com> - 2015-03-04 10:12 +1100
Re: Python Worst Practices Christian Gollwitzer <auriocus@gmx.de> - 2015-03-04 21:27 +0100
Re: Python Worst Practices Dan Sommers <dan@tombstonezero.net> - 2015-02-28 04:42 +0000
Re: Python Worst Practices Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-02-28 17:36 +1100
Re: Python Worst Practices Dan Sommers <dan@tombstonezero.net> - 2015-02-28 07:50 +0000
Re: Python Worst Practices Chris Angelico <rosuav@gmail.com> - 2015-02-28 19:55 +1100
Re: Python Worst Practices Ethan Furman <ethan@stoneleaf.us> - 2015-02-27 23:51 -0800
Re: Python Worst Practices Marko Rauhamaa <marko@pacujo.net> - 2015-02-28 10:50 +0200
Re: Python Worst Practices Ian Kelly <ian.g.kelly@gmail.com> - 2015-02-28 01:48 -0700
Re: Python Worst Practices Chris Angelico <rosuav@gmail.com> - 2015-02-28 19:58 +1100
Re: Python Worst Practices Tim Chase <python.list@tim.thechases.com> - 2015-02-27 21:50 -0600
Re: Python Worst Practices Cousin Stanley <cousinstanley@gmail.com> - 2015-02-28 09:03 -0700
Re: Python Worst Practices Rustom Mody <rustompmody@gmail.com> - 2015-02-28 08:16 -0800
Re: Python Worst Practices MRAB <python@mrabarnett.plus.com> - 2015-02-28 17:56 +0000
Re: Python Worst Practices Ethan Furman <ethan@stoneleaf.us> - 2015-02-28 10:13 -0800
Re: Python Worst Practices Tim Chase <python.list@tim.thechases.com> - 2015-02-28 12:30 -0600
Re: Python Worst Practices Tim Chase <python.list@tim.thechases.com> - 2015-02-28 12:39 -0600
Re: Python Worst Practices BartC <bc@freeuk.com> - 2015-02-28 10:39 +0000
Re: Python Worst Practices Chris Angelico <rosuav@gmail.com> - 2015-02-28 23:45 +1100
Re: Python Worst Practices Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2015-03-01 13:29 +1300
Page 1 of 2 [1] 2 Next page →
| From | Travis Griggs <travisgriggs@gmail.com> |
|---|---|
| Date | 2015-02-27 13:21 -0800 |
| Subject | Re: Python Worst Practices |
| Message-ID | <mailman.19318.1425072098.18130.python-list@python.org> |
> On Feb 25, 2015, at 12:45 PM, Mark Lawrence <breamoreboy@yahoo.co.uk> wrote: > > http://www.slideshare.net/pydanny/python-worst-practices > > Any that should be added to this list? Any that be removed as not that bad? I read ‘em. I thought they were pretty good, some more than others. And I learned some things. I especially liked the first one, since I’ve struggled with that one a bunch. In the context of “hey, accept Python for what it is”, I agree greatly with it. Memorize the builtins, and stay the heck away from them. I’ve been burned many times because I stored some bytes in a binding call, er, uh, ‘bytes’. And having mentored some people learning Python in the early stages, any explanation other than “Thou Shalt Never Use These Holy Words” just confuses people. That said… If I were giving a talk at SPLASH (or some other suitable polyglot conference), I might do one called “Language Design Worst Practices”. One of my first slides might be titled: Abuse Common Tokens in Confusing Ways * Make your language have a lot of keywords. Enough to make memorizing them ALL unlikely, requiring constant visits to your documentation * Make sure said keywords are many of the obvious words programmers would use in their applications (map, object, bytes, dir, etc) * Design your syntax so that you can’t disambiguate them contextually between bind and reference * Be sure to use it in a late bound language where no warnings will be provided about the mistake you’re making at authorship time, deferring the educational experience to sundry run times In my examples column of this bad practice, I’d put Python of course. :) I do like Python, and I accept it for what it is, so no one needs to jump forward as a Holy Python See to convert me to the truth. I also know that with most other languages, that first slide wouldn’t need to be one of the prominent “worst practices” slide.
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2015-02-28 12:09 +1100 |
| Message-ID | <54f1154c$0$12985$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #86592 |
Travis Griggs wrote:
> If I were giving a talk at SPLASH (or some other suitable polyglot
> conference), I might do one called “Language Design Worst Practices”.
>
> One of my first slides might be titled:
>
> Abuse Common Tokens in Confusing Ways
>
> * Make your language have a lot of keywords. Enough to make memorizing
> them ALL unlikely, requiring constant visits to your documentation
Is 33 a lot?
py> import keyword
py> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class',
'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for',
'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal',
'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
> * Make sure said keywords are many of the obvious words programmers would
> use in their applications (map, object, bytes, dir, etc)
Luckily, Python doesn't make that mistake of making built-ins keywords. That
would require making actual changes to the parser each time a new built-in
function was added, as well as breaking people's existing code.
Fortunately, Python has a much better system: a small set of keywords, very
few of which would make useful variable names ("else = 23"), and a much
larger set of regular names in a built-in namespace.
py> import builtins # use __builtin__ in Python 2
py> sorted(vars(builtins).keys())
['ArithmeticError', 'AssertionError', ... 'type', 'vars', 'zip']
There's 147 of the built-ins in Python 3.3, although a few of those aren't
truly built-in, merely added at interpreter startup.
The ability to shadow built-ins is not a bug, it is a feature. It's an
amazingly powerful feature, and not particularly newbie-friendly, but
*many* things are not easy for newbies to master or avoid abusing.
- Code can override, or overload, built-ins, either at the level of
an entire module, or inside a particular function.
- Modules can offer functions which clash with a built-in name.
E.g. reprlib.repr, math.pow.
- More importantly, modules can offer stable APIs with no fear that
the introduction of a new built-in function will require them to
change their function's name.
- Which is a special case of a more general benefit, the introduction
of a new built-in name does *not* break existing code that already
uses that name.
Newbies misuse this feature because they still have a wishful-thinking
approach to programming. One example of wishful-thinking is the common
newbie mistake of wondering why their loop variable never changes:
# Toss a coin until you get Tails.
x = random.random()
while x < 0.5:
print "Heads"
print "Tails"
Isn't it obvious that I want x to get a new random number every time through
the loop? I wish the computer understood me so I didn't need to write all
the steps out.
Likewise:
int = 23
n = int("42")
Isn't it obvious that the second use of int has to be the built-in function?
I wish that the computer would understand from context which one I mean.
Other newbie stylistic mistakes which can increase the chance of shadowing
errors include:
* Too many overly generic variable names like "int" and "str".
* Insufficient use of functions and too much top-level code. When they
shadow a built-in, they shadow it everywhere.
* Excessively large functions that do too much. By the time they reach
the end of their 300 line function, they have forgotten that they
have already used "list" for a variable name.
However, even experienced developers can make this mistake too. Generally
speaking, it's trivially easy to recover from. Although if you're doing it
*regularly* that might be a hint of deeper problems, e.g. poor variable
naming skills, too much top-level code.
There's no harm in calling a local variable "id", if you don't use the
built-in id() inside that function. That's one of the reasons why functions
exist, so that the names you use inside a function are distinct from those
outside.
> * Design your syntax so that you can’t disambiguate them contextually
> between bind and reference
Do you have an example of where Python cannot distinguish between a binding
operation and a reference?
> * Be sure to use it in a late bound language where no warnings will be
> provided about the mistake you’re making at authorship time, deferring the
> educational experience to sundry run times
Python raises a SyntaxError at compile time, not run time, if you try to
bind to a keyword:
py> global = 23
File "<stdin>", line 1
global = 23
^
SyntaxError: invalid syntax
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | sohcahtoa82@gmail.com |
|---|---|
| Date | 2015-02-27 17:32 -0800 |
| Message-ID | <d975f577-03e4-4125-97ee-853a8e177e0f@googlegroups.com> |
| In reply to | #86604 |
On Friday, February 27, 2015 at 5:09:49 PM UTC-8, Steven D'Aprano wrote:
> Travis Griggs wrote:
>
> > If I were giving a talk at SPLASH (or some other suitable polyglot
> > conference), I might do one called "Language Design Worst Practices".
> >
> > One of my first slides might be titled:
> >
> > Abuse Common Tokens in Confusing Ways
> >
> > * Make your language have a lot of keywords. Enough to make memorizing
> > them ALL unlikely, requiring constant visits to your documentation
>
> Is 33 a lot?
>
> py> import keyword
> py> keyword.kwlist
> ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class',
> 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for',
> 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal',
> 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
>
>
> > * Make sure said keywords are many of the obvious words programmers would
> > use in their applications (map, object, bytes, dir, etc)
>
> Luckily, Python doesn't make that mistake of making built-ins keywords. That
> would require making actual changes to the parser each time a new built-in
> function was added, as well as breaking people's existing code.
>
> Fortunately, Python has a much better system: a small set of keywords, very
> few of which would make useful variable names ("else = 23"), and a much
> larger set of regular names in a built-in namespace.
>
>
> py> import builtins # use __builtin__ in Python 2
> py> sorted(vars(builtins).keys())
> ['ArithmeticError', 'AssertionError', ... 'type', 'vars', 'zip']
>
>
> There's 147 of the built-ins in Python 3.3, although a few of those aren't
> truly built-in, merely added at interpreter startup.
>
> The ability to shadow built-ins is not a bug, it is a feature. It's an
> amazingly powerful feature, and not particularly newbie-friendly, but
> *many* things are not easy for newbies to master or avoid abusing.
>
> - Code can override, or overload, built-ins, either at the level of
> an entire module, or inside a particular function.
>
> - Modules can offer functions which clash with a built-in name.
> E.g. reprlib.repr, math.pow.
>
> - More importantly, modules can offer stable APIs with no fear that
> the introduction of a new built-in function will require them to
> change their function's name.
>
> - Which is a special case of a more general benefit, the introduction
> of a new built-in name does *not* break existing code that already
> uses that name.
>
>
> Newbies misuse this feature because they still have a wishful-thinking
> approach to programming. One example of wishful-thinking is the common
> newbie mistake of wondering why their loop variable never changes:
>
> # Toss a coin until you get Tails.
> x = random.random()
> while x < 0.5:
> print "Heads"
> print "Tails"
>
> Isn't it obvious that I want x to get a new random number every time through
> the loop? I wish the computer understood me so I didn't need to write all
> the steps out.
>
>
> Likewise:
>
> int = 23
> n = int("42")
>
> Isn't it obvious that the second use of int has to be the built-in function?
> I wish that the computer would understand from context which one I mean.
>
> Other newbie stylistic mistakes which can increase the chance of shadowing
> errors include:
>
> * Too many overly generic variable names like "int" and "str".
>
> * Insufficient use of functions and too much top-level code. When they
> shadow a built-in, they shadow it everywhere.
>
> * Excessively large functions that do too much. By the time they reach
> the end of their 300 line function, they have forgotten that they
> have already used "list" for a variable name.
>
>
> However, even experienced developers can make this mistake too. Generally
> speaking, it's trivially easy to recover from. Although if you're doing it
> *regularly* that might be a hint of deeper problems, e.g. poor variable
> naming skills, too much top-level code.
>
> There's no harm in calling a local variable "id", if you don't use the
> built-in id() inside that function. That's one of the reasons why functions
> exist, so that the names you use inside a function are distinct from those
> outside.
>
>
>
> > * Design your syntax so that you can't disambiguate them contextually
> > between bind and reference
>
> Do you have an example of where Python cannot distinguish between a binding
> operation and a reference?
>
>
> > * Be sure to use it in a late bound language where no warnings will be
> > provided about the mistake you're making at authorship time, deferring the
> > educational experience to sundry run times
>
> Python raises a SyntaxError at compile time, not run time, if you try to
> bind to a keyword:
>
> py> global = 23
> File "<stdin>", line 1
> global = 23
> ^
> SyntaxError: invalid syntax
>
>
>
>
> --
> Steven
Very well-said!
Just because a feature (In this case, shadowing built-in functions) can be abused or cause problems doesn't mean it's a bad feature.
It reminds me of the people that rip on C++'s operator overloading because some people write bad code and implement non-intuitive operators for classes.
For example, I've seen someone create a Socket class, then created an operator overload that allowed you to "add" a string to your socket to make the socket send the string, with the result being a status code indicating success or an error.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-02-28 12:44 +1100 |
| Message-ID | <mailman.19327.1425087893.18130.python-list@python.org> |
| In reply to | #86605 |
On Sat, Feb 28, 2015 at 12:32 PM, <sohcahtoa82@gmail.com> wrote: > For example, I've seen someone create a Socket class, then created an operator overload that allowed you to "add" a string to your socket to make the socket send the string, with the result being a status code indicating success or an error. > Why not left shift the socket by that string, the result being the original socket? At least that has precedent... ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Christian Gollwitzer <auriocus@gmx.de> |
|---|---|
| Date | 2015-03-03 09:51 +0100 |
| Message-ID | <md3sk8$4p8$1@dont-email.me> |
| In reply to | #86606 |
Am 28.02.15 um 02:44 schrieb Chris Angelico: > On Sat, Feb 28, 2015 at 12:32 PM, <sohcahtoa82@gmail.com> wrote: >> For example, I've seen someone create a Socket class, then created an operator overload that allowed you to "add" a string to your socket to make the socket send the string, with the result being a status code indicating success or an error. >> > > Why not left shift the socket by that string, the result being the > original socket? At least that has precedent... > Are you trying to pick on C++ streams? I could never understand why anybody has problems with an arrow << that means "put into the left thing" instead of "shift the bits to the left". How often do you use bitshift operations in your programs as opposed to output? Ot would be equally silly to complain, that in Python you divide a string by a tuple, and the modulus gives you a formatted string. Christian
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-03-03 22:12 +1100 |
| Message-ID | <mailman.11.1425381138.21433.python-list@python.org> |
| In reply to | #86832 |
On Tue, Mar 3, 2015 at 7:51 PM, Christian Gollwitzer <auriocus@gmx.de> wrote: > Am 28.02.15 um 02:44 schrieb Chris Angelico: >> On Sat, Feb 28, 2015 at 12:32 PM, <sohcahtoa82@gmail.com> wrote: >>> For example, I've seen someone create a Socket class, then created an operator overload that allowed you to "add" a string to your socket to make the socket send the string, with the result being a status code indicating success or an error. >>> >> >> Why not left shift the socket by that string, the result being the >> original socket? At least that has precedent... >> > > Are you trying to pick on C++ streams? I could never understand why > anybody has problems with an arrow << that means "put into the left > thing" instead of "shift the bits to the left". How often do you use > bitshift operations in your programs as opposed to output? Ot would be > equally silly to complain, that in Python you divide a string by a > tuple, and the modulus gives you a formatted string. I am, yes. Both your examples seem lovely and simple when you first look at them, but operator precedence means you get weird edge cases. In the case of string modulo, there's another edge case as a consequence of the operator being, by necessity, binary. A function call makes better sense here. Operator overloading in each case here is "cute", not optimally practical. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Christian Gollwitzer <auriocus@gmx.de> |
|---|---|
| Date | 2015-03-03 23:46 +0100 |
| Message-ID | <md5djb$rtf$1@dont-email.me> |
| In reply to | #86837 |
Am 03.03.15 um 12:12 schrieb Chris Angelico: > On Tue, Mar 3, 2015 at 7:51 PM, Christian Gollwitzer <auriocus@gmx.de> wrote: > >> Are you trying to pick on C++ streams? I could never understand why >> anybody has problems with an arrow << that means "put into the left >> thing" instead of "shift the bits to the left". How often do you use >> bitshift operations in your programs as opposed to output? Ot would be >> equally silly to complain, that in Python you divide a string by a >> tuple, and the modulus gives you a formatted string. > > I am, yes. Both your examples seem lovely and simple when you first > look at them, but operator precedence means you get weird edge cases. > In the case of string modulo, there's another edge case as a > consequence of the operator being, by necessity, binary. A function > call makes better sense here. I can agree with the argument that operator precedence can make problems; e.g. this cout<<a==b; does not output the truth value of a==b, but instead outputs a and compares the stream to b (which will usually fail to compile, but still). But the argument that << is a left-shift and nothing else is silly. << for bitshift is nothing more intuitive than % for modulus (where in math does this symbol occur?) or [] for indexing. We just got used to it, and to me << as an arrow for putting someting into a stream seems pretty obvious. > Operator overloading in each case here is "cute", not optimally practical. Maybe just sub-optimal? With today's C++ one could use a variadic template and still have type-safe compile-time bound output formatting. This hasn't been possible in the original iostream library back then. Christian
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-03-04 10:12 +1100 |
| Message-ID | <mailman.26.1425424342.21433.python-list@python.org> |
| In reply to | #86869 |
On Wed, Mar 4, 2015 at 9:46 AM, Christian Gollwitzer <auriocus@gmx.de> wrote:
> I can agree with the argument that operator precedence can make
> problems; e.g. this
>
> cout<<a==b;
>
> does not output the truth value of a==b, but instead outputs a and
> compares the stream to b (which will usually fail to compile, but still).
>
> But the argument that << is a left-shift and nothing else is silly. <<
> for bitshift is nothing more intuitive than % for modulus (where in math
> does this symbol occur?) or [] for indexing. We just got used to it, and
> to me << as an arrow for putting someting into a stream seems pretty
> obvious.
I don't mind the idea of << meaning something other than left-shift.
The problem comes usually when you try to use a binary operator in
place of a variadic function, and suddenly you need a pile of hacks to
get around operator overloading.
If you use << to add a flag to a flag-set (where the "flag-set" might
be an integer that retains bit-flags, or a set that retains strings,
or whatever), that would make reasonable sense. You take one thing on
the left, one thing on the right, and produce a result. (Or you'd use
<<= for that, which still looks fine. Then it does an assignment
instead of producing a result.)
If you create a Path object that responds to binary division with a
new Path that combines the left and right sides, that also makes very
good sense. The slash means "next path component" rather than
"divide", and it still is binary - there's no logical difference
between these:
Path("/etc") / "network" / "interfaces"
(Path("/etc") / "network") / "interfaces"
The problems come from needing more than two components at each step,
like with string formatting. You could write it like this:
"Hello, %s from %s!" % name % location
but then it'd be really hard to track down errors - the modulo
operator would have to handle the first percent sign and leave any
others unchanged. Plus there'd need to be some weird and funky magic
to mark the "current interpolation position" in order to cope with %%
becoming %, and the possibility that the person's name contains a
percent sign. No, string interpolation needs more than two arguments.
So either you have to mandatorially package the args up into an
iterable:
"Hello, %s from %s!" % (name, location)
which is very easy to forget (just look at what happens when you use
the Python DB API 2.0 and use "cur.execute(sql, single_argument)" -
you have to package that up into a one-tuple), or you have a special
case for non-tuple arguments, which is what Python has done. This is
great, except in the situation where you want to accept *any arbitrary
object* as your argument, eg for %r; you have to package that one up,
otherwise a tuple will behave very oddly. Hence, hacks on hacks to get
around the limitations of binary operators.
>> Operator overloading in each case here is "cute", not optimally practical.
>
> Maybe just sub-optimal? With today's C++ one could use a variadic
> template and still have type-safe compile-time bound output formatting.
> This hasn't been possible in the original iostream library back then.
I'm not sure how that would work, but the main question is: How is it
advantageous over a simple call? Actually, here's a simple way to do
it: Make the stream object callable.
cout("Hello, world!\n");
You can take as many args as you want, precedence and associativity
won't bite you, and it still reads reasonably well. The operator
method has to prove that it's better than that.
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Christian Gollwitzer <auriocus@gmx.de> |
|---|---|
| Date | 2015-03-04 21:27 +0100 |
| Message-ID | <md7pqj$uuu$1@dont-email.me> |
| In reply to | #86870 |
Am 04.03.15 um 00:12 schrieb Chris Angelico:
> The problems come from needing more than two components at each step,
> like with string formatting. You could write it like this:
>
> "Hello, %s from %s!" % name % location
>
> but then it'd be really hard to track down errors - the modulo
> operator would have to handle the first percent sign and leave any
> others unchanged. Plus there'd need to be some weird and funky magic
> to mark the "current interpolation position" in order to cope with %%
> becoming %, and the possibility that the person's name contains a
> percent sign.
boost::format does it like this, but not in a magic string processing
way as you desribe it. The string is parsed and some funny template
magic ensures that the arguments are inserted into it.
>>> Operator overloading in each case here is "cute", not optimally practical.
>>
>> Maybe just sub-optimal? With today's C++ one could use a variadic
>> template and still have type-safe compile-time bound output formatting.
>> This hasn't been possible in the original iostream library back then.
>
> I'm not sure how that would work, but the main question is: How is it
> advantageous over a simple call? Actually, here's a simple way to do
> it: Make the stream object callable.
>
> cout("Hello, world!\n");
Well variadic templates make it possible to do this:
string name="Chris";
int age=36;
cout("Hello ", name, "your age is ", age);
with any number of arguments of any (supported) type. This seems trivial
in Python, but is quite hard to do for a statically compiled language. A
type-safe printf-style function is one of the prime examples for
variadic templates: http://en.wikipedia.org/wiki/Variadic_template
> You can take as many args as you want, precedence and associativity
> won't bite you, and it still reads reasonably well. The operator
> method has to prove that it's better than that.
Agreed. The operator method was necessary in C++ because there simply
was no other way to create this interface. C++11 gained a lot more
features, but iostreams is still the thing from the very first design of
C++.
Christian
[toc] | [prev] | [next] | [standalone]
| From | Dan Sommers <dan@tombstonezero.net> |
|---|---|
| Date | 2015-02-28 04:42 +0000 |
| Message-ID | <mcrgvg$fjl$1@dont-email.me> |
| In reply to | #86604 |
On Sat, 28 Feb 2015 12:09:31 +1100, Steven D'Aprano wrote: > There's no harm in calling a local variable "id", if you don't use the > built-in id() inside that function. That's one of the reasons why functions > exist, so that the names you use inside a function are distinct from those > outside. And thank goodness for that! I've been writing Python code since 1997 and version 1.5.<something>,¹ and I still do a double take when emacs colors all my ids that faint blue that means "builtin." I don't think I've ever used the builtin function id in a program. Ever. Not even once. Honestly, what is a valid use case? That said, I do have boatloads of parameters and objects locally named id because it's idiomatic (at least to me) and mnemonic (at least to me) and just as meaningful. ¹ No, not continuously. I have eaten and slept since then.
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2015-02-28 17:36 +1100 |
| Message-ID | <54f161fd$0$12991$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #86607 |
Dan Sommers wrote:
> On Sat, 28 Feb 2015 12:09:31 +1100, Steven D'Aprano wrote:
>
>> There's no harm in calling a local variable "id", if you don't use the
>> built-in id() inside that function. That's one of the reasons why
>> functions exist, so that the names you use inside a function are distinct
>> from those outside.
>
> And thank goodness for that! I've been writing Python code since 1997
> and version 1.5.<something>,¹ and I still do a double take when emacs
> colors all my ids that faint blue that means "builtin."
Although it is not helpful for people using screen-readers, and may be of
limited use to the colour-blind, I am in favour of colourising built-ins so
they stand out.
On the other hand, I recall seeing an editor which rejected the idea of
colour-coding built-ins, keywords etc., instead it coloured your own
variables. So given:
spam = 23
eggs += cheese*len(sausage)
spam, eggs, cheese and sausage would be different colours. The idea being,
when scanning a large code base, all the places that use a specific
variable would stand out ("just look for the dark green word").
> I don't think I've ever used the builtin function id in a program.
> Ever. Not even once. Honestly, what is a valid use case?
Here's one. I think it's the only time I have seen id() used apart from
interactive experimentation:
https://code.activestate.com/recipes/577504
> That said, I
> do have boatloads of parameters and objects locally named id because
> it's idiomatic (at least to me) and mnemonic (at least to me) and just
> as meaningful.
>
> ¹ No, not continuously. I have eaten and slept since then.
Slacker!
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Dan Sommers <dan@tombstonezero.net> |
|---|---|
| Date | 2015-02-28 07:50 +0000 |
| Message-ID | <mcrrvo$qb4$1@dont-email.me> |
| In reply to | #86609 |
On Sat, 28 Feb 2015 17:36:44 +1100, Steven D'Aprano wrote:
> Dan Sommers wrote:
>> And thank goodness for that! I've been writing Python code since
>> 1997 and version 1.5.<something>,¹ and I still do a double take when
>> emacs colors all my ids that faint blue that means "builtin."
> Although it is not helpful for people using screen-readers, and may be
> of limited use to the colour-blind, I am in favour of colourising
> built-ins so they stand out.
Now if only emacs were clever enough *not* to colorize "id" when it's
one of my names and not the builtin... ;-)
> On the other hand, I recall seeing an editor which rejected the idea
> of colour-coding built-ins, keywords etc., instead it coloured your
> own variables. So given:
>
> spam = 23
> eggs += cheese*len(sausage)
>
> spam, eggs, cheese and sausage would be different colours. The idea
> being, when scanning a large code base, all the places that use a
> specific variable would stand out ("just look for the dark green
> word").
As a mostly visual person, I can see (pun intented) the logic and the
value in that. I wonder how many variables could be easily
distinguished, though, before running out of easily distinguishable
colors. Then again, a clever underlying algorithm might choose colors
based on *dissimilarity* of the identifiers, so that "i" and "j" would
be very diffent colors, but "spam" and "throat_warbler_mangrove" could
be the same color because they look so different anyway.
>> I don't think I've ever used the builtin function id in a program.
>> Ever. Not even once. Honestly, what is a valid use case?
>
> Here's one. I think it's the only time I have seen id() used apart from
> interactive experimentation:
>
> https://code.activestate.com/recipes/577504
Hah. Very nice. That sort of thing is probably useful for detecting
self-referential objects, too (e.g., to prevent infinite output for a
circular list).
>> ¹ No, not continuously. I have eaten and slept since then.
>
> Slacker!
Sorry. I'll make up the hours later, I promise!
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-02-28 19:55 +1100 |
| Message-ID | <mailman.19331.1425113719.18130.python-list@python.org> |
| In reply to | #86610 |
On Sat, Feb 28, 2015 at 6:50 PM, Dan Sommers <dan@tombstonezero.net> wrote: > Now if only emacs were clever enough *not* to colorize "id" when it's > one of my names and not the builtin... ;-) I think (part of) the point of the colorization is to make it obvious that you've shadowed a builtin. If you use << str = 'spam' >> in your code, the str should be highlighted. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ethan Furman <ethan@stoneleaf.us> |
|---|---|
| Date | 2015-02-27 23:51 -0800 |
| Message-ID | <mailman.19329.1425109954.18130.python-list@python.org> |
| In reply to | #86609 |
[Multipart message — attachments visible in raw view] — view raw
On 02/27/2015 10:36 PM, Steven D'Aprano wrote: > Dan Sommers wrote: > >> On Sat, 28 Feb 2015 12:09:31 +1100, Steven D'Aprano wrote: >> >>> There's no harm in calling a local variable "id", if you don't use the >>> built-in id() inside that function. That's one of the reasons why >>> functions exist, so that the names you use inside a function are distinct >>> from those outside. >> >> And thank goodness for that! I've been writing Python code since 1997 >> and version 1.5.<something>,¹ and I still do a double take when emacs >> colors all my ids that faint blue that means "builtin." > > Although it is not helpful for people using screen-readers, and may be of > limited use to the colour-blind, I am in favour of colourising built-ins so > they stand out. Sure, for the ones I use as built-ins. But I went through the color file for vim and took out the built-ins I use regularly as variables -- and 'id' was the first one to go. -- ~Ethan~
[toc] | [prev] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2015-02-28 10:50 +0200 |
| Message-ID | <87sidq8lo4.fsf@elektro.pacujo.net> |
| In reply to | #86611 |
Ethan Furman <ethan@stoneleaf.us>: > Sure, for the ones I use as built-ins. But I went through the color > file for vim and took out the built-ins I use regularly as variables > -- and 'id' was the first one to go. Ah, yes. The id is with us from the beginning. The self seeks to gratify the whims of the id while at least placating the demands of super. But I think stamping out the id altogether is bound to fail and risk the long-term soundness of the implementation. Marko
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2015-02-28 01:48 -0700 |
| Message-ID | <mailman.19330.1425113374.18130.python-list@python.org> |
| In reply to | #86607 |
On Fri, Feb 27, 2015 at 9:42 PM, Dan Sommers <dan@tombstonezero.net> wrote: > I don't think I've ever used the builtin function id in a program. > Ever. Not even once. Honestly, what is a valid use case? If you have a dict that you want to key on object identity rather than equality, then you can use object ids as the keys.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-02-28 19:58 +1100 |
| Message-ID | <mailman.19332.1425113912.18130.python-list@python.org> |
| In reply to | #86607 |
On Sat, Feb 28, 2015 at 7:48 PM, Ian Kelly <ian.g.kelly@gmail.com> wrote: > On Fri, Feb 27, 2015 at 9:42 PM, Dan Sommers <dan@tombstonezero.net> wrote: >> I don't think I've ever used the builtin function id in a program. >> Ever. Not even once. Honestly, what is a valid use case? > > If you have a dict that you want to key on object identity rather than > equality, then you can use object ids as the keys. And not forget to hang onto references to all those objects, else their ids will be meaningless. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Tim Chase <python.list@tim.thechases.com> |
|---|---|
| Date | 2015-02-27 21:50 -0600 |
| Message-ID | <mailman.19328.1425103867.18130.python-list@python.org> |
| In reply to | #86604 |
On 2015-02-28 12:09, Steven D'Aprano wrote: > > * Make your language have a lot of keywords. Enough to make > > memorizing them ALL unlikely, requiring constant visits to your > > documentation > > Is 33 a lot? > > py> import keyword > py> keyword.kwlist > ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', > 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', > 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', > 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', > 'with', 'yield'] A quick google-and-tally for languages and their corresponding number of keywords: C: 33 C#: 77 C++: 86 Java: 50 Lua: 21 PHP: 67 Pascal: 54 Perl: 40 Pike: 37 (Just for you, ChrisA) Python: 31 (2.x) or 33 (3.x) Ruby: 40 So I can't say that Python's all that bad in comparison to most other mainstream languages, with only the austere Lua beating out Python. -tkc
[toc] | [prev] | [next] | [standalone]
| From | Cousin Stanley <cousinstanley@gmail.com> |
|---|---|
| Date | 2015-02-28 09:03 -0700 |
| Message-ID | <mcsorr$i0p$1@dont-email.me> |
| In reply to | #86608 |
> From : Tim Chase
>
> A quick google-and-tally for languages
> and their corresponding number of keywords:
> ....
re-sorted ....
21 : Lua
31 : Python2.x
33 : Python3.x
33 : C
37 : Pike
40 : Perl
40 : Ruby
50 : Java
54 : Pascal
67 : PHP
77 : C#
86 : C++
--
Stanley C. Kitching
Human Being
Phoenix, Arizona
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2015-02-28 08:16 -0800 |
| Message-ID | <37a2d119-49d5-4bc2-90ea-9fefa54bd645@googlegroups.com> |
| In reply to | #86625 |
On Saturday, February 28, 2015 at 9:34:05 PM UTC+5:30, Cousin Stanley wrote: > > From : Tim Chase > > > > A quick google-and-tally for languages > > and their corresponding number of keywords: > > .... > > re-sorted .... > > 21 : Lua > 31 : Python2.x > 33 : Python3.x > 33 : C > 37 : Pike > 40 : Perl > 40 : Ruby > 50 : Java > 54 : Pascal > 67 : PHP > 77 : C# > 86 : C++ Ah so after 20 years of development, python has entered the equivalence class of C
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web