Syntactic sugar

2021-06-28 Thread Michael F. Stemper

I often want to execute a chunk of code n times

for iter in range(n):
  chunkofcode

Sometimes, the chunk of code doesn't care about which iteration
it's on. A week or two back, I would have sworn that I came across
a syntax for the above that eliminates the iteration counter.

This morning, I had use for that syntax, but couldn't find it
on-line or guess what it was. Does this syntax exist, or am I
simply imagining things?

Thanks,
--
Michael F. Stemper
There's no "me" in "team". There's no "us" in "team", either.
--
https://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar

2021-06-28 Thread Michael F. Stemper

On 28/06/2021 11.57, Stefan Ram wrote:

"Michael F. Stemper"  writes:

for iter in range(n):
   chunkofcode


   When the counter does not matter, people sometimes write "_":

for _ in range( n ):
 chunkofcode


That looks like what I wanted.

Thanks!

--
Michael F. Stemper
Indians scattered on dawn's highway bleeding;
Ghosts crowd the young child's fragile eggshell mind.
--
https://mail.python.org/mailman/listinfo/python-list


[issue5149] syntactic sugar: type coercion on pointer assignment

2020-10-25 Thread Irit Katriel


Change by Irit Katriel :


--
versions: +Python 3.10 -Python 3.2

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-12-02 Thread Ethan Furman
On 12/01/2014 05:15 PM, Chris Angelico wrote:
 On Tue, Dec 2, 2014 at 11:45 AM, Ethan Furman wrote:

 Put the above somewhere in your path (e.g. /usr/local/bin), make it 
 executable, and then instead of shebanging your
 scripts with `/usr/local/bin/python` you can use `/usr/local/bin/py_main`, 
 which will load and execute the script,
 calling script.main as its last act.
 
 Be aware that this trick (shebanging to a script rather than a binary)
 isn't specified by the POSIX standard. It works on Linux, but I don't
 know about other systems. 

Ah, thanks for that!

--
~Ethan~



signature.asc
Description: OpenPGP digital signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-12-02 Thread Cameron Simpson

On 02Dec2014 02:17, Ethan Furman et...@stoneleaf.us wrote:

On 12/01/2014 05:15 PM, Chris Angelico wrote:

On Tue, Dec 2, 2014 at 11:45 AM, Ethan Furman wrote:
Put the above somewhere in your path (e.g. /usr/local/bin), make it 

executable, and then instead of shebanging your

scripts with `/usr/local/bin/python` you can use `/usr/local/bin/py_main`, 
which will load and execute the script,
calling script.main as its last act.


Be aware that this trick (shebanging to a script rather than a binary)
isn't specified by the POSIX standard. It works on Linux, but I don't
know about other systems.


Ah, thanks for that!


I'm pretty sure I've used systems where you could not shebang to a script.  
Solaris IIRC. Several years ago, might not be an issue on modern releases.


Cheers,
Cameron Simpson c...@zip.com.au

For reading rec.moto, I use one of those carbon-fiber Logitech mice w/a
little 'No Fear' sticker on it. - Mike Hardcore DoD#5010 mo...@netcom.com
 Apologies to Primus
--
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-12-01 Thread Ethan Furman
On 11/13/2014 10:32 AM, Ethan Furman wrote:
 On 11/12/2014 01:51 PM, Ian Kelly wrote:
 On Wed, Nov 12, 2014 at 2:33 PM, Chris Kaynor wrote:

 A decorator is an interesting idea, and should be easy to implement (only
 lightly tested):

 def main(func):
  if func.__module__ == __main__:
  func()
  return func # The return could be omitted to block the function from
 being manually called after import.

 This calls it at the wrong time, though.  [...]
 
 One decorator that won't call too early is atexit.register().

Well, I've tried this out, and it's only okay.  As soon as interesting things 
start happening, spurious errors about
thread IDs start printing, which really messes up the user experience [1].


[1] something like Exception KeyError: KeyError(139924387112272,) in module 
'threading' from
'/usr/lib/python2.7/threading.pyc' ignored

--
~Ethan~



signature.asc
Description: OpenPGP digital signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-12-01 Thread Ethan Furman
On 12/01/2014 03:19 PM, Ethan Furman wrote:
 
 Well, I've tried this out, and it's only okay.  As soon as interesting things 
 start happening, spurious errors about 
 thread IDs start printing, which really messes up the user experience [...]

So here's another thought:  Have a small python script that loads and runs the 
actual script -- here's a POC:

--- 8 py_main --
#!/usr/bin/env python

import sys
sys.argv.pop(0)

try:
execfile
except NameError:
def execfile(file_name, globals):
with open(file_name) as fh:
script = fh.read()
exec(fh, globals)

module = {}
execfile(sys.argv[0], module)
module['main']()
-

Put the above somewhere in your path (e.g. /usr/local/bin), make it executable, 
and then instead of shebanging your
scripts with `/usr/local/bin/python` you can use `/usr/local/bin/py_main`, 
which will load and execute the script,
calling script.main as its last act.

--
~Ethan~



signature.asc
Description: OpenPGP digital signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-12-01 Thread Chris Angelico
On Tue, Dec 2, 2014 at 11:45 AM, Ethan Furman et...@stoneleaf.us wrote:
 Put the above somewhere in your path (e.g. /usr/local/bin), make it 
 executable, and then instead of shebanging your
 scripts with `/usr/local/bin/python` you can use `/usr/local/bin/py_main`, 
 which will load and execute the script,
 calling script.main as its last act.

Be aware that this trick (shebanging to a script rather than a binary)
isn't specified by the POSIX standard. It works on Linux, but I don't
know about other systems. It's a great trick, though. I once had
shebangs chained something like three or four levels deep.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-16 Thread Vito De Tullio
Steven D'Aprano wrote:

 Chris Kaynor wrote:
 
 I was thinking along the lines of replacing:
 
 if __name__ == __main__:
 block of code
 
 with
 
 @main
 def myFunction()
 block of code
 
 Both blocks of code will be called at the same time.
 
 
 You can't guarantee that, because you cannot tell ahead of time when the
 if __name__ statement will be run. It is *usually* at the end of the
 file, but that's just the normal useful convention, it is not a hard
 requirement.


sure you can: simply the main decorator is just something like

def main(myMainFunction):
if myMainFunction.__module__ == '__main__':
myMainFunction()
return myMainFunction




-- 
By ZeD

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-16 Thread Vito De Tullio
Ian Kelly wrote:

 def main(func):
 if func.__module__ == __main__:
 func()
 return func # The return could be omitted to block the function from
 being manually called after import.

 Just decorate the main function of the script with that, and it will be
 automatically called when ran as a script, but not when imported as a
 module.
 
 This calls it at the wrong time, though. Typically the way this idiom
 is used is that you define everything you need (functions, classes,
 etc.) within the main script, and then you call the main function.
 This would call the main function at the time it's defined, when other
 things in the main script may not have been defined yet. One could
 place the main function last, but it would be preferable not to be
 forced.

for the right time you can choose to spin a thread and wait to the end of 
the load of the module

something like



from threading import Thread, current_thread

def run_func(func, module_thread):
module_thread.join()
func()

def main(func):
if func.__module__ == '__main__':
Thread(target=run_func, args=[func, current_thread()]).start()

return func


-- 
By ZeD

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-16 Thread Ian Kelly
On Sun, Nov 16, 2014 at 3:39 AM, Vito De Tullio vito.detul...@gmail.com wrote:
 for the right time you can choose to spin a thread and wait to the end of
 the load of the module

Yuck. Just add threads is /not/ the answer to everything.

This case looks fairly harmless on the surface, although I could
imagine it breaking things that might object to the main thread being
changed, e.g. things that use event loops or that rely in some way on
the threading.main_thread() function.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-15 Thread Steven D'Aprano
John Ladasky wrote:

 I have taught Python to several students over the past few years.  As I
 have worked with my students, I find myself bothered by the programming
 idiom that we use to determine whether a module is being executed or
 merely imported:
 
   if __name__ == '__main__':
 
 The use of two dunder tokens -- one as a name in a namespace, and the
 other as a string, is intimidating.  It exposes too much of Python's guts.

The dunders are a tad ugly, but it's actually quite simple and elegant:

* every module has a global variable `__name__` which normally holds 
  the name of the module:


py import functools
py functools.__name__
'functools'
py import math as foobarbaz
py foobarbaz.__name__
'math'


* When Python imports a module, it sets the global __name__ to that 
  module's actual name (as taken from the file name).

* But when Python runs a file, as in `python2.7 path/to/script.py`, 
  it sets the global __name__ to the magic value '__main__' instead
  of script.

The consequence is that every module can tell whether it is being run as a
script or not by inspecting the __name__ global. That's all there is to it.





-- 
Steven

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-15 Thread Steven D'Aprano
Chris Kaynor wrote:

 I was thinking along the lines of replacing:
 
 if __name__ == __main__:
 block of code
 
 with
 
 @main
 def myFunction()
 block of code
 
 Both blocks of code will be called at the same time.


You can't guarantee that, because you cannot tell ahead of time when the if
__name__ statement will be run. It is *usually* at the end of the file,
but that's just the normal useful convention, it is not a hard requirement.

The current idiom uses normal, unmagical execution of Python code. When the
interpreter reaches the if __name__ ... statement, it executes that
statement, just like every other statement. There's no magic involved here,
and in fact I have written code with *multiple* such if __name__ blocks.
Here's a sketch of the sort of thing I mean:


import a
import b
if __name__ == '__main__':
import c as d
else:
import d

def this(): ...
def that(): ...

flag = __name__ == '__main__'
process(flag)

if __name__ == '__main__' or condition():
print still executing
main()

print done loading


(I haven't ever done *all* of these things in a *single* file, but I have
done all these things at one time or another.)

There's no way that any automatic system can match that for flexibility or
simplicity.




-- 
Steven

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-15 Thread Marko Rauhamaa
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info:

 if __name__ == '__main__' or condition():
 print still executing
 main()

 print done loading

 (I haven't ever done *all* of these things in a *single* file, but I
 have done all these things at one time or another.)

 There's no way that any automatic system can match that for
 flexibility or simplicity.

Our test system has this boilerplate at the end of each test case:

   if __name__ == '__main__':
   run(test)

Nobody claims it's beautiful but nobody has been overly bothered by it,
either.


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Chris Angelico
On Thu, Nov 13, 2014 at 6:23 PM, Cameron Simpson c...@zip.com.au wrote:
 Indeed. This aspect is a deal breaker for me; I'd never use it.

 I make a point of putting the module's main function right up the top,
 immediately after the imports and any constants (let's not dither over
 that term). I _want_ the main function to in the reader's face when they
 visit the module code. All the cogs come later.

 And lots of my modules have main functions. Terribly useful.

Hmm, I go the other way. As much as possible, I prefer functions to
call what's above them, not what's below them - so the main function
would always be at the end of the file. The very top of the file
should have comments/docstrings etc, then imports, then pure utility
functions that don't call on anything else, then guts functions, and
finally routines that are called externally but never internally (like
main). That way, if you're wondering at what some name means, you go
to the top of the file and find the first occurrence; that'll usually
be its definition. Most people already do this with their imports,
putting them all at the top - I like to go further and make it unusual
for this not to be the case. (Of course, the nature of live projects
and constant editing is that there will be violations of the
principle, and I don't code-churn just to fix it. But that's still the
ideal.)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Cameron Simpson

On 13Nov2014 19:04, Chris Angelico ros...@gmail.com wrote:

On Thu, Nov 13, 2014 at 6:23 PM, Cameron Simpson c...@zip.com.au wrote:

Indeed. This aspect is a deal breaker for me; I'd never use it.

I make a point of putting the module's main function right up the top,
immediately after the imports and any constants (let's not dither over
that term). I _want_ the main function to in the reader's face when they
visit the module code. All the cogs come later.

And lots of my modules have main functions. Terribly useful.


Hmm, I go the other way. As much as possible, I prefer functions to
call what's above them, not what's below them - so the main function
would always be at the end of the file.  [...]


My view is that if there's a main (i.e. the module implements a small app all 
on its own, however tiny), then the main program logic should come first. The 
details follow later.


For a pureply functional module (utility functions, classes built on them, etc) 
I tend to go your way. But the main, if there is one, comes first.



The very top of the file
should have comments/docstrings etc, then imports, then pure utility
functions that don't call on anything else, then guts functions, and
finally routines that are called externally but never internally (like
main). That way, if you're wondering at what some name means, you go
to the top of the file and find the first occurrence; that'll usually
be its definition.


Sounds effective. I probably prefer my code (main aside, again) organised the 
same way. Needless to say, I have a heap of modules that could do with a 
cleanup along these lines.


Cheers,
Cameron Simpson c...@zip.com.au

If you make people think they're thinking, they'll love you; but if you
really make them think, they'll hate you. - Don Marquis
--
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Chris Angelico
On Thu, Nov 13, 2014 at 7:47 PM, Cameron Simpson c...@zip.com.au wrote:
 My view is that if there's a main (i.e. the module implements a small app
 all on its own, however tiny), then the main program logic should come
 first. The details follow later.

Ah, I see. Makes sense. It's kinda like an executable docstring. Still
not my preferred style, but makes its own sense.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Roy Smith
In article mailman.15769.1415869145.18130.python-l...@python.org,
 Chris Angelico ros...@gmail.com wrote:

 On Thu, Nov 13, 2014 at 7:47 PM, Cameron Simpson c...@zip.com.au wrote:
  My view is that if there's a main (i.e. the module implements a small app
  all on its own, however tiny), then the main program logic should come
  first. The details follow later.
 
 Ah, I see. Makes sense. It's kinda like an executable docstring. Still
 not my preferred style, but makes its own sense.
 
 ChrisA

I generally define a main() routine up near the top, then put

if __name__ == '__main__':
main()

at the bottom.  That gives you the best of both worlds; you get to see 
the main() code up front in the file, but you also get to not worry 
about what order things are defined.

It also means you can import your module and call its main() directly.  
That's useful for testing, but occasionally for other purposes too.  You 
can't do that with the (detestable) style of putting a whole bunch of 
code in the body of the if statement.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Chris Angelico
On Fri, Nov 14, 2014 at 12:33 AM, Roy Smith r...@panix.com wrote:
 ... you also get to not worry
 about what order things are defined.

That's only as regards the interpreter, though. My point has nothing
to do with the order the interpreter sees things, it's all about how
they're laid out for humans to read. For that, I prefer to have
definitions before use.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Ethan Furman

On 11/12/2014 01:51 PM, Ian Kelly wrote:

On Wed, Nov 12, 2014 at 2:33 PM, Chris Kaynor wrote:


A decorator is an interesting idea, and should be easy to implement (only
lightly tested):

def main(func):
 if func.__module__ == __main__:
 func()
 return func # The return could be omitted to block the function from
being manually called after import.


This calls it at the wrong time, though.  [...]


One decorator that won't call too early is atexit.register().

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Ian Kelly
On Thu, Nov 13, 2014 at 11:32 AM, Ethan Furman et...@stoneleaf.us wrote:
 On 11/12/2014 01:51 PM, Ian Kelly wrote:

 On Wed, Nov 12, 2014 at 2:33 PM, Chris Kaynor wrote:

 A decorator is an interesting idea, and should be easy to implement (only
 lightly tested):

 def main(func):
  if func.__module__ == __main__:
  func()
  return func # The return could be omitted to block the function from
 being manually called after import.

 This calls it at the wrong time, though.  [...]

 One decorator that won't call too early is atexit.register().

Nice. That feels like an abuse, though. The actual program won't be
able to register its own atexit handlers, because the program will
already be exiting, and other things decorated with atexit.register
might actually be called before the main function.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Ethan Furman
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 11/13/2014 12:33 PM, Ian Kelly wrote:
 On Thu, Nov 13, 2014 at 11:32 AM, Ethan Furman et...@stoneleaf.us wrote:
 On 11/12/2014 01:51 PM, Ian Kelly wrote:
 
 On Wed, Nov 12, 2014 at 2:33 PM, Chris Kaynor wrote:
 
 A decorator is an interesting idea, and should be easy to implement (only 
 lightly tested):
 
 def main(func): if func.__module__ == __main__: func() return func # The 
 return could be omitted to block
 the function from being manually called after import.
 
 This calls it at the wrong time, though.  [...]
 
 One decorator that won't call too early is atexit.register().
 
 Nice. That feels like an abuse, though. The actual program won't be able to 
 register its own atexit handlers,
 because the program will already be exiting, and other things decorated with 
 atexit.register might actually be
 called before the main function.

It's definitely a niche use-case -- such as a cli-helper lib:  import said lib, 
and when it's decorators are used set
the atexit handler to call the lib's __main__ function, which checks that the 
module name of the decorated function is
'__main__', and if it is, run stuff!

Hmmm... hopefully that wasn't difficult to explain.  ;)

- --
~Ethan~
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.11 (GNU/Linux)

iQIcBAEBAgAGBQJUZRfjAAoJENZ7D1rrH75Nx4IP/3tuR4JhVK6Acv04+DiHm32H
BHGmBRZGtXQrHGEBcv8BlvUiztmrHqjV+Lkm78zKF3n9R8Ta9qTeSjqIsjRWUMtR
JVraCSH6usUwmcGITXIYKQHdXynl+ylu9p8Hr3NT2aNoICqowVGSvK3Ie1NmJuf3
lJcl8tXiXgUrGCwBwEgdrBKTdaATe4QT9XFQJx1QbXpF3qT1Za5hPYthY3fH/Pd9
Nl9NHyA6F5x4sSO7itD23UtUpnRBHWl7blwsKkBi7ClfacxJMrYjFAMUaxUaiTFF
/bygveskmMAZw87ISLtjkmOcKtsi0i2BQSQEjpBDZTiveCD/wyDDhJ+5pmZKzll0
Q+pISt4jG9hkArd+JCCxPuTCCo2xm+cMIB4/oSeONd760u6vURLPUNZ5tmNsRkiZ
o0/EwyRhWPZotiLoyi7kDNyfpj/BSKV0A6Ph+M40UXOkTZFUf0E84OFEpB359MTO
rIvHDpd6Tzch2Dliuj6UKZ1OOygIZauv2ebmEBHHNDMdsVbhdtTElS1Rh2JtDVyZ
tUd67KTmE9CwOPcFIbYKHXGIf4FWDAgeaz9x8RY4UUPaDRlyG1eqSxx8Vob2AG9c
MEawmA48JCj52ZeICQf6nnIFdIowFkV7QssUgte3cVfbcMBYnPx/nuJWWMjULo77
WrIUpisDf/juvXn4VtuO
=oczI
-END PGP SIGNATURE-
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Skip Montanaro
On Thu, Nov 13, 2014 at 2:33 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 ... other things decorated with atexit.register
 might actually be called before the main function

I don't think that will happen. The atexit module is documented to
execute its exit functions in reverse order. What's not documented is
the behavior of calling atexit.register() while atexit._run_exitfuncs
is running. That's an implementation detail, and though unlikely to
change, it might be worthwhile getting that behavior documented.

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Skip Montanaro
On Thu, Nov 13, 2014 at 2:44 PM, Skip Montanaro
skip.montan...@gmail.com wrote:
 What's not documented is
 the behavior of calling atexit.register() while atexit._run_exitfuncs
 is running. That's an implementation detail, and though unlikely to
 change, it might be worthwhile getting that behavior documented.

http://bugs.python.org/issue22867

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Ian Kelly
On Thu, Nov 13, 2014 at 1:44 PM, Skip Montanaro
skip.montan...@gmail.com wrote:
 On Thu, Nov 13, 2014 at 2:33 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 ... other things decorated with atexit.register
 might actually be called before the main function

 I don't think that will happen. The atexit module is documented to
 execute its exit functions in reverse order.

Right, so if something else gets registered after the main function,
it will be called before the main function.

 What's not documented is
 the behavior of calling atexit.register() while atexit._run_exitfuncs
 is running. That's an implementation detail, and though unlikely to
 change, it might be worthwhile getting that behavior documented.

Since the exit functions are executed in reverse order, anything
registered at this time would have to be called before something else
that has already been called, so I would expect this to be an error
condition.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-13 Thread Ian Kelly
On Thu, Nov 13, 2014 at 1:53 PM, Skip Montanaro
skip.montan...@gmail.com wrote:
 On Thu, Nov 13, 2014 at 2:44 PM, Skip Montanaro
 skip.montan...@gmail.com wrote:
 What's not documented is
 the behavior of calling atexit.register() while atexit._run_exitfuncs
 is running. That's an implementation detail, and though unlikely to
 change, it might be worthwhile getting that behavior documented.

 http://bugs.python.org/issue22867

In fact it seems the behavior does differ between Python 2.7 and Python 3.4:

$ cat testatexit.py
import atexit

@atexit.register
def main():
  atexit.register(goodbye)

@atexit.register
def goodbye():
  print(Goodbye)
$ python2 testatexit.py
Goodbye
Goodbye
$ python3 testatexit.py
Goodbye
-- 
https://mail.python.org/mailman/listinfo/python-list


How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread John Ladasky
I have taught Python to several students over the past few years.  As I have 
worked with my students, I find myself bothered by the programming idiom that 
we use to determine whether a module is being executed or merely imported:

  if __name__ == '__main__':

The use of two dunder tokens -- one as a name in a namespace, and the other as 
a string, is intimidating.  It exposes too much of Python's guts.  As such, I 
think that it is less Pythonic than we might want.  Myself, I've been 
programming in Python for a decade, and I still haven't dug very deeply into 
what exactly __name__ means or does.

I would like to start a discussion about whether Python should include a 
function which executes this evaluation, and hides all of the unfriendly 
dunderish details.  And if that's a good idea, I would invite a discussion of 
how, exactly, it should be implemented.  I'm nowhere near proposing a PEP, but 
that may come later.

Thanks for your thoughts.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Joel Goldstick
On Wed, Nov 12, 2014 at 4:02 PM, John Ladasky
john_lada...@sbcglobal.net wrote:
 I have taught Python to several students over the past few years.  As I have 
 worked with my students, I find myself bothered by the programming idiom that 
 we use to determine whether a module is being executed or merely imported:

   if __name__ == '__main__':

 The use of two dunder tokens -- one as a name in a namespace, and the other 
 as a string, is intimidating.  It exposes too much of Python's guts.  As 
 such, I think that it is less Pythonic than we might want.  Myself, I've been 
 programming in Python for a decade, and I still haven't dug very deeply into 
 what exactly __name__ means or does.

 I would like to start a discussion about whether Python should include a 
 function which executes this evaluation, and hides all of the unfriendly 
 dunderish details.  And if that's a good idea, I would invite a discussion of 
 how, exactly, it should be implemented.  I'm nowhere near proposing a PEP, 
 but that may come later.

 Thanks for your thoughts.
 --
 https://mail.python.org/mailman/listinfo/python-list

How about a decorator?

-- 
Joel Goldstick
http://joelgoldstick.com
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread John Ladasky
It appears that I'm not the first person to have thoughts along these lines.  
Here's a relevant article:

http://aliles.tumblr.com/post/7455032885/sugar-for-pythons-main
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Ethan Furman

On 11/12/2014 01:02 PM, John Ladasky wrote:


I would like to start a discussion about whether Python should include
 a function which executes this evaluation, and hides all of the unfriendly
 dunderish details.  And if that's a good idea, I would invite a discussion
 of how, exactly, it should be implemented.  I'm nowhere near proposing a
 PEP, but that may come later.


I believe this has come up before.  You might check the Python-Ideas list to see.  If you do, please write up a summary 
of the past discussions so we can move forward instead of rehashing the same things as before.


--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Chris Kaynor
On Wed, Nov 12, 2014 at 1:07 PM, Joel Goldstick joel.goldst...@gmail.com
wrote:

 On Wed, Nov 12, 2014 at 4:02 PM, John Ladasky
 john_lada...@sbcglobal.net wrote:
  I have taught Python to several students over the past few years.  As I
 have worked with my students, I find myself bothered by the programming
 idiom that we use to determine whether a module is being executed or merely
 imported:
 
if __name__ == '__main__':
 
  The use of two dunder tokens -- one as a name in a namespace, and the
 other as a string, is intimidating.  It exposes too much of Python's guts.
 As such, I think that it is less Pythonic than we might want.  Myself, I've
 been programming in Python for a decade, and I still haven't dug very
 deeply into what exactly __name__ means or does.
 
  I would like to start a discussion about whether Python should include a
 function which executes this evaluation, and hides all of the unfriendly
 dunderish details.  And if that's a good idea, I would invite a discussion
 of how, exactly, it should be implemented.  I'm nowhere near proposing a
 PEP, but that may come later.
 
  Thanks for your thoughts.

 How about a decorator?


A decorator is an interesting idea, and should be easy to implement (only
lightly tested):

def main(func):
if func.__module__ == __main__:
func()
return func # The return could be omitted to block the function from
being manually called after import.

Just decorate the main function of the script with that, and it will be
automatically called when ran as a script, but not when imported as a
module.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Ian Kelly
On Wed, Nov 12, 2014 at 2:33 PM, Chris Kaynor ckay...@zindagigames.com wrote:
 A decorator is an interesting idea, and should be easy to implement (only
 lightly tested):

 def main(func):
 if func.__module__ == __main__:
 func()
 return func # The return could be omitted to block the function from
 being manually called after import.

 Just decorate the main function of the script with that, and it will be
 automatically called when ran as a script, but not when imported as a
 module.

This calls it at the wrong time, though. Typically the way this idiom
is used is that you define everything you need (functions, classes,
etc.) within the main script, and then you call the main function.
This would call the main function at the time it's defined, when other
things in the main script may not have been defined yet. One could
place the main function last, but it would be preferable not to be
forced.

This also calls the function before it's been assigned to the global,
which would prevent recursive calls of the main function.

Instead of a decorator, I'd prefer to just have this:

def main(func, *args, **kwargs):
if func.__module__ == '__main__':
func(*args, **kwargs)

And then I can easily invoke it wherever I want in the main script.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Marko Rauhamaa
John Ladasky john_lada...@sbcglobal.net:

 I find myself bothered by the programming idiom that we use to
 determine whether a module is being executed or merely imported:

   if __name__ == '__main__':

I find the idiom cute and loveably silly. A typing tongue twister of
sorts. That boilerplate is far less cumbersome than, say, in Java.

 Myself, I've been programming in Python for a decade, and I still
 haven't dug very deeply into what exactly __name__ means or does.

The idiom allows you to include a main function in auxiliary modules.
When imported, the module acts as a library. When executed, it acts as a
command. I have done this a couple of times IRL.

 I would like to start a discussion about whether Python should include
 a function which executes this evaluation, and hides all of the
 unfriendly dunderish details.

Probably not. Idioms are important in that they are immediately spotted
by a casual reader of the code. However ugly you consider those two
lines, it will not waste a measurable amount of your precious time to
begin your brand new project by typing:

   import sys

   def main():
   pass

   if __name__ == __main__:
   main()


Yes, I always type those in again. I don't copy them over as I do, say,
Java main programs or static HTML pages.


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Skip Montanaro
 def main(func):
 if func.__module__ == __main__:
 func()
 return func # The return could be omitted to block the function from
 being manually called after import.

 Just decorate the main function of the script with that, and it will be
 automatically called when ran as a script, but not when imported as a
 module.

This won't work (I don't think) if you want to call the main
function from another place (like the interpreter prompt).

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Chris Kaynor
On Wed, Nov 12, 2014 at 1:51 PM, Ian Kelly ian.g.ke...@gmail.com wrote:

 On Wed, Nov 12, 2014 at 2:33 PM, Chris Kaynor ckay...@zindagigames.com
 wrote:
  A decorator is an interesting idea, and should be easy to implement (only
  lightly tested):
 
  def main(func):
  if func.__module__ == __main__:
  func()
  return func # The return could be omitted to block the function from
  being manually called after import.
 
  Just decorate the main function of the script with that, and it will be
  automatically called when ran as a script, but not when imported as a
  module.

 This calls it at the wrong time, though. Typically the way this idiom
 is used is that you define everything you need (functions, classes,
 etc.) within the main script, and then you call the main function.
 This would call the main function at the time it's defined, when other
 things in the main script may not have been defined yet. One could
 place the main function last, but it would be preferable not to be
 forced.


I was thinking along the lines of replacing:

if __name__ == __main__:
block of code

with

@main
def myFunction()
block of code

Both blocks of code will be called at the same time.


 This also calls the function before it's been assigned to the global,
 which would prevent recursive calls of the main function.

 Instead of a decorator, I'd prefer to just have this:

 def main(func, *args, **kwargs):
 if func.__module__ == '__main__':
 func(*args, **kwargs)

 And then I can easily invoke it wherever I want in the main script.



 On Wed, Nov 12, 2014 at 1:55 PM, Skip Montanaro skip.montan...@gmail.com
 wrote:

 This won't work (I don't think) if you want to call the main

function from another place (like the interpreter prompt).


With the plain if block, you absolutely cannot call it elsewhere, without
wrapping it in a function anyways.

There is the issue, as mentioned by Ian, that the function will not be in
the module namespace at the time it is called. That does block it, however
it is also easy to work around: make the main function extremely simple,
such as just calling another function.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Ian Kelly
On Wed, Nov 12, 2014 at 3:09 PM, Chris Kaynor ckay...@zindagigames.com wrote:
 I was thinking along the lines of replacing:

 if __name__ == __main__:
 block of code

 with

 @main
 def myFunction()
 block of code

 Both blocks of code will be called at the same time.

99% of the time the content of block of code is just main(),
so then you're proposing replacing this:

if __name__ == __main__:
main()

with this:

@main
def myFunction():
my_main()

Which feels redundant to me. Why have a function here that does
nothing but call another function?

I think if this is the goal then a simple predicate would be clearer:

if is_main_module():
main()
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Terry Reedy

On 11/12/2014 4:02 PM, John Ladasky wrote:

I have taught Python to several students over the past few years.  As
I have worked with my students, I find myself bothered by the
programming idiom that we use to determine whether a module is being
executed or merely imported:

if __name__ == '__main__':

The use of two dunder tokens -- one as a name in a namespace, and the
other as a string, is intimidating.  It exposes too much of Python's
guts.  As such, I think that it is less Pythonic than we might want.
Myself, I've been programming in Python for a decade, and I still
haven't dug very deeply into what exactly __name__ means or does.

I would like to start a discussion about whether Python should
include a function which executes this evaluation, and hides all of
the unfriendly dunderish details.  And if that's a good idea, I would
invite a discussion of how, exactly, it should be implemented.  I'm
nowhere near proposing a PEP, but that may come later.


Functions have an implicit 'return None' at the end (which, in CPython, 
become an explicit pair of bytecodes, even when the function already 
ends with return something'.  The simplest proposal is that modules have 
an implicit if __name__ == '__main__': main() at the end.  I think 
this would not have to be added to the bytecode.


This magical invocation mimics C and some other languages, and I think 
it works well.


--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Chris Angelico
On Thu, Nov 13, 2014 at 10:19 AM, Terry Reedy tjre...@udel.edu wrote:
 Functions have an implicit 'return None' at the end (which, in CPython,
 become an explicit pair of bytecodes, even when the function already ends
 with return something'.  The simplest proposal is that modules have an
 implicit if __name__ == '__main__': main() at the end.  I think this would
 not have to be added to the bytecode.

 This magical invocation mimics C and some other languages, and I think it
 works well.

Yes, but it conflicts with the existing and common usage of having
that explicitly in the code. Safer - and more in line with the way
other such functions are written - would be a dunder function:

if __name__ == '__main__': __main__()

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Terry Reedy

On 11/12/2014 6:26 PM, Chris Angelico wrote:

On Thu, Nov 13, 2014 at 10:19 AM, Terry Reedy tjre...@udel.edu wrote:

Functions have an implicit 'return None' at the end (which, in CPython,
become an explicit pair of bytecodes, even when the function already ends
with return something'.  The simplest proposal is that modules have an
implicit if __name__ == '__main__': main() at the end.  I think this would
not have to be added to the bytecode.

This magical invocation mimics C and some other languages, and I think it
works well.


Yes, but it conflicts with the existing and common usage of having
that explicitly in the code.


Yeh, calling main twice could be a problem.


Safer - and more in line with the way
other such functions are written - would be a dunder function:

if __name__ == '__main__': __main__()


I presume you mean that calling __main__ implicitly would be both 
consistent and safer.  No code should be using that now.



--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Chris Angelico
On Thu, Nov 13, 2014 at 11:35 AM, Terry Reedy tjre...@udel.edu wrote:
 Safer - and more in line with the way
 other such functions are written - would be a dunder function:

 if __name__ == '__main__': __main__()


 I presume you mean that calling __main__ implicitly would be both consistent
 and safer.  No code should be using that now.

That's what I mean. Like changing iter.next() to iter.__next__() in
Py3, it'd be using a name that emphasizes that the interpreter, not
userland code, should be calling this function.

Of course, it'd still be optional. Top-level code would be executed
top-down, same as it now is.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How about some syntactic sugar for __name__ == '__main__' ?

2014-11-12 Thread Cameron Simpson

On 12Nov2014 14:51, Ian Kelly ian.g.ke...@gmail.com wrote:

On Wed, Nov 12, 2014 at 2:33 PM, Chris Kaynor ckay...@zindagigames.com wrote:

A decorator is an interesting idea, and should be easy to implement (only
lightly tested): [...]
Just decorate the main function of the script with that, and it will be
automatically called when ran as a script, but not when imported as a
module.


This calls it at the wrong time, though. [...]
This would call the main function at the time it's defined, when other
things in the main script may not have been defined yet. One could
place the main function last, but it would be preferable not to be
forced.


Indeed. This aspect is a deal breaker for me; I'd never use it.

I make a point of putting the module's main function right up the top, 
immediately after the imports and any constants (let's not dither over that 
term). I _want_ the main function to in the reader's face when they visit the 
module code. All the cogs come later.


And lots of my modules have main functions. Terribly useful.

Cheers,
Cameron Simpson c...@zip.com.au

We're in the business of putting goo on a substrate.
- overhead by WIRED at the Intelligent Printing conference Oct2006
--
https://mail.python.org/mailman/listinfo/python-list


Re: syntactic sugar for def?

2011-09-29 Thread Westley Martínez
On Wed, Sep 28, 2011 at 07:01:11PM -0400, Terry Reedy wrote:
 On 9/28/2011 5:26 PM, Ethan Furman wrote:
 
 I don't remember if 'def' is sugar for something besides lambda.
 
 That is a bit backwards.
   lambda x: expr(x)
 is syntactic sugar for
   def lambda(x): return expr(x)
   del lambda
 ;-)
 

lambda is less sugar and more of just a def as an expression.
-- 
http://mail.python.org/mailman/listinfo/python-list


syntactic sugar for def?

2011-09-28 Thread Ethan Furman

I remember that 'class' is sugar for type().

I don't remember if 'def' is sugar for something besides lambda.

Any clues for me?  Heck, I'll even be grateful for outright answers!

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list


Re: syntactic sugar for def?

2011-09-28 Thread Ian Kelly
On Wed, Sep 28, 2011 at 3:26 PM, Ethan Furman et...@stoneleaf.us wrote:
 I remember that 'class' is sugar for type().

 I don't remember if 'def' is sugar for something besides lambda.

 Any clues for me?  Heck, I'll even be grateful for outright answers!

If you mean is there a way to create functions using reflection, you
can use types.FunctionType.  Like type() requires a dict,
FunctionType() requires a code object that must first be compiled.

Cheers,
Ian
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: syntactic sugar for def?

2011-09-28 Thread Arnaud Delobelle
On 28 September 2011 22:26, Ethan Furman et...@stoneleaf.us wrote:
 I remember that 'class' is sugar for type().

 I don't remember if 'def' is sugar for something besides lambda.

 Any clues for me?  Heck, I'll even be grateful for outright answers!

It's not really sugar.  But I think you mean something like this:


 class A: pass
...
 type(A)
class 'type'
 type is type(A)
True

So the closest you get for functions will be:

 def f(): pass
...
 type(f)
class 'function'

Try help(type(f)) to see how to use it to create a function object.
The problem is that you need to provide a code object, and the easiest
way to create a code object is to use a def statement :)

HTH

-- 
Arnaud
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: syntactic sugar for def?

2011-09-28 Thread Chris Kaynor
On Wed, Sep 28, 2011 at 2:37 PM, Arnaud Delobelle arno...@gmail.com wrote:
 On 28 September 2011 22:26, Ethan Furman et...@stoneleaf.us wrote:
 I remember that 'class' is sugar for type().

 I don't remember if 'def' is sugar for something besides lambda.

 Any clues for me?  Heck, I'll even be grateful for outright answers!

 It's not really sugar.  But I think you mean something like this:


 class A: pass
 ...
 type(A)
 class 'type'
 type is type(A)
 True

 So the closest you get for functions will be:

 def f(): pass
 ...
 type(f)
 class 'function'

 Try help(type(f)) to see how to use it to create a function object.
 The problem is that you need to provide a code object, and the easiest
 way to create a code object is to use a def statement :)

I would say compile isn't too much harder to use:
 c = compile('a = 123', 'test', 'exec')
 d = {}
 f = types.FunctionType(c, d, 'test')
 f()
 print d
{'a': 123}

Although it appears you get all of the variables defined as global
apparently (try f = types.FunctionType(c, globals(), 'test')
instead).


 HTH

 --
 Arnaud
 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: syntactic sugar for def?

2011-09-28 Thread Gabriel Genellina
En Wed, 28 Sep 2011 18:51:00 -0300, Chris Kaynor  
ckay...@zindagigames.com escribió:


On Wed, Sep 28, 2011 at 2:37 PM, Arnaud Delobelle arno...@gmail.com  
wrote:

On 28 September 2011 22:26, Ethan Furman et...@stoneleaf.us wrote:

I remember that 'class' is sugar for type().

I don't remember if 'def' is sugar for something besides lambda.

Any clues for me?  Heck, I'll even be grateful for outright answers!


It's not really sugar.  But I think you mean something like this:



class A: pass

...

type(A)

class 'type'

type is type(A)

True

So the closest you get for functions will be:


def f(): pass

...

type(f)

class 'function'

Try help(type(f)) to see how to use it to create a function object.
The problem is that you need to provide a code object, and the easiest
way to create a code object is to use a def statement :)


I would say compile isn't too much harder to use:

c = compile('a = 123', 'test', 'exec')
d = {}
f = types.FunctionType(c, d, 'test')
f()
print d

{'a': 123}

Although it appears you get all of the variables defined as global
apparently (try f = types.FunctionType(c, globals(), 'test')
instead).


I know no way of compiling a function body alone. Suppose you have this  
function:


def foo(x):
  print x
  y = 2*x
  return y

py compile(  print x\n  y = 2*x\n  return y, string, exec)
Traceback (most recent call last):
  File stdin, line 1, in module
  File string, line 1
print x
^
IndentationError: unexpected indent
py compile(print x\ny = 2*x\nreturn y, string, exec)
Traceback (most recent call last):
  File stdin, line 1, in module
  File string, line 3
SyntaxError: 'return' outside function

If you include the 'def' statement in the source string, the resulting  
code object does not represent the function itself, but a module  
defining it:


py f = FunctionType(compile(def foo(x):\n print x\n y = 2*x\n return  
y\n,

...   string, exec), globals(), foo)
py f(3)
Traceback (most recent call last):
  File stdin, line 1, in module
TypeError: module() takes no arguments (1 given)
py dis.dis(f)
  1   0 LOAD_CONST   0 (code object foo at 00C0FAD0,  
file string, line 1)

  3 MAKE_FUNCTION0
  6 STORE_NAME   0 (foo)
  9 LOAD_CONST   1 (None)
 12 RETURN_VALUE

To get at the actual function code, one should use  
f.func_code.co_consts[0]; this would be the 'code' parameter for  
types.FunctionType. Very complicated, really; nothing can beat the 'def'  
statement for defining a function ;)


--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list


Re: syntactic sugar for def?

2011-09-28 Thread Eric Snow
On Wed, Sep 28, 2011 at 3:26 PM, Ethan Furman et...@stoneleaf.us wrote:
 I remember that 'class' is sugar for type().

 I don't remember if 'def' is sugar for something besides lambda.

This is something I have thought about a lot since PyCon this year.  I
apologize in advance.  wink

Since 3.0, class statements are syntactic sugar for some extra steps
beyond meta(...) [1].  In CPython this is facilitated through the
hidden __build_class__() builtin[2].  We have the __import__()
builtin for customizing module creation. But, as you asked, what about
functions?

Currently there isn't a way to customize function creation.  There is
no __build_function__() builtin.  The best you can do is, like others
have said, directly call FunctionType(...) or type(f)(...) where f is
an existing function.

I expect that if there were a __build_function__, it would wrap the
code that is currently run for the MAKE_FUNCTION/MAKE_CLOSURE
opcodes[3].

Also, both modules and classes have mechanisms built-in to allow for
customization in certain parts of the creation process (PEP 302[4] and
metaclasses[5], respectively).  Functions lack this as well, though
there hasn't been a big clamor for it.  :)  Nick Coghlan proposed an
interesting idea for this in March[6], with some later follow-up[7].
Nothing much came of it though.

Definitely an interesting topic, which has led me to learn a lot about
Python and CPython.

-eric

[1] http://www.python.org/dev/peps/pep-3115/
 http://mail.python.org/pipermail/python-3000/2007-March/006338.html
[2] http://hg.python.org/cpython/file/default/Python/bltinmodule.c#l35
[3] http://hg.python.org/cpython/file/default/Python/ceval.c#l2680
[4] http://www.python.org/dev/peps/pep-0302/
 http://docs.python.org/release/2.3.5/whatsnew/section-pep302.html
 http://docs.python.org/dev/reference/simple_stmts.html#the-import-statement
[5] 
http://docs.python.org/dev/reference/datamodel.html#customizing-class-creation
 http://www.python.org/doc/essays/metaclasses/
[6] http://mail.python.org/pipermail/python-ideas/2011-March/009391.html
[7] http://mail.python.org/pipermail/python-ideas/2011-March/009625.html
 http://mail.python.org/pipermail/python-ideas/2011-April/009765.html


 Any clues for me?  Heck, I'll even be grateful for outright answers!

 ~Ethan~
 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: syntactic sugar for def?

2011-09-28 Thread Terry Reedy

On 9/28/2011 5:26 PM, Ethan Furman wrote:


I don't remember if 'def' is sugar for something besides lambda.


That is a bit backwards.
  lambda x: expr(x)
is syntactic sugar for
  def lambda(x): return expr(x)
  del lambda
;-)

--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list


[issue5149] syntactic sugar: type coercion on pointer assignment

2011-09-06 Thread Vlad Riscutia

Vlad Riscutia riscutiav...@gmail.com added the comment:

I believe there is a deeper issue here in ctypes design. Basically we provide 
both c_char_p and POINTER(c_char) which should behave exactly the same since 
both are the equivalent of char* in C but internally they have different 
implementations.

c_char_p is considered a simple type and I believe supports some conversions 
to and from Python strings while POINTER(c_char) is considered a pointer type 
which supports assignment from array etc.

I think a better fix would be to deprecate p_char_p or make it an equivalent of 
POINTER(c_char), otherwise we will have to do work on c_char_p to make it more 
like POINTER(c_char) when issues like this get opened and probably also make 
POINTER(c_char) more like c_char_p. Why not just have POINTER(c_char) which 
works as expected? I don't have all the historical context on why this 
pseudo-simple type was provided but I saw a couple of issues where people 
expect it to behave like a C char* but it won't because it is implemented as a 
convenience type with limited support.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue5149
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue5149] syntactic sugar: type coercion on pointer assignment

2011-09-06 Thread Meador Inge

Meador Inge mead...@gmail.com added the comment:

Vlad, I agree that having both 'c_char_p' and 'POINTER(c_char)' will just be 
more work for two seemingly identical constructs.  I don't fully understand why 
both would be needed either (or the implications of removing one of them or 
making them synonyms).  I guess a little software archeology is in order.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue5149
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue5149] syntactic sugar: type coercion on pointer assignment

2011-09-02 Thread Meador Inge

Meador Inge mead...@gmail.com added the comment:

This is busted for plain old assignment too:

Python 3.3.0a0 (default:6374b4ffe00c, Sep  2 2011, 23:50:39) 
[GCC 4.6.0 20110603 (Red Hat 4.6.0-10)] on linux
Type help, copyright, credits or license for more information.
 from ctypes import *
 buff = create_string_buffer(b'foo')
 p = c_char_p()
 p.value = addressof(buff)
 print(p.value)
b'foo'
 p.value = buff.value
 print(p.value)
b'foo'
 p.value = buff
Traceback (most recent call last):
  File stdin, line 1, in module
TypeError: string or integer address expected instead of c_char_Array_4 instance

I think having the conversion is an entirely reasonable request.  It is the 
equivalent of:

char buff[128] = foo;
char *p = buff;

in C.  I imagine a lot of C programmers would expect this behavior.

Also, 'ctypes' already does this type of conversion for function parameters.  
Consider a function exported from a shared library 'libfoo' called 
'print_string':

void print_string (char *str)
{
  printf (%s\n, str);
}

The following all work fine:

 libfoo = CDLL(./libfoo.so.1.0)
 buff = create_string_buffer(foo)
 libfoo.print_string(buff)
foo
 libfoo.print_string(foo)
foo
 libfoo.print_string(addressof(buff))
foo

I am working on a patch for this.  I will post it soon.

--
assignee: theller - 
nosy: +amaury.forgeotdarc, belopolsky, meadori -theller
stage: test needed - needs patch

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue5149
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-18 Thread John Pinner
On Aug 3, 2:45 am, gc gc1...@gmail.com wrote:
 Hi everyone! Longtime lurker, hardly an expert, but I've been using
 Python for various projects since 2007 and love it.

 I'm looking for either (A) suggestions on how to do a very common
 operation elegantly and Pythonically, or (B) input on whether my
 proposal is PEP-able, assuming there's no answer to A. (The proposal
 is sort of like the inverse of PEP 3132; I don't think it has been
 proposed before, sorry if I missed it.)

 Anyway, I frequently need to initialize several variables to the same
 value, as I'm sure many do. Sometimes the value is a constant, often
 zero; sometimes it's more particular, such as defaultdict(list). I use
 dict() below.

 Target lists using comma separation are great, but they don't work
 very well for this task. What I want is something like

 a,b,c,d,e = *dict()

 where * in this context means something like assign separately to
 all. I'm not sure that * would the best sugar for this, but the
 normal meaning of * doesn't seem as if it would ever be valid in this
 case, and it somehow feels right (to me, anyway).

 Statements fitting the form above would get expanded during parsing to
 a sequence of separate assignments (a = dict(); b = dict(); c = dict()
 and so forth.) That's all there is to it. Compared to the patterns
 below, it's svelte, less copy-paste-y (so it removes an opportunity
 for inconsistency, where I remember to change a-d to defaultdict(list)
 but forget with e), and it doesn't require me to keep count of the
 number of variables I'm initializing.

 This would update section 6.2 of the language reference and require a
 small grammar expansion.

 But: Is there already a good way to do this that I just don't know?
 Below, I compare four obvious patterns, three of which are correct but
 annoying and one of which is incorrect in a way which used to surprise
 me when I was starting out.

 # Option 1 (separate lines)
 # Verbose and annoying, particularly when the varnames are long and of
 irregular length

 a = dict()
 b = dict()
 c = dict()
 d = dict()
 e = dict()

 # Option 2 (one line)
 # More concise but still pretty annoying, and hard to read (alternates
 variables and assignments)

 a = dict(); b = dict(); c = dict(); d = dict(); e = dict()

 # Option 3 (multiple target list: this seems the most Pythonic, and is
 normally what I use)
 # Concise, separates variables from assignments, but somewhat
 annoying; have to change individually and track numbers on both sides.

 a,b,c,d,e = dict(),dict(),dict(),dict(),dict()

 # Option 4 (iterable multiplication)
 # Looks better, and if the dict() should be something else, you only
 have to change it once, but the extra brackets are ugly and you still
 have to keep count of the targets...

 a,b,c,d,e = [dict()] * 5

 # and it will bite you...

  a[1] = 1
  b
 {1: 1}
  id(a) == id(b)

 True

 # Gotcha!

 # Other forms of 4 also have this behavior:

 a,b,c,d,e = ({},) * 5 a[1] = 1
  b

 {1: 1}

 Alternatively, is there a version of iterable multiplication that
 creates new objects rather than just copying the reference? That would
 solve part of the problem, though it would still look clunky and you'd
 still have to keep count.

 Any thoughts? Thanks!

I hesitate to put this forward, as it smells and is probably
considered bad practice, but heh!

for char in 'abcdefg' :
globals()[ char ] = dict()

does what you wanted.

Best wishes,

John
--


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-18 Thread Roy Smith
In article 
16ea4848-db0c-489a-968c-ca40700f5...@m5g2000prh.googlegroups.com,
 gc gc1...@gmail.com wrote:

 I frequently need to initialize several variables to the same
 value, as I'm sure many do. Sometimes the value is a constant, often
 zero; sometimes it's more particular, such as defaultdict(list). I use
 dict() below.

Keep in mind that when you do:

a = dict()
b = dict()

you are NOT initializing a and b to the same value.  You are 
initializing each of them to a different empty dictionary, which is very 
different from

a = b = dict()

I suspect you knew that, but it's worth mentioning.

 # Option 1 (separate lines)
 # Verbose and annoying, particularly when the varnames are long and of
 irregular length
 
 a = dict()
 b = dict()
 c = dict()
 d = dict()
 e = dict()

This seems the best to me.  Simple, straight-forward, easy to 
understand.  What could be bad?  It may not be elegant, but if I could 
have a nickel for every hour I've wasted trying to understand elegant 
code, I'd be a rich man.  I can understand the above code in an instant, 
even at 2 AM juiced up on sugar and caffeine.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread Chris Angelico
On Wed, Aug 17, 2011 at 1:14 AM, gc gc1...@gmail.com wrote:
 Perfectly reasonable request! Maybe there aren't as many cases when
 multiple variables need to be initialized to the same value as I think
 there are.


Minor clarification: You don't want to initialize them to the same
value, which you can do already:

a=b=c=d=e=dict()

You want to initialize them each to a fresh evaluation of the same
expression. What you're asking for is a syntax that writes an
expression once, but evaluates it many times; I think it's going to
work out something very similar to a list comprehension (as has been
mentioned).

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread gc
On Aug 17, 3:13 am, Chris Angelico ros...@gmail.com wrote:

 Minor clarification: You don't want to initialize them to the same
 value, which you can do already:

 a=b=c=d=e=dict()

Right. Call the proposed syntax the instantiate separately for each
target operator.  (It can be precisely defined as a * on the RHS of a
one-into-many assignment statement--i.e. an assignment statement with
1 object on the RHS and more than 1 on the LHS).

It has only one very modest function, which is to unpack

a, b, c, d, e = *dict()

to

a, b, c, d, e = dict(), dict(), dict(), dict(), dict()

so that you have n separate objects instead of one. If you want the
same object duplicated five times, you'd best use a=b=c=d=e=dict().
(I'd guess that 90% of the people who try the a=b=c version actually
*want* separate objects and are surprised at what they get--I made
that mistake a few times!--but changing either behavior would be a
very bad idea. This proposed syntax would be the Right Way to get
separate objects.)

Maybe this is more visibly convenient with a complex class, like

x, y, z = *SuperComplexClass(param1, param2, kwparam = 3, ...)

where you need three separate objects but don't want to duplicate the
class call (for obvious copy-paste reasons) and where bundling it in a
list comprehension:

x, y, z = [SuperComplexClass(param1, etc, ...) for _ in range(3)]

layers gunk on top of something that's already complex.

 I think it's going to work out something very similar to a
 list comprehension (as has been mentioned).

Right; kind of a self-limiting generator[1], although that sounds MUCH
more complex than it needs to. It's really just sugar. Not that it
this is a suggestion :) but it could easily be done with a pre-
processor. It would also be perfectly amenable to automated code
conversion (i.e. 3to2).

On Aug 16, 10:11 pm, MRAB pyt...@mrabarnett.plus.com wrote:

 1. Repeated evaluation of an expression: dict() would be evaluated as
 many times as necessary. In other words, it's an unlimited generator.

 2. Lazy unpacking: unpacking normally continues until the source is
 exhausted, but here you want it to stop when the destination (the RHS)
 is satisfied.

Yes, this is a good way to think of it. (Although I think you meant to
type LHS, right?) * in this context would tell Python to do both of
these things at once: evaluate successively and unpack lazily to the
destination. Although it's still fully (and more simply) explainable
as sugar.

[1] Self-limiting is the key here. As above, the only proposed methods
which don't require manual tallying on the RHS are Tim's very creative
a,b,c,d,e,*scrap = (dict() for _ in range()), which in this case
creates a list containing 9994 unnecessary dicts, or the purer but
Python-crashing a,b,c,d,e,*scrap = (dict() for _ in
itertools.count()). Tim's intuition, which I share, is that in both
cases *scrap should, since it's in final position, actually become the
generator-in-state-6, rather than slurping the rest into a list. One
argument for this is that the present behavior is (surprisingly,
counterintuitively) identical for list comprehensions and generator
expressions. Changing the outer parens to brackets yields the same
results. But that's a separate, more complex proposal which would need
its own use cases.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread Chris Angelico
On Wed, Aug 17, 2011 at 10:26 AM, gc gc1...@gmail.com wrote:
 On Aug 17, 3:13 am, Chris Angelico ros...@gmail.com wrote:

 Minor clarification: You don't want to initialize them to the same
 value, which you can do already:

 a=b=c=d=e=dict()

 Right. Call the proposed syntax the instantiate separately for each
 target operator.  (It can be precisely defined as a * on the RHS of a
 one-into-many assignment statement--i.e. an assignment statement with
 1 object on the RHS and more than 1 on the LHS).


Agreed, but there's no requirement for it to be instantiating
something (although that will be common). dict() is an expression
that you want to evaluate five (or however many) times. It might just
as easily be some other function call; for instance:

head1,head2,head3=file.readline()

to read three lines from a file. Or it mightn't even be a function call per se.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread gc
On Aug 17, 5:45 am, Chris Angelico ros...@gmail.com wrote:
(snip)
  Right. Call the proposed syntax the instantiate separately for each
  target operator.

(snip)
 It might just
 as easily be some other function call; for instance:

 head1,head2,head3=file.readline()

Hm--that's interesting! OK, call it the evaluate separately for each
target operator.

Same benefits in this use case; if I realize that the file only has
two header lines, I can just change

head1, head2, head3 = *file.readline()

to

head1, head2 = *file.readline()

without needing to keep a RHS like = [file.readline() for _ in
range(3)] in lockstep with the number of variables I'm assigning.

Presumably this syntax should be disallowed, as a grammatical matter,
when there's a starred target (per PEP 3132/language reference 6.2).
That is,

head, *body, tail = *file.readline()

is disallowed, since it is (by definition) simply sugar for

head = file.readline()
*body = file.readline()
tail = file.readline()

and

*body = file.readline() is disallowed (see PEP 3132). (Here, of
course, you'd just want head, *body, tail = file.readlines(), which is
perfectly good code.)

PS.

Off-topic, but the *target syntax already gets into similar territory,
since

a, *b, c = itertools.count()

crashes with a MemoryError--but what else could it do? Ruling out such
infinite-assignment statements on a grammatical basis would require
solving the halting problem through static analysis, which might be a
bit inefficient :P



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread Terry Reedy
The issue behind this thread is that for immutable objects, binding to n 
copies has the same effect as n bindings to one object (so one does not 
really have to know which one is doing), whereas the two are different 
for mutable objects (so one does have to know). In short, identity 
matters for mutables but not for immutables. Python programmers must 
learn both this and the fact that Python does not make copies unless asked.


Adding a special case exception to the latter to mask the former does 
not seem like a good idea.


On 8/17/2011 5:26 AM, gc wrote:


It has only one very modest function, which is to unpack

a, b, c, d, e = *dict()


*expression has already been proposed to generally mean what it does in 
function calls -- unpack the iterator in place.


funnylist = [1,2,*dict,99,100]
# == [1,2]+list(dict)+[99,100]

would interpolate the keys of the dict into the list.

There is a tracker issue for this -- it would be a follow-on to the 
addition of *traget in assignments.


In a real sense, a,b = iterable *already* means a,b = *iterable. If 
*iterable had been in general use from the beginning, presume the latter 
is how we would write sequence unpacking for assignments.



a, b, c, d, e = dict(), dict(), dict(), dict(), dict()


*expression will not be changed in meaning to magically re-evaluate an 
expression some multiple number of times according to code elsewhere.



so that you have n separate objects instead of one. If you want the
same object duplicated five times, you'd best use a=b=c=d=e=dict().


Not 'duplicated', but 'bound'.


(I'd guess that 90% of the people who try the a=b=c version actually
*want* separate objects and are surprised at what they get--I made
that mistake a few times!


Guessing that 90% of people are like you is likely to be wrong.
I think this use case (for more than 2 or 3 copies) is pretty rare for 
most people.


Where many people do trip up is array = [[0]*i]*j, expecting to get j 
copies of [0]*i rather than j bindings of one object. But then, they 
must have the same wrong idea that [0]*i makes i copies of 0. For 
immutable 0, the misunderstanding does not matter. For mutable [0]*i, it 
does. People *must* learn that sequence multiplication multiplies 
bindings, not (copies of) objects. Both multiple copy problems have the 
same solution:


array = [[0]*i for _ in range(j)]
a,b,c,d,e = [dict() for _ in range(5)]

The fact that the number of assignment sources (possibly after implicit 
unpacking) and targets have to match, unless one uses *target, and that 
both sides need to be changed if one is, is true of all assignments, not 
just this rare case.



--but changing either behavior would be a
very bad idea. This proposed syntax would be the Right Way to get
separate objects.)


It would be very Wrong as it already has a very different meaning.

--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread MRAB

On 17/08/2011 10:26, gc wrote:

On Aug 17, 3:13 am, Chris Angelicoros...@gmail.com  wrote:


Minor clarification: You don't want to initialize them to the same
value, which you can do already:

a=b=c=d=e=dict()


Right. Call the proposed syntax the instantiate separately for each
target operator.  (It can be precisely defined as a * on the RHS of a
one-into-many assignment statement--i.e. an assignment statement with
1 object on the RHS and more than 1 on the LHS).


I think that lazy unpacking is the more important issue because we can
replace instantiation with copying:

def copies(obj, count=None):
if count is None:
while True:
yield obj.copy()
else:
for i in range(count):
yield obj.copy()

(Should it yield deep copies, or should there be a separate deep_copies
function?)


It has only one very modest function, which is to unpack

a, b, c, d, e = *dict()

to

a, b, c, d, e = dict(), dict(), dict(), dict(), dict()


This becomes:

a, b, c, d, e = copies(dict(), 5)

With lazy unpacking it would become:

a, b, c, d, e = lazy copies(dict())

(Or whatever the syntax is.)


so that you have n separate objects instead of one. If you want the
same object duplicated five times, you'd best use a=b=c=d=e=dict().
(I'd guess that 90% of the people who try the a=b=c version actually
*want* separate objects and are surprised at what they get--I made
that mistake a few times!--but changing either behavior would be a
very bad idea. This proposed syntax would be the Right Way to get
separate objects.)

Maybe this is more visibly convenient with a complex class, like

x, y, z = *SuperComplexClass(param1, param2, kwparam = 3, ...)


x, y, z = lazy copies(SuperComplexClass(param1, etc, ...))

[snip]
--
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread Chris Angelico
On Wed, Aug 17, 2011 at 5:55 PM, MRAB pyt...@mrabarnett.plus.com wrote:
 x, y, z = lazy copies(SuperComplexClass(param1, etc, ...))


This assumes that you can construct it once and then copy it reliably,
which may mean that the class implement copying correctly. It also
wouldn't work with:

a, b, c, d = *random.randint(1,20)

which would roll 4d20 and get the results in separate variables. The
OP's idea of separately evaluating the expression would; but to do it
with copying would require a special randint object that functions
exactly as an integer but, when copied, would re-randomize.

Perhaps * is the wrong syntactic element to use. Maybe it needs a
special assignment operator:

a, b, c, d @= random.randint(1,20)

which would evaluate its left operand as a tuple of lvalues, then
evaluate its right operand once for each element in the left operand,
and assign to each element in turn. (I've no idea what form of
assignment operator would be suitable, but @= is currently illegal, so
it ought to be safe at least for discussion purposes.)

Chris Angelico
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread OKB (not okblacke)
gc wrote:

 Maybe this is more visibly convenient with a complex class, like
 
 x, y, z = *SuperComplexClass(param1, param2, kwparam = 3, ...)
 
 where you need three separate objects but don't want to duplicate the
 class call (for obvious copy-paste reasons) and where bundling it in a
 list comprehension:
 
 x, y, z = [SuperComplexClass(param1, etc, ...) for _ in range(3)]
 
 layers gunk on top of something that's already complex.

That just seems like an odd use case to me.  I rarely find myself 
wanting to make exactly N copies of the same thing and assign them to 
explicit names.  If I'm not making just one, it's usually because 
I'm making some sort of list or dict of them that will be accessed by 
index (not with names like x, y, and z), in which case a list 
comprehension is the right way to go.

-- 
--OKB (not okblacke)
Brendan Barnwell
Do not follow where the path may lead.  Go, instead, where there is
no path, and leave a trail.
--author unknown
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread Ethan Furman

gc wrote:

Target lists using comma separation are great, but they don't work
very well for this task. What I want is something like

a,b,c,d,e = *dict()


This isn't going to happen.  From all the discussion so far I think your 
best solution is a simple helper function (not tested):


def repeat(count_, object_, *args, **kwargs):
result = []
for _ in range(count_):
result.append(object_(*args, **kwargs))
return result

a, b, c, d, e = repeat(5, dict)

These are each new objects, so depending on the function (like the 
random.rand_int example) the values may not be the same.


Oh, and I put the trailing _ on count and object to minimize possible 
conflicts with keyword arguments.


~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-17 Thread Zero Piraeus
:

Off on a tangent ...

On 16 August 2011 20:14, gc gc1...@gmail.com wrote:

 Let me address one smell from my particular example, which may be the
 one you're noticing. If I needed fifty parallel collections I would
 not use separate variables; I've coded a ghastly defaultdefaultdict
 just for this purpose, which effectively permits what most people
 would express as defaultdict(defaultdict(list)) [not possible AFAIK
 with the existing defaultdict class].

Dunno if it's better than your ghastly defaultdefaultdict, but this works:

 from collections import defaultdict
 ddd = defaultdict(lambda: defaultdict(list))
 ddd[foo][bar].append(something)
 ddd[foo][bar]
['something']


 -[]z.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-16 Thread gc
Thanks for all the discussion on this. Very illuminating. Sorry for
the long delay in responding--deadlines intervened.

I will use the list comprehension syntax for the foreseeable future.

Tim, I agree with you about the slurping in final position--it's
actually quite surprising. As I'm sure you realized, that behavior
makes your 'tidier' version:

a,b,c,d,e, *more_dict_generator = (dict() for _ in itertools.count())

break with a MemoryError, which I don't think is the result that most
people would expect.

Stephen wrote:

 While slightly ugly, it doesn't seem ugly enough to justify the
 extra complexity of special syntax for such a special case.

You're probably right (although for my coding this multiple assignment
scenario is a pretty ordinary case.) Anyway, I'll shop the a,b,c =
*dict() syntax over to python-ideas just to see what they say.

Thanks again, everyone! Happy Python.

On Aug 3, 7:25 am, Tim Chase python.l...@tim.thechases.com wrote:
 On 08/03/2011 03:36 AM, Katriel Cohn-Gordon wrote:

  On Wed, Aug 3, 2011 at 9:25 AM, Steven D'Aprano wrote:
  a, b, c, d, e = [dict() for i in range(5)]

  I think this is good code -- if you want five different dicts,
  then you should call dict five times. Otherwise Python will
  magically call your expression more than once, which isn't
  very nice. And what if your datatype constructor has
  side-effects?

 If the side-effects are correct behavior (perhaps opening files,
 network connections, or even updating a class variable) then
 constructor side-effects are just doing what they're supposed to.
   E.g. something I use somewhat regularly in my code[*]:

   a,b,c,d = (file('file%i.txt', 'w') for i in range(4))

 If the side-effects aren't performing the correct behavior, fix
 the constructor. :)

 -tkc

 [*] okay, it's more like

 (features,
   adjustments,
   internet,
   ) = (file(fname) for fname in (
     'features.txt',
     'adjustments.txt',
     'internet.txt'
     )

 or even

 (features,
   adjustments,
   internet,
   ) = (
     set(
       line.strip().upper()
       for line
       in file(fname)
       if line.strip()
       )
     for fname in (
     'features.txt',
     'adjustments.txt',
     'internet.txt'
     )

 to load various set() data from text-files.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-16 Thread Martin P. Hellwig

On 03/08/2011 02:45, gc wrote:
cut

a,b,c,d,e = *dict()

where * in this context means something like assign separately to
all.

CUT

Any thoughts? Thanks!


Well got a thought but I am afraid it is the opposite of helpful in the 
direct sense. So if you don't want to hear it skip it :-)


Although I can not proficiently argument it, it has a certain code smell 
to it. In the sense that it could hint that there is a better more 
readable way of solving that particular problem (taking in account that 
the one letter labels are pure for demonstration purpose).


I would love to see an example where you would need such a construct.

--
mph

--
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-16 Thread gc
On Aug 16, 4:39 pm, Martin P. Hellwig martin.hell...@gmail.com
wrote:
 On 03/08/2011 02:45, gc wrote:
 cut

  a,b,c,d,e = *dict()

  where * in this context means something like assign separately to
  all.

 snip . . . it has a certain code smell to it. snip
 I would love to see an example where you would need such a construct.

Perfectly reasonable request! Maybe there aren't as many cases when
multiple variables need to be initialized to the same value as I think
there are.

I'm a heavy user of collections, especially counters and defaultdicts.
One frequent pattern involves boiling (typically) SQLite records down
into Python data structures for further manipulation. (OK, arguably
that has some code smell right there--but I often have to do very
expensive analysis on large subsets with complex definitions which can
be very expensive to pull, sometimes requiring table scans over tens
of gigabytes. I *like* being able to use dicts or other structures as
a way to cache and structure query results in ways amenable to
analysis procedures, even if it doesn't impress Joe Celko.)

defaultdict(list) is a very clean way to do this. I'll often have four
or five of them collecting different subsets of a single SQL pull, as
in:

# PROPOSED SYNTAX:
all_pets_by_pet_store, blue_dogs_by_pet_store,
green_cats_by_pet_store, red_cats_and_birds_by_pet_store =
*defautdict(list)

# (Yes, indexes on color and kind would speed up this query, but the
actual fields can be way quite complex and have much higher
cardinality.)
for pet_store, pet_kind, pet_color, pet_weight, pet_height in
cur.execute(SELECT s, k, c, w, h FROM SuperExpensivePetTable WHERE
CostlyCriterionA(criterion_basis) IN(you, get, the, idea)):
all_pets_by_pet_store[pet_store].append(pet_weight, pet_height)
if pet_color in (Blue, Cyan, Dark Blue) and pet_kind in
(Dog, Puppy):
blue_dogs_by_pet_store[pet_store].append(pet_weight,
pet_height)
#... and so forth

all_pets_analysis  =
BootstrappedMarkovDecisionForestFromHell(all_pets_by_pet_store)
blue_dogs_analysis =
BootstrappedMarkovDecisionForestFromHell(blue_dogs_by_pet_store)
red_cats_and_birds_analysis =
BMDFFHPreyInteracton(red_cats_and_bird_by_pet_store)
#... and so forth

Point is, I'd like to be able to create such collections cleanly, and
a,b,c = *defaultdict(list) seems as clean as it gets. Plus, when I
realize I need six (or only three) it's annoying to need to change two
redundant things (i.e. both the variable names and the count.)

if tl_dr: break()

Generally speaking, when you know you need several variables of the
same (maybe complex) type, the proposed syntax lets the equals sign
fully partition the variables question (how many variables do I need,
and what are they called?) from the data structure question (what type
should the variables be?) The other syntaxes (except Tim's generator-
slurping one, which as Tim points out has its own issues) all spread
the variables question across the equals sign, breaking the analogy
with single assignment (where the form is Variable = DataStructure).
If we're allowing multiple assignment, why can't we allow some form of
Variable1, Variable2, Variable3 = DataStructure without reaching for
list comprehensions, copy-pasting and/or keeping a side count of the
variables?

if much_tl_dr: break()

Let me address one smell from my particular example, which may be the
one you're noticing. If I needed fifty parallel collections I would
not use separate variables; I've coded a ghastly defaultdefaultdict
just for this purpose, which effectively permits what most people
would express as defaultdict(defaultdict(list)) [not possible AFAIK
with the existing defaultdict class]. But for reasons of explicitness
and simplicity I try to avoid hash-tables of hash-tables (and higher
iterations). I'm not trying to use dicts to inner-platform a fully
hashed version of SQL, but to boil things down.

Also bear in mind, reading the above, that I do a lot of script-type
programming which is constantly being changed under severe time
pressure (often as I'm sitting next to my clients), which needs to be
as simple as possible, and which tech-savvy non-programmers need to
understand. A lot of my value comes from quickly creating code which
other people (usually research academics) can feel ownership over.
Python is already a great language for this, and anything which makes
the syntax cleaner and more expressive and which eliminates redundancy
helps me do my job better. If I were coding big, stable applications
where the defaultdicts were created in a header file and wouldn't be
touched again for three years, I would care less about a more awkward
initialization method.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-16 Thread MRAB

On 17/08/2011 01:14, gc wrote:

On Aug 16, 4:39 pm, Martin P. Hellwigmartin.hell...@gmail.com
wrote:

On 03/08/2011 02:45, gc wrote:
cut


a,b,c,d,e = *dict()



where * in this context means something like assign separately to
all.



snip  . . . it has a certain code smell to it.snip
I would love to see an example where you would need such a construct.


Perfectly reasonable request! Maybe there aren't as many cases when
multiple variables need to be initialized to the same value as I think
there are.


[snip]
As I see it, there are 2 issues:

1. Repeated evaluation of an expression: dict() would be evaluated as
many times as necessary. In other words, it's an unlimited generator.

2. Lazy unpacking: unpacking normally continues until the source is
exhausted, but here you want it to stop when the destination (the RHS)
is satisfied.

It just happens that in your use-case they are being used together.
--
http://mail.python.org/mailman/listinfo/python-list


[issue5149] syntactic sugar: type coercion on pointer assignment

2011-08-07 Thread Vlad Riscutia

Vlad Riscutia riscutiav...@gmail.com added the comment:

The main reason for this issue is that internally ctypes doesn't consider 
c_char_p as a pointer type. This is a bit counter-intuitive, but c_char_p is 
treated as a simple type and has some other sugar built-in, like easier 
integration with Python strings. Alternative pointer type is POINTER(c_char), 
which allows assignment from array.

I would make this clear in the documentation. Even now, documentation says 
following about c_char_p:

Represents the C char * datatype when it points to a zero-terminated string. 
For a general character pointer that may also point to binary data, 
POINTER(c_char) must be used. The constructor accepts an integer address, or a 
string.

So there already is a hint that c_char_p has limited use for convenience. We 
should maybe make documentation more clear. If you want equivalent of C char* 
behavior, POINTER(c_char) is the way to go.

--
nosy: +vladris

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue5149
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-03 Thread Steven D'Aprano
gc wrote:

 Target lists using comma separation are great, but they don't work
 very well for this task. What I want is something like
 
 a,b,c,d,e = *dict()


a, b, c, d, e = [dict() for i in range(5)]

Unfortunately there is no way of doing so without counting the assignment
targets. While slightly ugly, it doesn't seem ugly enough to justify the
extra complexity of special syntax for such a special case.


-- 
Steven

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-03 Thread Gregory Ewing

gc wrote:


Alternatively, is there a version of iterable multiplication that
creates new objects rather than just copying the reference?


You can use a list comprehension:

  a, b, c, d, e = [dict() for i in xrange(5)]

or a generator expression:

  a, b, c, d, e = (dict() for i in xrange(5))

--
Greg
--
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-03 Thread Katriel Cohn-Gordon
On Wed, Aug 3, 2011 at 9:25 AM, Steven D'Aprano 
steve+comp.lang.pyt...@pearwood.info wrote:

 gc wrote:

  Target lists using comma separation are great, but they don't work
  very well for this task. What I want is something like
 
  a,b,c,d,e = *dict()

 a, b, c, d, e = [dict() for i in range(5)]


I think this is good code -- if you want five different dicts, then you
should call dict five times. Otherwise Python will magically call your
expression more than once, which isn't very nice. And what if your datatype
constructor has side-effects?

Katriel
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-03 Thread Tim Chase

On 08/03/2011 03:25 AM, Steven D'Aprano wrote:

gc wrote:


Target lists using comma separation are great, but they don't work
very well for this task. What I want is something like

a,b,c,d,e = *dict()



a, b, c, d, e = [dict() for i in range(5)]

Unfortunately there is no way of doing so without counting the assignment
targets. While slightly ugly, it doesn't seem ugly enough to justify the
extra complexity of special syntax for such a special case.


I understand that in Py3k (and perhaps back-ported into later 2.x 
series?) one can do something like


a, b, c, d, e, *junk = (dict() for _ in range())

to prevent the need to count.  However, I was disappointed with 
all the generator-ification of things in Py3k, that this and the 
rest syntax slurps up the entire generator, rather than just 
assigning the iterator.  That would much more tidily be written as


a,b,c,d,e, *more_dict_generator = (dict() for _ in itertools.count())

(itertools.count() happening to be a infinite generator).  I can 
see the need to slurp if you have things afterward:


  a,b,c, *junk ,d,e = iterator(...)

but when the and the rest is the last one, it would make sense 
not to force a slurp.


-tkc





--
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-03 Thread Tim Chase

On 08/03/2011 03:36 AM, Katriel Cohn-Gordon wrote:

On Wed, Aug 3, 2011 at 9:25 AM, Steven D'Aprano wrote:

a, b, c, d, e = [dict() for i in range(5)]


I think this is good code -- if you want five different dicts,
then you should call dict five times. Otherwise Python will
magically call your expression more than once, which isn't
very nice. And what if your datatype constructor has
side-effects?


If the side-effects are correct behavior (perhaps opening files, 
network connections, or even updating a class variable) then 
constructor side-effects are just doing what they're supposed to. 
 E.g. something I use somewhat regularly in my code[*]:


 a,b,c,d = (file('file%i.txt', 'w') for i in range(4))

If the side-effects aren't performing the correct behavior, fix 
the constructor. :)


-tkc


[*] okay, it's more like

(features,
 adjustments,
 internet,
 ) = (file(fname) for fname in (
   'features.txt',
   'adjustments.txt',
   'internet.txt'
   )

or even

(features,
 adjustments,
 internet,
 ) = (
   set(
 line.strip().upper()
 for line
 in file(fname)
 if line.strip()
 )
   for fname in (
   'features.txt',
   'adjustments.txt',
   'internet.txt'
   )

to load various set() data from text-files.
--
http://mail.python.org/mailman/listinfo/python-list


Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-02 Thread gc
Hi everyone! Longtime lurker, hardly an expert, but I've been using
Python for various projects since 2007 and love it.

I'm looking for either (A) suggestions on how to do a very common
operation elegantly and Pythonically, or (B) input on whether my
proposal is PEP-able, assuming there's no answer to A. (The proposal
is sort of like the inverse of PEP 3132; I don't think it has been
proposed before, sorry if I missed it.)

Anyway, I frequently need to initialize several variables to the same
value, as I'm sure many do. Sometimes the value is a constant, often
zero; sometimes it's more particular, such as defaultdict(list). I use
dict() below.

Target lists using comma separation are great, but they don't work
very well for this task. What I want is something like

a,b,c,d,e = *dict()

where * in this context means something like assign separately to
all. I'm not sure that * would the best sugar for this, but the
normal meaning of * doesn't seem as if it would ever be valid in this
case, and it somehow feels right (to me, anyway).

Statements fitting the form above would get expanded during parsing to
a sequence of separate assignments (a = dict(); b = dict(); c = dict()
and so forth.) That's all there is to it. Compared to the patterns
below, it's svelte, less copy-paste-y (so it removes an opportunity
for inconsistency, where I remember to change a-d to defaultdict(list)
but forget with e), and it doesn't require me to keep count of the
number of variables I'm initializing.

This would update section 6.2 of the language reference and require a
small grammar expansion.

But: Is there already a good way to do this that I just don't know?
Below, I compare four obvious patterns, three of which are correct but
annoying and one of which is incorrect in a way which used to surprise
me when I was starting out.

# Option 1 (separate lines)
# Verbose and annoying, particularly when the varnames are long and of
irregular length

a = dict()
b = dict()
c = dict()
d = dict()
e = dict()

# Option 2 (one line)
# More concise but still pretty annoying, and hard to read (alternates
variables and assignments)

a = dict(); b = dict(); c = dict(); d = dict(); e = dict()

# Option 3 (multiple target list: this seems the most Pythonic, and is
normally what I use)
# Concise, separates variables from assignments, but somewhat
annoying; have to change individually and track numbers on both sides.

a,b,c,d,e = dict(),dict(),dict(),dict(),dict()

# Option 4 (iterable multiplication)
# Looks better, and if the dict() should be something else, you only
have to change it once, but the extra brackets are ugly and you still
have to keep count of the targets...

a,b,c,d,e = [dict()] * 5

# and it will bite you...

 a[1] = 1
 b
{1: 1}
 id(a) == id(b)
True

# Gotcha!

# Other forms of 4 also have this behavior:

a,b,c,d,e = ({},) * 5
 a[1] = 1
 b
{1: 1}

Alternatively, is there a version of iterable multiplication that
creates new objects rather than just copying the reference? That would
solve part of the problem, though it would still look clunky and you'd
still have to keep count.

Any thoughts? Thanks!
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Syntactic sugar for assignment statements: one value to multiple targets?

2011-08-02 Thread Chris Angelico
On Wed, Aug 3, 2011 at 2:45 AM, gc gc1...@gmail.com wrote:
 Anyway, I frequently need to initialize several variables to the same
 value, as I'm sure many do. Sometimes the value is a constant, often
 zero; sometimes it's more particular, such as defaultdict(list). I use
 dict() below.

If it's an immutable value (such as a constant integer), you can use
syntax similar to C's chained assignment:

a=b=c=0

If you do this with dict(), though, it'll assign the same dictionary
to each of them - not much use.

 # Option 3 (multiple target list: this seems the most Pythonic, and is
 normally what I use)
 # Concise, separates variables from assignments, but somewhat
 annoying; have to change individually and track numbers on both sides.

 a,b,c,d,e = dict(),dict(),dict(),dict(),dict()

I think this is probably the best option, although I would be inclined
to use dictionary-literal syntax:
a,b,c,d,e = {},{},{},{},{}

It might be possible to do something weird with map(), but I think
it'll end up cleaner to do it this way.

Chris Angelico
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-12-02 Thread Mark Dickinson
On Nov 15, 12:46 pm, Tim Chase python.l...@tim.thechases.com wrote:
 On 11/15/2010 12:39 AM, Dmitry Groshev wrote:

  x in range optimisation

 I've often thought this would make a nice O(1)-test lookup on an
 xrange() generator.

An O(1) test for 'x in range_object' is implemented in Python 3.2,
at least provided that x has type 'int', 'long' or 'bool'.  (If x is
an instance of a subclass of int or long, then there's a risk that the
semantics of the membership test have been changed by an explicitly
overridden __eq__, so Python wimps out and falls back to the O(n)
algorithm in that case.)

Python 3.2a4+ (py3k:86635:86636M, Nov 21 2010, 19:22:18)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type help, copyright, credits or license for more information.
 -1 in range(10**9)
False
 5 in range(0, 10**100, 2)
False
 10**99 in range(0, 10**100, 2)
True

IIRC, there wasn't sufficient interest to get it backported to Python
2.7 in time for its release.  Though as a pure optimization, one could
argue that it would still be possible to get this into Python 2.7.2.

Mark
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-12-02 Thread Tim Chase

On 12/02/2010 10:39 AM, Mark Dickinson wrote:

On Nov 15, 12:46 pm, Tim Chasepython.l...@tim.thechases.com  wrote:

On 11/15/2010 12:39 AM, Dmitry Groshev wrote:


x in range optimisation


I've often thought this would make a nice O(1)-test lookup on an
xrange() generator.


An O(1) test for 'x inrange_object' is implemented in Python 3.2,
at least provided that x has type 'int', 'long' or 'bool'.  (If x is
an instance of a subclass of int or long, then there's a risk that the
semantics of the membership test have been changed by an explicitly
overridden __eq__, so Python wimps out and falls back to the O(n)
algorithm in that case.)


Drat, bested again by the python time-machine.  Thanks for 
bringing that to my attention.


-tkc



--
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-12-01 Thread Dmitry Groshev
On Nov 22, 2:21 pm, Andreas Löscher andreas.loesc...@s2005.tu-
chemnitz.de wrote:
      if x in range(a, b): #wrong!
  it feels so natural to check it that way, but we have to write
      if a = x = b
  I understand that it's not a big deal, but it would be awesome to have
  some optimisations - it's clearly possible to detect things like that
  wrong one and fix it in a bytecode.

 You can implement it yourself:

 class between(object):
         def __init__(self, a,b):
                 super(crang, self).__init__()
                 self.a=a
                 self.b=b
         def __contains__(self, value):
                 return self.a = value = self.b

  12.45 in between(-100,100)

 true

 But do you need

 a   x   b
 a = x   b
 a = x = b or
 a   x = b ?

 Sure, you could set a new parameter for this, but the normal way is not
 broken at all.

 Best

Of course there are better ways to do this. Your between, standart
comparisons and so, but expressing this as i in range(a, b) is just
intuitive and declarative.
Here is a fresh example of what I meant by my first proposal. You need
to build a matrix like this:
2 1 0 ...
1 2 1 ...
0 1 2 ...
...
... 1 2 1
... 0 1 2
You could do this by one-liner:
[[(2 - abs(x - y)) if it  0 else 0 for x in xrange(8)] for y in
xrange(8)]
...but in reality you should write something like this:
[[(lambda t: t if t  0 else 0)(2 - abs(x - y)) for x in xrange(8)]
for y in xrange(8)]
or this
[[(2 - abs(x - y)) if (2 - abs(x - y))  0 else 0 for x in xrange(8)]
for y in xrange(8)]
or even this
def foo(x, y):
if abs(x - y) == 0:
return 2
elif abs(x - y) == 1:
return 1
else:
return 0
[[foo(x, y) for x in xrange(8)] for y in xrange(8)]
It's not THAT matter, but it's just about readability and shortness in
some cases.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-12-01 Thread Steven D'Aprano
On Wed, 01 Dec 2010 15:18:32 -0800, Dmitry Groshev wrote:

 Here is a fresh example of what I meant by my first proposal. You need
 to build a matrix like this:
 2 1 0 ...
 1 2 1 ...
 0 1 2 ...
 ...
 ... 1 2 1
 ... 0 1 2
 You could do this by one-liner:
 [[(2 - abs(x - y)) if it  0 else 0 for x in xrange(8)] for y in
 xrange(8)]
 ...but in reality you should write something like this: [[(lambda t: t
 if t  0 else 0)(2 - abs(x - y)) for x in xrange(8)] for y in xrange(8)]
 or this
 [[(2 - abs(x - y)) if (2 - abs(x - y))  0 else 0 for x in xrange(8)]
 for y in xrange(8)]
 or even this
 def foo(x, y):
 if abs(x - y) == 0:
 return 2
 elif abs(x - y) == 1:
 return 1
 else:
 return 0
 [[foo(x, y) for x in xrange(8)] for y in xrange(8)]


All those one-liners give me a headache. At least your foo solution is 
understandable.

But I'd do it like this:

 array = [[0]*8 for _ in range(8)]
 for i in range(8):
... array[i][i] = 2
... if i  0: array[i][i-1] = 1
... if i  7: array[i][i+1] = 1
...
 pprint.pprint(array)
[[2, 1, 0, 0, 0, 0, 0, 0],
 [1, 2, 1, 0, 0, 0, 0, 0],
 [0, 1, 2, 1, 0, 0, 0, 0],
 [0, 0, 1, 2, 1, 0, 0, 0],
 [0, 0, 0, 1, 2, 1, 0, 0],
 [0, 0, 0, 0, 1, 2, 1, 0],
 [0, 0, 0, 0, 0, 1, 2, 1],
 [0, 0, 0, 0, 0, 0, 1, 2]]



When you stop trying to make everything a one-liner, it's amazing how 
readable you can make code :)



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-22 Thread Andreas Löscher
 if x in range(a, b): #wrong!
 it feels so natural to check it that way, but we have to write
 if a = x = b
 I understand that it's not a big deal, but it would be awesome to have
 some optimisations - it's clearly possible to detect things like that
 wrong one and fix it in a bytecode.


You can implement it yourself:

class between(object):
def __init__(self, a,b):
super(crang, self).__init__()
self.a=a
self.b=b
def __contains__(self, value):
return self.a = value = self.b

 12.45 in between(-100,100)
true


But do you need

a   x   b
a = x   b
a = x = b or
a   x = b ?

Sure, you could set a new parameter for this, but the normal way is not
broken at all.

Best


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-18 Thread Mark Wooding
Steven D'Aprano steve-remove-t...@cybersource.com.au writes:

 On Wed, 17 Nov 2010 16:31:40 +, Mark Wooding wrote:

  But I don't think that's the big problem with this proposal.  The real
  problem is that it completely changes the evaluation rule for the
  conditional expression.  (The evaluation rule is already pretty screwy:
  Python is consistently left-to-right -- except here.)

 Not quite...

  1+2*3
 7
  (1+2)*3
 9

You're wrong.  Python evaluates these left-to-right, as I said.
Parentheses override operator associativity; they don't affect
evaluation order at all.

Consider:

def say(x):
  print 'seen %s' % x
  return x

print say(1) + say(2) * say(3)
print (say(1) + say(2)) * say(3)

Run this program and you get

seen 1
seen 2
seen 3
7
seen 1
seen 2
seen 3
9

So definitely left-to-right.  Translating into reverse-Polish, say with
Dijkstra's shunting-yard algorithm, is enlightening: you get

1 2 3 * +

for the first and

1 2 + 3 *

for the second.  This preserves evaluation order; indeed, this is a
general property of the shunting-yard algorithm.

Finally, I quote from the language reference (5.13 of the 2.5 version),
just to show that (this time, at least) I'm not trying to impose
unfamiliar terminology, and that Python is defined to behave like this
and I'm not relying on implementation-specific details.  Alas, it also
highlights a genuine inconsistency, but one which might be considered
tolerable.

: 5.13 Evaluation order
: =
: 
: Python evaluates expressions from left to right. Notice that while
: evaluating an assignment, the right-hand side is evaluated before the
: left-hand side.
: 
: In the following lines, expressions will be evaluated in the
: arithmetic order of their suffixes:
: 
:  expr1, expr2, expr3, expr4
:  (expr1, expr2, expr3, expr4)
:  {expr1: expr2, expr3: expr4}
:  expr1 + expr2 * (expr3 - expr4)
:  func(expr1, expr2, *expr3, **expr4)
:  expr3, expr4 = expr1, expr2

So the above example is /explicitly/ dealt with in the language
reference, if only you'd cared to look.

 Not everything needs to be a one liner. If you need this, do it the old-
 fashioned way:

 t = foo()
 if not pred(t): t = default_value

I already explained how to write it as a one-liner:

t = (lambda y: y if pred(y) else default_value)(foo())

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-18 Thread Steven D'Aprano
On Thu, 18 Nov 2010 09:32:23 +, Mark Wooding wrote:

[...]
 You're wrong.  Python evaluates these left-to-right, as I said.
 Parentheses override operator associativity; they don't affect
 evaluation order at all.

Fair enough. I concede your point.


[...]
 Not everything needs to be a one liner. If you need this, do it the
 old- fashioned way:

 t = foo()
 if not pred(t): t = default_value
 
 I already explained how to write it as a one-liner:
 
 t = (lambda y: y if pred(y) else default_value)(foo())


I didn't say it couldn't be written as a one-liner. I suggested that it 
was better not to.

The costs of the one-liner are:

* reduced readability;
* requires an increased level of knowledge of the reader (what's lambda 
do?);
* runtime inefficiency (you create a function object, only to use it once 
then throw it away).

The advantages?

* one fewer line of code.

In my experience, the obsessiveness in which some people look for one-
liners is far from helpful, and goes against the spirit of Python. This 
isn't Perl :)


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-18 Thread Mark Wooding
Steven D'Aprano st...@remove-this-cybersource.com.au writes:

  Not everything needs to be a one liner. If you need this, do it the
  old- fashioned way:
 
  t = foo()
  if not pred(t): t = default_value
  
  I already explained how to write it as a one-liner:
  
  t = (lambda y: y if pred(y) else default_value)(foo())

 I didn't say it couldn't be written as a one-liner. I suggested that it 
 was better not to.

Ahh.  I misunderstood the first sentence above as dismissing the
possibility.  Sorry.  I agree that it's not a /nice/ one-liner. ;-)

 The costs of the one-liner are:

 * reduced readability;
 * requires an increased level of knowledge of the reader (what's lambda 
 do?);
 * runtime inefficiency (you create a function object, only to use it once 
 then throw it away).

This last can be obviated by a clever compiler (which, in our case, we
have not got).  The second could be considered an advantage: it's
educational!

 The advantages?

 * one fewer line of code.

 In my experience, the obsessiveness in which some people look for one-
 liners is far from helpful, and goes against the spirit of Python. This 
 isn't Perl :)

Oh, I agree completely.  On the other hand, it's just /fun/.  Python is
a fun language and using its features in playfully unusual ways is
enjoyable; like a good pun in a natural language.  Just as puns aren't
always appropriate in written language, playful code isn't always
appropriate either; but that doesn't mean it's never appropriate.

(Java has no sense of humour.  C++ does have, but it's a bit weird.)

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-17 Thread Christopher
 ? Of course we can write it as
     t = foo() if pred(foo()) else default_value
 but here we have 2 foo() calls instead of one. Why can't we write just
 something like this:
     t = foo() if pred(it) else default_value
 where it means foo() value?

i don't like magic names. what about:

t = foo() as v if pred(v) else default_value


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-17 Thread Mel
Christopher wrote:

 ? Of course we can write it as
 t = foo() if pred(foo()) else default_value
 but here we have 2 foo() calls instead of one. Why can't we write just
 something like this:
 t = foo() if pred(it) else default_value
 where it means foo() value?
 
 i don't like magic names. what about:
 
 t = foo() as v if pred(v) else default_value

!!  so: assignment inside an expression.

Mel.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-17 Thread Andreas Waldenburger
On Wed, 17 Nov 2010 10:18:51 -0500 Mel mwil...@the-wire.com wrote:

 Christopher wrote:
 
  ? Of course we can write it as
  t = foo() if pred(foo()) else default_value
  but here we have 2 foo() calls instead of one. Why can't we write
  just something like this:
  t = foo() if pred(it) else default_value
  where it means foo() value?
  
  i don't like magic names. what about:
  
  t = foo() as v if pred(v) else default_value
 
 !!  so: assignment inside an expression.
 
I like the idea of having an as ... if construct, though. :)

/W

-- 
To reach me via email, replace INVALID with the country code of my home 
country.  But if you spam me, I'll be one sour Kraut.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-17 Thread Mark Wooding
Christopher nadiasver...@gmail.com writes:

 i don't like magic names. what about:

 t = foo() as v if pred(v) else default_value

This is an improvement on `it'; anaphorics are useful in their place,
but they don't seem to fit well with Python.

But I don't think that's the big problem with this proposal.  The real
problem is that it completely changes the evaluation rule for the
conditional expression.  (The evaluation rule is already pretty screwy:
Python is consistently left-to-right -- except here.)

Evaluating a conditional expression starts in the middle, by evaluating
the condition.  If the condition is true, then it evaluates the
consequent (to the left); otherwise it evaluates the alternative (to the
right).  Screwy, but tolerable.

The proposal is to evaluate the /consequent/, stash it somewhere,
evaluate the condition, and then either output the consequent which we
evaluated earlier or the alternative which we must evaluate now.

Of course, the implementation must be able to tell which of these
evaluation rules to apply.  The marker to look for is either `it'
(original anaphoric proposal -- this is the real reason why `it' should
be a reserved word: its presence radically alters the evaluation rule,
so it ought to be a clear syntactic marker) or `as' (as suggested
above).

Elsewhere in the language, `as' is pretty consistent in what it does:
it provides a name for a thing described elsewhere (a `with' context
object, or an imported thing) -- but nothing else.  It certainly doesn't
suggest a change in the way anything else is evaluated.

1/x if x != 0 else None

works for any numeric x; it'd be really surprising to me if

1/x as hunoz if x != 0 else None

didn't.

-1 on this one.

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-17 Thread Steven D'Aprano
On Wed, 17 Nov 2010 16:31:40 +, Mark Wooding wrote:

 But I don't think that's the big problem with this proposal.  The real
 problem is that it completely changes the evaluation rule for the
 conditional expression.  (The evaluation rule is already pretty screwy:
 Python is consistently left-to-right -- except here.)

Not quite...

 1+2*3
7
 (1+2)*3
9

But other than that, I agree with your analysis for why Python should not 
be changed to allow:

t = foo() as v if pred(v) else default_value


Not everything needs to be a one liner. If you need this, do it the old-
fashioned way:

t = foo()
if not pred(t): t = default_value


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-16 Thread Steven D'Aprano
On Mon, 15 Nov 2010 22:40:00 -0700, Ian Kelly wrote:

 On 11/15/2010 10:26 PM, Steven D'Aprano wrote:
 t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar()

 What does it mean here?
 
 it would mean the result of the expression foo()+bar()+baz().  What
 else could it mean?

It could mean the last expression, baz(). Or the entire compound 
expression, foo()+bar()+baz().


 There are valid objections to the proposal, but the
 intended semantics seem perfectly clear.

Fair point, my example was terrible and didn't show the point that was 
clear in my head. Mea culpa. How about this instead?

t = foo()+it if pred(it) else bar()

Should that be a SyntaxError, or is `it` a variable that holds its value 
from statement to statement?

t = it

t = (foo() if pred(it) else bar()) if cond(it) else baz()


For what it's worth, Apple's defunct Hypertalk language had a couple of 
syntax elements very much like that. Hypertalk had a special variable, 
it, which you used like this:

get the number of cards
put it into field Card number

I trust I don't have to explain this? :)

Hypertalk also had a special function, the result, which worked 
something like this:

ask This is a dialog box. Please type your answer here:
put the result into field Your answer

(or you could use result() instead). Both of these worked quite well 
with Hypertalk, particularly with it's focus on non-programmers, but they 
were designed into the language from the beginning. In Python they would 
be the proverbial round peg in a square hole.

BTW, I frequently use it for iterators, and making it a reserved word 
would break a lot of my code. This would make me quite peeved.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-16 Thread Ian Kelly

On 11/16/2010 3:42 AM, Steven D'Aprano wrote:

On Mon, 15 Nov 2010 22:40:00 -0700, Ian Kelly wrote:


On 11/15/2010 10:26 PM, Steven D'Aprano wrote:

t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar()

What does it mean here?


it would mean the result of the expression foo()+bar()+baz().  What
else could it mean?


It could mean the last expression, baz(). Or the entire compound
expression, foo()+bar()+baz().


Unless the precedence rules were to change, the three expressions in the 
example that are operated on by the ternary are these:


1. foo()+bar()+baz()
2. pred(it)
3. baz()-foo()-bar()

So the antecedent would have to be one of those in order to make any 
sense at all, and obviously the only choice of those that would be 
useful is the first one.



There are valid objections to the proposal, but the
intended semantics seem perfectly clear.


Fair point, my example was terrible and didn't show the point that was
clear in my head. Mea culpa. How about this instead?

t = foo()+it if pred(it) else bar()

Should that be a SyntaxError, or is `it` a variable that holds its value
from statement to statement?


SyntaxError.  Implementing this without making 'it' a keyword would be 
very sloppy, IMO.


Another option would be to use a special variable named '__', similar to 
the variable '_' that the REPL uses to store the result of the last 
command.  This might break some existing code, but probably not very 
much.  Mostly it would just be confusing.



t = (foo() if pred(it) else bar()) if cond(it) else baz()


More problematic:

t = foo() if pred(bar() if pred2(it) else str(it)) else bar()

Does the first 'it' belong to the inner or outer ternary?  Probably the 
inner one.  What about the second 'it'?



BTW, I frequently use it for iterators, and making it a reserved word
would break a lot of my code. This would make me quite peeved.


I do the same, and yes, it would make upgrading a real pain.

Cheers,
Ian

--
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-16 Thread André
On Nov 15, 2:39 am, Dmitry Groshev lambdadmi...@gmail.com wrote:
 Here are some proposals. They are quite useful at my opinion and I'm
 interested for suggestions. It's all about some common patterns.
 First of all: how many times do you write something like
     t = foo()
     t = t if pred(t) else default_value

Never!

[snip]

 And the third. The more I use python the more I see how natural it
 can be. By natural I mean the statements like this:
     [x.strip() for x in reversed(foo)]
 which looks almost like a natural language. But there is some
 pitfalls:
     if x in range(a, b): #wrong!

This is true only if x is an integer such that  a = x  b

 it feels so natural to check it that way, but we have to write
     if a = x = b

This is true if x is an integer OR a float.   Two very different
cases, deserving of different notation.

André


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-16 Thread John Ladasky
On Nov 14, 11:30 pm, alex23 wuwe...@gmail.com wrote:
 On Nov 15, 4:39 pm, Dmitry Groshev lambdadmi...@gmail.com wrote:

      if x in range(a, b): #wrong!

 Only in Python 3.x, it's perfectly valid in Python 2.x. To achieve the
 same in Python 3.x, try:

     if x in list(range(a, b,)): # BUT SEE MY COMMENT BELOW

  it feels so natural to check it that way, but we have to write
      if a = x = b
  I understand that it's not a big deal, but it would be awesome to have
  some optimisations - it's clearly possible to detect things like that
  wrong one and fix it in a bytecode.

 This seems more like a pessimisation to me: your range version
 constructs a list just to do a single container check. That's a _lot_
 more cumbersome than two simple comparisons chained together.

Also: testing for the membership of x in a set is NOT the same thing
as testing using inequality operators.  The inequality operators will
return True for any FLOATING-POINT value within the range (a...b), but
the set test will only return True for set members.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread alex23
On Nov 15, 5:50 pm, Dmitry Groshev lambdadmi...@gmail.com wrote:
 On Nov 15, 10:30 am, alex23 wuwe...@gmail.com wrote:
  Personally, I like keeping object attribute references separate from
  dictionary item references.

 Your Python doesn't - dot notation is just a sugar for __dict__ lookup
 with default metaclass.

That's a gross oversimplification that tends towards wrong:

 class C(object):
...   def __init__(self):
... self._x = None
...   @property
...   def x(self): return self._x
...   @x.setter
...   def x(self, val): self._x = val
...
 c = C()
 c.x = 1
 c.x
1
 c.__dict__['x']
Traceback (most recent call last):
  File stdin, line 1, in module
KeyError: 'x'

But my concern has _nothing_ to do with the implementation detail of
how objects hold attributes, it's solely over the clarity that comes
from being able to visually tell that something is an object vs a
dictionary.

  This seems more like a pessimisation to me: your range version
  constructs a list just to do a single container check. That's a _lot_
  more cumbersome than two simple comparisons chained together.

 By wrong I meant exactly this. I told about compiler optimisation
 of statements like this so it would not construct a list.

So you want this:

  if x in range(1,10):

...to effectively emit the same bytecode as a chained comparison while
this:

  for x in range(1,10):

...produces a list/generator?

Never going to happen. Special cases aren't special enough to break
the rules. The standard form for chained comparisons can handle far
more complex expressions which your 'in' version could not: 0 = min
= max = 100
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Dmitry Groshev
On Nov 15, 12:03 pm, alex23 wuwe...@gmail.com wrote:
 On Nov 15, 5:50 pm, Dmitry Groshev lambdadmi...@gmail.com wrote:

  On Nov 15, 10:30 am, alex23 wuwe...@gmail.com wrote:
   Personally, I like keeping object attribute references separate from
   dictionary item references.

  Your Python doesn't - dot notation is just a sugar for __dict__ lookup
  with default metaclass.

 That's a gross oversimplification that tends towards wrong:

  class C(object):

 ...   def __init__(self):
 ...     self._x = None
 ...   @property
 ...   def x(self): return self._x
 ...   @x.setter
 ...   def x(self, val): self._x = val
 ... c = C()
  c.x = 1
  c.x
 1
  c.__dict__['x']

 Traceback (most recent call last):
   File stdin, line 1, in module
 KeyError: 'x'

 But my concern has _nothing_ to do with the implementation detail of
 how objects hold attributes, it's solely over the clarity that comes
 from being able to visually tell that something is an object vs a
 dictionary.

Oh, now I understand you. But this dotdict (or bunch) things don't
break anything. You still need to use it explicitly and it is very
useful if you need to serialize some JSON data about some entities.
s = [{name: Jhon Doe, age: 12}, {name: Alice,
age: 23}]
t = map(dotdict, json.loads(s))
t[0] #{'age': '12', 'name': 'Jhon Doe'}
t[0].age #'12'
Of course you can do this with namedtuple, but in fact this isn't a
tuple at all. It's a list of entities.

   This seems more like a pessimisation to me: your range version
   constructs a list just to do a single container check. That's a _lot_
   more cumbersome than two simple comparisons chained together.

  By wrong I meant exactly this. I told about compiler optimisation
  of statements like this so it would not construct a list.

 So you want this:

   if x in range(1,10):

 ...to effectively emit the same bytecode as a chained comparison while
 this:

   for x in range(1,10):

 ...produces a list/generator?

 Never going to happen. Special cases aren't special enough to break
 the rules. The standard form for chained comparisons can handle far
 more complex expressions which your 'in' version could not: 0 = min
 = max = 100

I know about chained comparisons, thanks. It's not about them. It's
about bytecode optimisation. But maybe you are right about Special
cases aren't special enough to break the rules. I kinda forgot that :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Hrvoje Niksic
Dmitry Groshev lambdadmi...@gmail.com writes:

 which looks almost like a natural language. But there is some
 pitfalls:
 if x in range(a, b): #wrong!
 it feels so natural to check it that way, but we have to write
 if a = x = b

For the record, you have to write:

if a = x  b:

Ranges are open on the ending side.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Mark Wooding
Dmitry Groshev lambdadmi...@gmail.com writes:

 First of all: how many times do you write something like
 t = foo()
 t = t if pred(t) else default_value
 ? Of course we can write it as
 t = foo() if pred(foo()) else default_value
 but here we have 2 foo() calls instead of one. Why can't we write just
 something like this:
 t = foo() if pred(it) else default_value
 where it means foo() value?

How about

t = (lambda y: y if pred(y) else default_value)(foo(x))

You could even package the lambda into a named function if you get bored
of typing or your aesthetic senses are offended.

 And the third. The more I use python the more I see how natural it
 can be. By natural I mean the statements like this:
 [x.strip() for x in reversed(foo)]
 which looks almost like a natural language. But there is some
 pitfalls:
 if x in range(a, b): #wrong!
 it feels so natural to check it that way, but we have to write
 if a = x = b

This, I think, is your error.  The test `x in range(a, b)' means the
same as `a = x  b' (only in Python 2 it builds a list and then throws
it away again).  Such half-open intervals turn out to be what you want
most of the time, and I think you'll avoid many bugs if you embrace them
rather than trying to cling to the fully-closed intervals above.

Python very definitely made the right decision to use half-open
intervals pervasively, e.g., for `rangeand 'in sequence slicing.  It's a
bad idea to fight against it.

Advantages of half-open intervals [a, b):

  * The number of elements is exactly b - a; closed intervals contain an
extra element which is often forgotten.

  * They compose and split nicely: if a = c = b then [a, b) is exactly
the disjoint union of [a, c) and [c, b).

  * Sums over these intervals are often better behaved; indeed, there's
a rather pretty analogy between sums on half-open intervals and
definite integrals which is lost if you use closed intervals.  (The
above two observations are special cases of this one.)  See Concrete
Mathematics (Graham, Knuth, Patashnik) for more on this.

  * It's easy to express an empty interval.  You can't do that if you
work entirely with closed intervals, but empty sets are an important
boundary case and it's annoying to have to handle them separately.

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Tim Chase

On 11/15/2010 12:39 AM, Dmitry Groshev wrote:

x in range optimisation


I've often thought this would make a nice O(1)-test lookup on an 
xrange() generator.  I don't have strong use-cases for it, but a 
bit of well-tested code in the standard library would save me 
from doing the math (along with its potential fenceposting and 
sign errors) the couple times I've reached for it.  Using the


  x in list(xrange(...)) # or range() depending your version

ends up with an O(n) lookup, though I suppose one could create a 
set() for O(1) lookups, but that still requires O(N) storage 
(where a mathematical lookup would involve O(1) storage *and* time)



foo() if foo() else bar()


This is usually indicative that you need to cache the 
object...something like


  etcc = expensive_to_calculate_constructor()
  result = foo(etcc) if test(etcc) else bar()

That way, you cache the potentially-expensive calculation, 
indicate to other readers-of-your-code that it's 
potentially-expensive, and enforce the use of that cache to 
ensure that you don't duplicate the expensive op.


-tkc






--
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Terry Reedy

On 11/15/2010 1:39 AM, Dmitry Groshev wrote:

Here are some proposals. They are quite useful at my opinion and I'm
interested for suggestions. It's all about some common patterns.
First of all: how many times do you write something like
 t = foo()
 t = t if pred(t) else default_value


Never. t=t unbinds and rebinds 't' to the same object. A waste.
Only rebind if needed.
if not pred(t): t = default_value


? Of course we can write it as
 t = foo() if pred(foo()) else default_value
but here we have 2 foo() calls instead of one. Why can't we write just
something like this:
 t = foo() if pred(it) else default_value
where it means foo() value?


Too magical.

I agree with most other comments.

--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Brian Blais
On Nov 15, 2010, at 1:39 AM, Dmitry Groshev wrote:

if x in range(a, b): #wrong!
 it feels so natural to check it that way, but we have to write
if a = x = b
 I understand that it's not a big deal, but it would be awesome to have
 some optimisations - it's clearly possible to detect things like that
 wrong one and fix it in a bytecode.

I don't think anyone has pointed this out, but these are *not* the same thing.  
observe:


x=3
if x in range(1,10):
print yay!

if 1=x10:
print yay too!

x=3.2
if x in range(1,10):
print yay!

if 1=x10:
print yay too!

output:

yay!
yay too!
yay too!


bb
-- 
Brian Blais
bbl...@bryant.edu
http://web.bryant.edu/~bblais
http://bblais.blogspot.com/



-- 
http://mail.python.org/mailman/listinfo/python-list


  1   2   >