Re: [Python-ideas] for/except/else

2017-03-02 Thread Pavol Lisy
On 3/1/17, Wolfgang Maier  wrote:

> - as explained by Nick, the existence of "except break" would strengthen
> the analogy with try/except/else and help people understand what the
> existing else clause after a loop is good for.

I was thinking bout this analogy:

1. try/else (without except) is SyntaxError. And seems useless.

2. try/break/except is backward compatible:

for i in L:
try:
break
except Something:
pass
except break:  # current code has not this so break is applied to for-block


3. for/raise/except (which is natural application of this analogy)
could reduce indentation but in my personal view that don't improve
readability (but I could be wrong)

It could help enhance "break" possibilities so "simplify" double break
in nested loops.

for
broken = False
for
if condition1():  # I like to "double break" here
raise SomeError()
if condition2():
break
except SomeError:
break
except break:
broken = True

4. for/finally may be useful
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Matthias Bussonnier
On Thu, Mar 2, 2017 at 9:13 PM, Mike Miller  wrote:

>
> It is a built-in singleton so rarely known that you will almost never
> encounter code with it, so you'll have it all to yourself.  Even on a python
> mailing list, in a thread about sentinels/singletons, it will not be
> mentioned.  Some may "consider it unnatural."  It is…
>
> …
>
> … (hint)
>
> … (wait for it)
>
> …
>

<3 the suspens ! I got it before the end though !

I'll  tell you my secret as well. I have my own
(https://pypi.python.org/pypi/undefined)
I've set it up to raise on __eq__ or __bool__ to enforce checking for identity.

-- 
M
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Mike Miller
Agreed, I've rarely found a need for a "second None" or sentinel either, but 
once every few years I do.  So, this use case doesn't seem to be common enough 
to devote special syntax or a keyword to from my perspective.


But, I'll let you know my secret.  I don't make my own sentinel, but rather use 
another singleton that is built-in already.  And if you squint just right, it 
even makes sense.


It is a built-in singleton so rarely known that you will almost never encounter 
code with it, so you'll have it all to yourself.  Even on a python mailing list, 
in a thread about sentinels/singletons, it will not be mentioned.  Some may 
"consider it unnatural."  It is…


…

… (hint)

… (wait for it)

…

>>> Ellipsis
Ellipsis


Don't think I've ever needed a "third None" but if I did I'd probably try an 
enum instead.


-Mike



On 2017-03-02 15:02, Barry Warsaw wrote:

On Mar 02, 2017, at 06:37 PM, Brett Cannon wrote:


So to me, there's actually two things being discussed. Do we need another
sentinel to handle the "None is valid" case, and do we want syntax to more
clearly delineate optional arguments?


No, and no (IMHO).

-Barry


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Delayed Execution via Keyword

2017-03-02 Thread Abe Dillon
Another problem I thought of was how this might complicate stack
tracebacks. If you execute the following code:

[1] a = ["hello", 1]
[2] b = "1" + 1
[3] a = "".join(a)
[4] print(a)

The interpreter would build a graph until it hit line 4 and was forced to
evaluate `a`. It would track `a` back to the branch:
[1]->[3]->

and raise an error from line [3] when you would expect line [2] to raise an
error first. I suppose it may be possible to catch any exceptions and force
full evaluation of nodes up to that point to find any preceding errors, but
that sounds like a harry proposition...

On Thu, Mar 2, 2017 at 8:10 PM, Abe Dillon  wrote:

> without special casing iteration how do you know that `x1 = next(xs)`
>> depends on the value of `x0`?
>
> `x1 = next(xs)` doesn't depend on the value of `x0`, it depends on the
> state of xs. In order to evaluate `next(xs)` you have to jump into the
> function call and evaluate the relevant expressions within, which will,
> presumably, mean evaluating the value of some place-holder variable or
> something, which will trigger evaluation of preceding, pending expressions
> that modify the value of that place-holder variable, which includes `x0 =
> next(xs)`.
>
> You do have a point, though; if the pending-execution graph has to be fine
> enough scale to capture all that, then it's a dubious claim that juggling
> such a construct would save any time over simply executing the code as you
> go. This, I believe, goes beyond iterators and gets at the heart of what
> Josh said:
>
> What you really do want is functional purity, which is a different concept
>> and one that python as a language can't easily provide no matter what.
>
>
> `next` is not a pure function, because it has side-effects: it changes
> state variables. Even if those side-effects can be tracked by the
> interpreter, they present a challenge. In the example:
> >>> log.warning(expensive_function())
>
> Where we want to avoid executing expensive_function(). It's likely that
> the function iterates over some large amount of data. According to the `x1
> = next(xs)` example, that means building a huge pending-execution graph in
> case that function does need to be evaluated, so you can track the iterator
> state changes all the way back to the first iteration before executing.
>
> Perhaps there's some clever trick I'm not thinking of to keep the graph
> small and only expand it as needed. I don't know. Maybe, like Joshua
> Morton's JIT example, you could automatically identify loop patterns and
> collapse them somehow. I guess special casing iteration would help with
> that, though it's difficult to see what that would look like.
>
>
>
> On Thu, Mar 2, 2017 at 7:30 PM, Joseph Jevnik  wrote:
>
>> without special casing iteration how do you know that `x1 = next(xs)`
>> depends on the value of `x0`? If you assume every operation depends on
>> every other operation then you have implemented an eager evaluation model.
>>
>> On Thu, Mar 2, 2017 at 8:26 PM, Abe Dillon  wrote:
>>
>>> I don't think you have to make a special case for iteration.
>>>
>>> When the interpreter hits:
>>> >>> print(x1)
>>>
>>> print falls under I/O, so it forces evaluation of x1, so we back-track
>>> to where x1 is evaluated:
>>> >>> x1 = next(xs)
>>>
>>> And in the next call, we find that we must evaluate the state of the
>>> iterator, so we have to back-track to:
>>> >>> x0 = next(xs)
>>>
>>> Evaluate that, then move forward.
>>>
>>> You essentially keep a graph of pending/unevaluated expressions linked
>>> by their dependencies and evaluate branches of the graph as needed. You
>>> need to evaluate state to navigate conditional branches, and whenever state
>>> is passed outside of the interpreter's scope (like I/O or multi-threading).
>>> I think problems might crop up in parts of the language that are pure
>>> c-code. For instance; I don't know if the state variables in a list
>>> iterator are actually visible to the Interpreter or if it's implemented in
>>> C that is inscrutable to the interpreter.
>>>
>>>
>>> On Mar 2, 2017 5:54 PM, "Joseph Jevnik"  wrote:
>>>
>>> Other things that scrutinize an expression are iteration or branching
>>> (with the current evaluation model). If `xs` is a thunk, then `for x in xs`
>>> must scrutinize `xs`. At first this doesn't seem required; however, in
>>> general `next` imposes a data dependency on the next call to `next`. For
>>> example:
>>>
>>> x0 = next(xs)
>>> x1 = next(xs)
>>>
>>> print(x1)
>>> print(x0)
>>>
>>> If `next` doesn't force computation then evaluating `x1` before `x0`
>>> will bind `x1` to `xs[0]` which is not what the eager version of the code
>>> does.
>>>
>>> To preserve the current semantics of the language you cannot defer
>>> arbitrary expressions because they may have observable side-effects.
>>> Automatically translating would require knowing ahead of time if a function
>>> can have observable side effects, 

Re: [Python-ideas] Delayed Execution via Keyword

2017-03-02 Thread Abe Dillon
>
> without special casing iteration how do you know that `x1 = next(xs)`
> depends on the value of `x0`?

`x1 = next(xs)` doesn't depend on the value of `x0`, it depends on the
state of xs. In order to evaluate `next(xs)` you have to jump into the
function call and evaluate the relevant expressions within, which will,
presumably, mean evaluating the value of some place-holder variable or
something, which will trigger evaluation of preceding, pending expressions
that modify the value of that place-holder variable, which includes `x0 =
next(xs)`.

You do have a point, though; if the pending-execution graph has to be fine
enough scale to capture all that, then it's a dubious claim that juggling
such a construct would save any time over simply executing the code as you
go. This, I believe, goes beyond iterators and gets at the heart of what
Josh said:

What you really do want is functional purity, which is a different concept
> and one that python as a language can't easily provide no matter what.


`next` is not a pure function, because it has side-effects: it changes
state variables. Even if those side-effects can be tracked by the
interpreter, they present a challenge. In the example:
>>> log.warning(expensive_function())

Where we want to avoid executing expensive_function(). It's likely that the
function iterates over some large amount of data. According to the `x1 =
next(xs)` example, that means building a huge pending-execution graph in
case that function does need to be evaluated, so you can track the iterator
state changes all the way back to the first iteration before executing.

Perhaps there's some clever trick I'm not thinking of to keep the graph
small and only expand it as needed. I don't know. Maybe, like Joshua
Morton's JIT example, you could automatically identify loop patterns and
collapse them somehow. I guess special casing iteration would help with
that, though it's difficult to see what that would look like.



On Thu, Mar 2, 2017 at 7:30 PM, Joseph Jevnik  wrote:

> without special casing iteration how do you know that `x1 = next(xs)`
> depends on the value of `x0`? If you assume every operation depends on
> every other operation then you have implemented an eager evaluation model.
>
> On Thu, Mar 2, 2017 at 8:26 PM, Abe Dillon  wrote:
>
>> I don't think you have to make a special case for iteration.
>>
>> When the interpreter hits:
>> >>> print(x1)
>>
>> print falls under I/O, so it forces evaluation of x1, so we back-track to
>> where x1 is evaluated:
>> >>> x1 = next(xs)
>>
>> And in the next call, we find that we must evaluate the state of the
>> iterator, so we have to back-track to:
>> >>> x0 = next(xs)
>>
>> Evaluate that, then move forward.
>>
>> You essentially keep a graph of pending/unevaluated expressions linked by
>> their dependencies and evaluate branches of the graph as needed. You need
>> to evaluate state to navigate conditional branches, and whenever state is
>> passed outside of the interpreter's scope (like I/O or multi-threading). I
>> think problems might crop up in parts of the language that are pure c-code.
>> For instance; I don't know if the state variables in a list iterator are
>> actually visible to the Interpreter or if it's implemented in C that is
>> inscrutable to the interpreter.
>>
>>
>> On Mar 2, 2017 5:54 PM, "Joseph Jevnik"  wrote:
>>
>> Other things that scrutinize an expression are iteration or branching
>> (with the current evaluation model). If `xs` is a thunk, then `for x in xs`
>> must scrutinize `xs`. At first this doesn't seem required; however, in
>> general `next` imposes a data dependency on the next call to `next`. For
>> example:
>>
>> x0 = next(xs)
>> x1 = next(xs)
>>
>> print(x1)
>> print(x0)
>>
>> If `next` doesn't force computation then evaluating `x1` before `x0` will
>> bind `x1` to `xs[0]` which is not what the eager version of the code does.
>>
>> To preserve the current semantics of the language you cannot defer
>> arbitrary expressions because they may have observable side-effects.
>> Automatically translating would require knowing ahead of time if a function
>> can have observable side effects, but that is not possible in Python.
>> Because it is impossible to tell in the general case, we must rely on the
>> user to tell us when it is safe to defer an expression.
>>
>> On Thu, Mar 2, 2017 at 6:42 PM, Abe Dillon  wrote:
>>
>>> I'm going to repeat here what I posted in the thread on lazy imports.
>>> If it's possible for the interpreter to determine when it needs to force
>>> evaluation of a lazy expression or statement, then why not use them
>>> everywhere? If that's the case, then why not make everything lazy by
>>> default? Why not make it a service of the language to lazify your code
>>> (analogous to garbage collection) so a human doesn't have to worry about
>>> screwing it up?
>>>
>>> There are, AFAIK, three things that *must* force 

Re: [Python-ideas] Delayed Execution via Keyword

2017-03-02 Thread Joseph Jevnik
without special casing iteration how do you know that `x1 = next(xs)`
depends on the value of `x0`? If you assume every operation depends on
every other operation then you have implemented an eager evaluation model.

On Thu, Mar 2, 2017 at 8:26 PM, Abe Dillon  wrote:

> I don't think you have to make a special case for iteration.
>
> When the interpreter hits:
> >>> print(x1)
>
> print falls under I/O, so it forces evaluation of x1, so we back-track to
> where x1 is evaluated:
> >>> x1 = next(xs)
>
> And in the next call, we find that we must evaluate the state of the
> iterator, so we have to back-track to:
> >>> x0 = next(xs)
>
> Evaluate that, then move forward.
>
> You essentially keep a graph of pending/unevaluated expressions linked by
> their dependencies and evaluate branches of the graph as needed. You need
> to evaluate state to navigate conditional branches, and whenever state is
> passed outside of the interpreter's scope (like I/O or multi-threading). I
> think problems might crop up in parts of the language that are pure c-code.
> For instance; I don't know if the state variables in a list iterator are
> actually visible to the Interpreter or if it's implemented in C that is
> inscrutable to the interpreter.
>
>
> On Mar 2, 2017 5:54 PM, "Joseph Jevnik"  wrote:
>
> Other things that scrutinize an expression are iteration or branching
> (with the current evaluation model). If `xs` is a thunk, then `for x in xs`
> must scrutinize `xs`. At first this doesn't seem required; however, in
> general `next` imposes a data dependency on the next call to `next`. For
> example:
>
> x0 = next(xs)
> x1 = next(xs)
>
> print(x1)
> print(x0)
>
> If `next` doesn't force computation then evaluating `x1` before `x0` will
> bind `x1` to `xs[0]` which is not what the eager version of the code does.
>
> To preserve the current semantics of the language you cannot defer
> arbitrary expressions because they may have observable side-effects.
> Automatically translating would require knowing ahead of time if a function
> can have observable side effects, but that is not possible in Python.
> Because it is impossible to tell in the general case, we must rely on the
> user to tell us when it is safe to defer an expression.
>
> On Thu, Mar 2, 2017 at 6:42 PM, Abe Dillon  wrote:
>
>> I'm going to repeat here what I posted in the thread on lazy imports.
>> If it's possible for the interpreter to determine when it needs to force
>> evaluation of a lazy expression or statement, then why not use them
>> everywhere? If that's the case, then why not make everything lazy by
>> default? Why not make it a service of the language to lazify your code
>> (analogous to garbage collection) so a human doesn't have to worry about
>> screwing it up?
>>
>> There are, AFAIK, three things that *must* force evaluation of lazy
>> expressions or statements:
>>
>> 1) Before the GIL is released, all pending lazy code must be evaluated
>> since the current thread can't know what variables another thread will try
>> to access (unless there's a way to explicitly label variables as "shared",
>> then it will only force evaluation of those).
>>
>> 2) Branching statements force evaluation of anything required to evaluate
>> the conditional clause.
>>
>> 3) I/O forces evaluation of any involved lazy expressions.
>>
>>
>> On Mon, Feb 20, 2017 at 7:07 PM, Joshua Morton > > wrote:
>>
>>> This comes from a bit of a misunderstanding of how an interpreter
>>> figures out what needs to be compiled. Most (all?) JIT compilers run code
>>> in an interpreted manner, and then compile subsections down to efficient
>>> machine code when they notice that the same code path is taken repeatedly,
>>> so in pypy something like
>>>
>>> x = 0
>>> for i in range(10):
>>> x += 1
>>>
>>> would, get, after 10-20 runs through the loop, turned into assembly that
>>> looked like what you'd write in pure C, instead of the very indirection and
>>> pointer heavy code that such a loop would be if you could take it and
>>> convert it to cpython actually executes, for example. So the "hot" code is
>>> still run.
>>>
>>> All that said, this is a bit of an off topic discussion and probably
>>> shouldn't be on list.
>>>
>>> What you really do want is functional purity, which is a different
>>> concept and one that python as a language can't easily provide no matter
>>> what.
>>>
>>> --Josh
>>>
>>> On Mon, Feb 20, 2017 at 7:53 PM Abe Dillon  wrote:
>>>
 On Fri, Feb 17, 2017, Steven D'Aprano wrote:

 JIT compilation delays *compiling* the code to run-time. This is a
 proposal for delaying *running* the code until such time as some other
 piece of code actually needs the result.


 My thought was that if a compiler is capable of determining what needs
 to be compiled just in time, then an interpreter might be able to determine
 

Re: [Python-ideas] Delayed Execution via Keyword

2017-03-02 Thread Abe Dillon
I don't think you have to make a special case for iteration.

When the interpreter hits:
>>> print(x1)

print falls under I/O, so it forces evaluation of x1, so we back-track to
where x1 is evaluated:
>>> x1 = next(xs)

And in the next call, we find that we must evaluate the state of the
iterator, so we have to back-track to:
>>> x0 = next(xs)

Evaluate that, then move forward.

You essentially keep a graph of pending/unevaluated expressions linked by
their dependencies and evaluate branches of the graph as needed. You need
to evaluate state to navigate conditional branches, and whenever state is
passed outside of the interpreter's scope (like I/O or multi-threading). I
think problems might crop up in parts of the language that are pure c-code.
For instance; I don't know if the state variables in a list iterator are
actually visible to the Interpreter or if it's implemented in C that is
inscrutable to the interpreter.


On Mar 2, 2017 5:54 PM, "Joseph Jevnik"  wrote:

Other things that scrutinize an expression are iteration or branching (with
the current evaluation model). If `xs` is a thunk, then `for x in xs` must
scrutinize `xs`. At first this doesn't seem required; however, in general
`next` imposes a data dependency on the next call to `next`. For example:

x0 = next(xs)
x1 = next(xs)

print(x1)
print(x0)

If `next` doesn't force computation then evaluating `x1` before `x0` will
bind `x1` to `xs[0]` which is not what the eager version of the code does.

To preserve the current semantics of the language you cannot defer
arbitrary expressions because they may have observable side-effects.
Automatically translating would require knowing ahead of time if a function
can have observable side effects, but that is not possible in Python.
Because it is impossible to tell in the general case, we must rely on the
user to tell us when it is safe to defer an expression.

On Thu, Mar 2, 2017 at 6:42 PM, Abe Dillon  wrote:

> I'm going to repeat here what I posted in the thread on lazy imports.
> If it's possible for the interpreter to determine when it needs to force
> evaluation of a lazy expression or statement, then why not use them
> everywhere? If that's the case, then why not make everything lazy by
> default? Why not make it a service of the language to lazify your code
> (analogous to garbage collection) so a human doesn't have to worry about
> screwing it up?
>
> There are, AFAIK, three things that *must* force evaluation of lazy
> expressions or statements:
>
> 1) Before the GIL is released, all pending lazy code must be evaluated
> since the current thread can't know what variables another thread will try
> to access (unless there's a way to explicitly label variables as "shared",
> then it will only force evaluation of those).
>
> 2) Branching statements force evaluation of anything required to evaluate
> the conditional clause.
>
> 3) I/O forces evaluation of any involved lazy expressions.
>
>
> On Mon, Feb 20, 2017 at 7:07 PM, Joshua Morton 
> wrote:
>
>> This comes from a bit of a misunderstanding of how an interpreter figures
>> out what needs to be compiled. Most (all?) JIT compilers run code in an
>> interpreted manner, and then compile subsections down to efficient machine
>> code when they notice that the same code path is taken repeatedly, so in
>> pypy something like
>>
>> x = 0
>> for i in range(10):
>> x += 1
>>
>> would, get, after 10-20 runs through the loop, turned into assembly that
>> looked like what you'd write in pure C, instead of the very indirection and
>> pointer heavy code that such a loop would be if you could take it and
>> convert it to cpython actually executes, for example. So the "hot" code is
>> still run.
>>
>> All that said, this is a bit of an off topic discussion and probably
>> shouldn't be on list.
>>
>> What you really do want is functional purity, which is a different
>> concept and one that python as a language can't easily provide no matter
>> what.
>>
>> --Josh
>>
>> On Mon, Feb 20, 2017 at 7:53 PM Abe Dillon  wrote:
>>
>>> On Fri, Feb 17, 2017, Steven D'Aprano wrote:
>>>
>>> JIT compilation delays *compiling* the code to run-time. This is a
>>> proposal for delaying *running* the code until such time as some other
>>> piece of code actually needs the result.
>>>
>>>
>>> My thought was that if a compiler is capable of determining what needs
>>> to be compiled just in time, then an interpreter might be able to determine
>>> what expressions need to be evaluated just when their results are actually
>>> used.
>>>
>>> So if you had code that looked like:
>>>
>>> >>> log.debug("data: %s", expensive())
>>>
>>> The interpreter could skip evaluating the expensive function if the
>>> result is never used. It would only evaluate it "just in time". This would
>>> almost certainly require just in time compilation as well, otherwise the
>>> byte code that calls the 

Re: [Python-ideas] Positional-only parameters

2017-03-02 Thread Victor Stinner
I am thinking at writing a PEP, yes. I need time to think about it, find
all corner cases. Maybe also include something for "optional parameter
without default value".

Don't expect it soon, I have some pending work to finish before :-)

Victor

Le 2 mars 2017 7:16 PM, "Brett Cannon"  a écrit :

> It seems all the core devs who have commented on this are in the positive
> (Victor, Yury, Ethan, Yury, Guido, Terry, and Steven; MAL didn't explicitly
> vote). So to me that suggests there's enough support to warrant writing a
> PEP. Are you up for writing it, Victor, or is someone else going to write
> it?
>
> On Tue, 28 Feb 2017 at 13:18 Victor Stinner 
> wrote:
>
>> Hi,
>>
>> For technical reasons, many functions of the Python standard libraries
>> implemented in C have positional-only parameters. Example:
>> ---
>> $ ./python
>> Python 3.7.0a0 (default, Feb 25 2017, 04:30:32)
>> >>> help(str.replace)
>> replace(self, old, new, count=-1, /)   # <== notice "/" at the end
>> ...
>> >>> "a".replace("x", "y")  # ok
>> 'a'
>>
>> >>> "a".replace(old="x", new="y")   # ERR!
>> TypeError: replace() takes at least 2 arguments (0 given)
>> ---
>>
>> When converting the methods of the builtin str type to the internal
>> "Argument Clinic" tool (tool to generate the function signature,
>> function docstring and the code to parse arguments in C), I asked if
>> we should add support for keyword arguments in str.replace(). The
>> answer was quick: no! It's a deliberate design choice.
>>
>> Quote of Yury Selivanov's message:
>> """
>> I think Guido explicitly stated that he doesn't like the idea to
>> always allow keyword arguments for all methods. I.e. `str.find('aaa')`
>> just reads better than `str.find(needle='aaa')`. Essentially, the idea
>> is that for most of the builtins that accept one or two arguments,
>> positional-only parameters are better.
>> """
>> http://bugs.python.org/issue29286#msg285578
>>
>> I just noticed a module on PyPI to implement this behaviour on Python
>> functions:
>>
>>https://pypi.python.org/pypi/positional
>>
>> My question is: would it make sense to implement this feature in
>> Python directly? If yes, what should be the syntax? Use "/" marker?
>> Use the @positional() decorator?
>>
>> Do you see concrete cases where it's a deliberate choice to deny
>> passing arguments as keywords?
>>
>> Don't you like writing int(x="123") instead of int("123")? :-) (I know
>> that Serhiy Storshake hates the name of the "x" parameter of the int
>> constructor ;-))
>>
>> By the way, I read that "/" marker is unknown by almost all Python
>> developers, and [...] syntax should be preferred, but
>> inspect.signature() doesn't support this syntax. Maybe we should fix
>> signature() and use [...] format instead?
>>
>> Replace "replace(self, old, new, count=-1, /)" with "replace(self,
>> old, new[, count=-1])" (or maybe even not document the default
>> value?).
>>
>> Python 3.5 help (docstring) uses "S.replace(old, new[, count])".
>>
>> Victor
>> ___
>> Python-ideas mailing list
>> Python-ideas@python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Victor Stinner
In my code, I commonly use a NOT_SET singleton used as default value. I
like this name for the test:

if arg is NOT_SET: ...

;-)

I use that when I want to behave differently when None is passed. And yes,
I have such code.

Victor

Le 2 mars 2017 9:36 AM, "M.-A. Lemburg"  a écrit :

On 02.03.2017 09:03, Serhiy Storchaka wrote:
> Function implemented in Python can have optional parameters with default
> value. It also can accept arbitrary number of positional and keyword
> arguments if use var-positional or var-keyword parameters (*args and
> **kwargs). But there is no way to declare an optional parameter that
> don't have default value. Currently you need to use the sentinel idiom
> for implementing this:
>
> _sentinel = object()
> def get(store, key, default=_sentinel):
> if store.exists(key):
> return store.retrieve(key)
> if default is _sentinel:
> raise LookupError
> else:
> return default
>
> There are drawback of this:
>
> * Module's namespace is polluted with sentinel's variables.
>
> * You need to check for the sentinel before passing it to other function
> by accident.
>
> * Possible name conflicts between sentinels for different functions of
> the same module.
>
> * Since the sentinel is accessible outside of the function, it possible
> to pass it to the function.
>
> * help() of the function shows reprs of default values. "foo(bar= object at 0xb713c698>)" looks ugly.
>
>
> I propose to add a new syntax for optional parameters. If the argument
> corresponding to the optional parameter without default value is not
> specified, the parameter takes no value. As well as the "*" prefix means
> "arbitrary number of positional parameters", the prefix "?" can mean
> "single optional parameter".
>
> Example:
>
> def get(store, key, ?default):
> if store.exists(key):
> return store.retrieve(key)
> try:
> return default
> except NameError:
> raise LookupError

Why a new syntax ? Can't we just have a pre-defined sentinel
singleton NoDefault and use that throughout the code (and also
special case it in argument parsing/handling)?

def get(store, key, default=NoDefault):
if store.exists(key):
return store.retrieve(key)
...

I added a special singleton NotGiven to our mxTools long ago for
this purpose.

--
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Delayed Execution via Keyword

2017-03-02 Thread Joseph Jevnik
Other things that scrutinize an expression are iteration or branching (with
the current evaluation model). If `xs` is a thunk, then `for x in xs` must
scrutinize `xs`. At first this doesn't seem required; however, in general
`next` imposes a data dependency on the next call to `next`. For example:

x0 = next(xs)
x1 = next(xs)

print(x1)
print(x0)

If `next` doesn't force computation then evaluating `x1` before `x0` will
bind `x1` to `xs[0]` which is not what the eager version of the code does.

To preserve the current semantics of the language you cannot defer
arbitrary expressions because they may have observable side-effects.
Automatically translating would require knowing ahead of time if a function
can have observable side effects, but that is not possible in Python.
Because it is impossible to tell in the general case, we must rely on the
user to tell us when it is safe to defer an expression.

On Thu, Mar 2, 2017 at 6:42 PM, Abe Dillon  wrote:

> I'm going to repeat here what I posted in the thread on lazy imports.
> If it's possible for the interpreter to determine when it needs to force
> evaluation of a lazy expression or statement, then why not use them
> everywhere? If that's the case, then why not make everything lazy by
> default? Why not make it a service of the language to lazify your code
> (analogous to garbage collection) so a human doesn't have to worry about
> screwing it up?
>
> There are, AFAIK, three things that *must* force evaluation of lazy
> expressions or statements:
>
> 1) Before the GIL is released, all pending lazy code must be evaluated
> since the current thread can't know what variables another thread will try
> to access (unless there's a way to explicitly label variables as "shared",
> then it will only force evaluation of those).
>
> 2) Branching statements force evaluation of anything required to evaluate
> the conditional clause.
>
> 3) I/O forces evaluation of any involved lazy expressions.
>
>
> On Mon, Feb 20, 2017 at 7:07 PM, Joshua Morton 
> wrote:
>
>> This comes from a bit of a misunderstanding of how an interpreter figures
>> out what needs to be compiled. Most (all?) JIT compilers run code in an
>> interpreted manner, and then compile subsections down to efficient machine
>> code when they notice that the same code path is taken repeatedly, so in
>> pypy something like
>>
>> x = 0
>> for i in range(10):
>> x += 1
>>
>> would, get, after 10-20 runs through the loop, turned into assembly that
>> looked like what you'd write in pure C, instead of the very indirection and
>> pointer heavy code that such a loop would be if you could take it and
>> convert it to cpython actually executes, for example. So the "hot" code is
>> still run.
>>
>> All that said, this is a bit of an off topic discussion and probably
>> shouldn't be on list.
>>
>> What you really do want is functional purity, which is a different
>> concept and one that python as a language can't easily provide no matter
>> what.
>>
>> --Josh
>>
>> On Mon, Feb 20, 2017 at 7:53 PM Abe Dillon  wrote:
>>
>>> On Fri, Feb 17, 2017, Steven D'Aprano wrote:
>>>
>>> JIT compilation delays *compiling* the code to run-time. This is a
>>> proposal for delaying *running* the code until such time as some other
>>> piece of code actually needs the result.
>>>
>>>
>>> My thought was that if a compiler is capable of determining what needs
>>> to be compiled just in time, then an interpreter might be able to determine
>>> what expressions need to be evaluated just when their results are actually
>>> used.
>>>
>>> So if you had code that looked like:
>>>
>>> >>> log.debug("data: %s", expensive())
>>>
>>> The interpreter could skip evaluating the expensive function if the
>>> result is never used. It would only evaluate it "just in time". This would
>>> almost certainly require just in time compilation as well, otherwise the
>>> byte code that calls the "log.debug" function would be unaware of the byte
>>> code that implements the function.
>>>
>>> This is probably a pipe-dream, though; because the interpreter would
>>> have to be aware of side effects.
>>>
>>>
>>>
>>> On Mon, Feb 20, 2017 at 5:18 AM,  wrote:
>>>
>>>
>>>
>>> > -Original Message-
>>> > From: Python-ideas [mailto:python-ideas-bounces+tritium-
>>> > list=sdamon@python.org] On Behalf Of Michel Desmoulin
>>> > Sent: Monday, February 20, 2017 3:30 AM
>>> > To: python-ideas@python.org
>>> > Subject: Re: [Python-ideas] Delayed Execution via Keyword
>>> >
>>> > I wrote a blog post about this, and someone asked me if it meant
>>> > allowing lazy imports to make optional imports easier.
>>> >
>>> > Someting like:
>>> >
>>> > lazy import foo
>>> > lazy from foo import bar
>>> >
>>> > So now if I don't use the imports, the module is not loaded, which
>>> could
>>> > also significantly speed up applications starting time with a lot of
>>> > 

Re: [Python-ideas] lazy use for optional import

2017-03-02 Thread Chris Angelico
On Fri, Mar 3, 2017 at 10:10 AM, Abe Dillon  wrote:
> I really think the whole "lazy" idea is misguided. If it's possible for the
> interpreter to determine automatically when it needs to force evaluation of
> a lazy expression or statement, then why not make *all* expressions and
> statements lazy by default? I think it's pretty clear when to force
> evaluation: 1) when the result is used in a control flow
> statement/expression 2) when the result is output (file, network, or other
> I/O)  and 3) evaluate all pending lazy code before releasing the GIL. At
> that point, why not make lazy evaluation an implicit feature of the
> language, like the garbage collector.

4) When the evaluation will have side effects.

Making everything lazy is fine when you can guarantee that there's no
visible effect (modulo performance) of evaluating things in a
different order, or not evaluating some of them at all. In Python,
that can't be guaranteed, so universal laziness is way too dangerous.
Think of all the problems people have with getting their heads around
multithreading, and consider that this is basically going to take your
code and turn it into a bunch of threads, and join on those threads
only when there's a reason to. Debugging becomes highly
non-deterministic, because adding a quick little 'print' call to see
what's going on might force evaluation a little sooner, which means X
happens before Y, but without that print, Y happens before X... aeons
of fun.

No, if laziness is added to Python, it *must* be under programmer control.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Barry Warsaw
On Mar 02, 2017, at 06:37 PM, Brett Cannon wrote:

>So to me, there's actually two things being discussed. Do we need another
>sentinel to handle the "None is valid" case, and do we want syntax to more
>clearly delineate optional arguments?

No, and no (IMHO).

-Barry


pgpULmSfZJDcd.pgp
Description: OpenPGP digital signature
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Abe Dillon
I honestly don't understand the reasoning behind using anything more
complex than a built-in sentinel value. Just plop "NotGiven" or whatever in
the built-ins and say "it's like None, but for the specific case of
optional parameters with no default value". Why prohibit people from
passing it to functions? That would just be an explicit way of saying: "I'm
not giving you a value for this parameter". Anything more than that is just
paranoia that people won't know how to use it in an expected manner.

I'm -0.5 on this proposal. It seems like it would add more confusion for
dubious benefit.

On Thu, Mar 2, 2017 at 2:07 PM, MRAB  wrote:

> On 2017-03-02 08:03, Serhiy Storchaka wrote:
>
>> Function implemented in Python can have optional parameters with default
>> value. It also can accept arbitrary number of positional and keyword
>> arguments if use var-positional or var-keyword parameters (*args and
>> **kwargs). But there is no way to declare an optional parameter that
>> don't have default value. Currently you need to use the sentinel idiom
>> for implementing this:
>>
>> _sentinel = object()
>> def get(store, key, default=_sentinel):
>>  if store.exists(key):
>>  return store.retrieve(key)
>>  if default is _sentinel:
>>  raise LookupError
>>  else:
>>  return default
>>
>> There are drawback of this:
>>
>> * Module's namespace is polluted with sentinel's variables.
>>
>> * You need to check for the sentinel before passing it to other function
>> by accident.
>>
>> * Possible name conflicts between sentinels for different functions of
>> the same module.
>>
>> * Since the sentinel is accessible outside of the function, it possible
>> to pass it to the function.
>>
>> * help() of the function shows reprs of default values. "foo(bar=> object at 0xb713c698>)" looks ugly.
>>
>>
>> I propose to add a new syntax for optional parameters. If the argument
>> corresponding to the optional parameter without default value is not
>> specified, the parameter takes no value. As well as the "*" prefix means
>> "arbitrary number of positional parameters", the prefix "?" can mean
>> "single optional parameter".
>>
>> Example:
>>
>> def get(store, key, ?default):
>>  if store.exists(key):
>>  return store.retrieve(key)
>>  try:
>>  return default
>>  except NameError:
>>  raise LookupError
>>
>> Alternative syntaxes:
>>
>> * "=" not followed by an expression: "def get(store, key, default=)".
>>
>> * The "del" keyword: "def get(store, key, del default)".
>>
>> This feature is orthogonal to supporting positional-only parameters.
>> Optional parameters without default value can be positional-or-keyword,
>> keyword-only or positional-only (if the latter is implemented).
>>
>> Could you use 'pass' as the pseudo-sentinel?
>
> Maybe also allow " is pass"/" is not pass" as tests for
> absence/presence.
>
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] lazy use for optional import

2017-03-02 Thread Abe Dillon
I really think the whole "lazy" idea is misguided. If it's possible for the
interpreter to determine automatically when it needs to force evaluation of
a lazy expression or statement, then why not make *all* expressions and
statements lazy by default? I think it's pretty clear when to force
evaluation: 1) when the result is used in a control flow
statement/expression 2) when the result is output (file, network, or other
I/O)  and 3) evaluate all pending lazy code before releasing the GIL. At
that point, why not make lazy evaluation an implicit feature of the
language, like the garbage collector.

On Wed, Mar 1, 2017 at 8:58 PM, Chris Barker  wrote:

> Going through machinations to satisfy PEP 8 makes no sense -- it's s style
> *guide* -- that's it.
>
> -CHB
>
>
> On Tue, Feb 28, 2017 at 3:31 PM, Nicolas Cellier <
> cont...@nicolas-cellier.net> wrote:
>
>> I have seen some interest into lazy functionality implementation.
>>
>> I wondered if it can be linked with optional import.
>>
>> PEP 8  authoritatively states:
>>
>> Imports are always put at the top of the file, just after any module
>> comments and docstrings, and before module globals and constants.
>>
>> So, if we want to stick to PEP8 with non mandatory import, we have to
>> catch the import errors, or jail the class or function using extra
>> functionnality.
>>
>> Why not using the potential lazy keyword to have a nice way to deal with
>> it?
>>
>> For example:
>>
>> lazy import pylab as pl  # do nothing for now
>>>
>>> # do stuff
>>>
>>> def plot(*args):
>>> pl.figure() # Will raise an ImportError at this point
>>> pl.plot(...)
>>>
>>
>> That way, our library will raise an ImportError only on plot func usage
>> with an explicit traceback : if matplotlib is not installed, we will have
>> the line where it is used for the first time and we will have the name of
>> the faulty library.
>>
>> ___
>> Python-ideas mailing list
>> Python-ideas@python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
>
>
> --
>
> Christopher Barker, Ph.D.
> Oceanographer
>
> Emergency Response Division
> NOAA/NOS/OR(206) 526-6959   voice
> 7600 Sand Point Way NE   (206) 526-6329   fax
> Seattle, WA  98115   (206) 526-6317   main reception
>
> chris.bar...@noaa.gov
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread MRAB

On 2017-03-02 08:03, Serhiy Storchaka wrote:

Function implemented in Python can have optional parameters with default
value. It also can accept arbitrary number of positional and keyword
arguments if use var-positional or var-keyword parameters (*args and
**kwargs). But there is no way to declare an optional parameter that
don't have default value. Currently you need to use the sentinel idiom
for implementing this:

_sentinel = object()
def get(store, key, default=_sentinel):
 if store.exists(key):
 return store.retrieve(key)
 if default is _sentinel:
 raise LookupError
 else:
 return default

There are drawback of this:

* Module's namespace is polluted with sentinel's variables.

* You need to check for the sentinel before passing it to other function
by accident.

* Possible name conflicts between sentinels for different functions of
the same module.

* Since the sentinel is accessible outside of the function, it possible
to pass it to the function.

* help() of the function shows reprs of default values. "foo(bar=)" looks ugly.


I propose to add a new syntax for optional parameters. If the argument
corresponding to the optional parameter without default value is not
specified, the parameter takes no value. As well as the "*" prefix means
"arbitrary number of positional parameters", the prefix "?" can mean
"single optional parameter".

Example:

def get(store, key, ?default):
 if store.exists(key):
 return store.retrieve(key)
 try:
 return default
 except NameError:
 raise LookupError

Alternative syntaxes:

* "=" not followed by an expression: "def get(store, key, default=)".

* The "del" keyword: "def get(store, key, del default)".

This feature is orthogonal to supporting positional-only parameters.
Optional parameters without default value can be positional-or-keyword,
keyword-only or positional-only (if the latter is implemented).


Could you use 'pass' as the pseudo-sentinel?

Maybe also allow " is pass"/" is not pass" as tests for 
absence/presence.


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] for/except/else

2017-03-02 Thread Joao S. O. Bueno
On 1 March 2017 at 06:37, Wolfgang Maier
 wrote:
> Now here's the proposal: allow an except (or except break) clause to follow
> for/while loops that will be executed if the loop was terminated by a break
> statement.

After rethinking over some code I've written in the past, yes, I agree
this change could be a nice one.
The simple fact that people are commenting that they could chage the
code to be an inner
function in order to break from nested "for" loops should be a hint
this syntax is useful. (I myself have done that with exceptions in some cases).

   js
 -><-
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Positional-only parameters

2017-03-02 Thread Brett Cannon
It seems all the core devs who have commented on this are in the positive
(Victor, Yury, Ethan, Yury, Guido, Terry, and Steven; MAL didn't explicitly
vote). So to me that suggests there's enough support to warrant writing a
PEP. Are you up for writing it, Victor, or is someone else going to write
it?

On Tue, 28 Feb 2017 at 13:18 Victor Stinner 
wrote:

> Hi,
>
> For technical reasons, many functions of the Python standard libraries
> implemented in C have positional-only parameters. Example:
> ---
> $ ./python
> Python 3.7.0a0 (default, Feb 25 2017, 04:30:32)
> >>> help(str.replace)
> replace(self, old, new, count=-1, /)   # <== notice "/" at the end
> ...
> >>> "a".replace("x", "y")  # ok
> 'a'
>
> >>> "a".replace(old="x", new="y")   # ERR!
> TypeError: replace() takes at least 2 arguments (0 given)
> ---
>
> When converting the methods of the builtin str type to the internal
> "Argument Clinic" tool (tool to generate the function signature,
> function docstring and the code to parse arguments in C), I asked if
> we should add support for keyword arguments in str.replace(). The
> answer was quick: no! It's a deliberate design choice.
>
> Quote of Yury Selivanov's message:
> """
> I think Guido explicitly stated that he doesn't like the idea to
> always allow keyword arguments for all methods. I.e. `str.find('aaa')`
> just reads better than `str.find(needle='aaa')`. Essentially, the idea
> is that for most of the builtins that accept one or two arguments,
> positional-only parameters are better.
> """
> http://bugs.python.org/issue29286#msg285578
>
> I just noticed a module on PyPI to implement this behaviour on Python
> functions:
>
>https://pypi.python.org/pypi/positional
>
> My question is: would it make sense to implement this feature in
> Python directly? If yes, what should be the syntax? Use "/" marker?
> Use the @positional() decorator?
>
> Do you see concrete cases where it's a deliberate choice to deny
> passing arguments as keywords?
>
> Don't you like writing int(x="123") instead of int("123")? :-) (I know
> that Serhiy Storshake hates the name of the "x" parameter of the int
> constructor ;-))
>
> By the way, I read that "/" marker is unknown by almost all Python
> developers, and [...] syntax should be preferred, but
> inspect.signature() doesn't support this syntax. Maybe we should fix
> signature() and use [...] format instead?
>
> Replace "replace(self, old, new, count=-1, /)" with "replace(self,
> old, new[, count=-1])" (or maybe even not document the default
> value?).
>
> Python 3.5 help (docstring) uses "S.replace(old, new[, count])".
>
> Victor
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Brett Cannon
On Thu, 2 Mar 2017 at 08:58 Ethan Furman  wrote:

> On 03/02/2017 08:13 AM, Joao S. O. Bueno wrote:
>
> > Is it just me that find that having the un-assigned parameter raise
> > NameError (or other exception) much more cumbersome than
> > havign a sentinel-value?
>
> No.  While clever, the hassle of figuring out if you have a parameter
> clearly outweighs the benefit of avoiding a
> sentinel value.
>
> It would be a different story if we had exception-catching expressions.  ;)
>

I don't like the NameError solution either.

What I would like to know is how common is this problem? That will help
frame whether this warrants syntax or just providing a sentinel in some
module in the stdlib that people can use (e.g. functools.NotGiven; I do
prefer MAL's naming of the sentinel). Sticking it into a module would help
minimize people from using it in places where None is entirely acceptable
and not confusing the whole community when people suddenly start peppering
their code with NotGiven instead of None for default values.

And if this is really common enough to warrant syntax, then I would want:

  def foo(a, b, opt?): ...

to represent that 'opt' is optional and if not provided by the user then it
is given the value of NotGiven (or None if we are just after a syntactic
shortcut to say "this argument is optional").

So to me, there's actually two things being discussed. Do we need another
sentinel to handle the "None is valid" case, and do we want syntax to more
clearly delineate optional arguments?
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] add __contains__ into the "type" object

2017-03-02 Thread Ethan Furman

-1.

It is already possible to specify what

  inst in cls

means by using a metaclass.  For example:

  class Color(enum.Enum):
 RED = 1
 GREEN = 2
 BLUE = 3

  some_var = Color.GREEN
  some_var in Color  # True
  some_var in enum.Enum  # False

Containment != isinstance()

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Joao S. O. Bueno
Is it just me that find that having the un-assigned parameter raise
NameError (or other exception) much more cumbersome than
havign a sentinel-value?

I definitely don't find it clever - for one, a common default parameter -
sentinel or not, can be replaced in  a single line of code by an
expression using "if" or "or", while the Exception raising variant
require a whole try-except block.

So, while I like the idea of simplifying the "sentinel idiom", I don't
find any suggestion here useful so far.

Maybe something to the stlib that would allow something along:

from paramlib import NoDefault, passed

def myfunc(a, b, count=NoDefault):
 if not passed(count):
  ...
 else:
  ...

That would simplify a bit the sentinel pattern, do not pollute the
namespace, and don't  need any new syntax, (and still allow "if"
expressions without a full try/except block)

On 2 March 2017 at 12:04, M.-A. Lemburg  wrote:
> On 02.03.2017 14:08, Serhiy Storchaka wrote:
>> On 02.03.17 12:04, M.-A. Lemburg wrote:
>>> This is not new syntax, nor is it a keyword. It's only a
>>> new singleton and it is well usable outside of function
>>> declarations as well, e.g. for class attributes which are
>>> not yet initialized (and which can accept None as value).
>>
>> If it is not a keyword, it could be used in expressions, e.g. assigned
>> to a variable or passed to a function. It could be monkey-patched or
>> hidden by accident (as True and False in Python 2).
>
> Yes, sure.
>
> My proposal was just to address the problems of
> changing Python syntax and making it possible to define
> positional only arguments in Python functions/methods in
> a backwards compatible way.
>
> The same could be had by adding a C function proxy to Python
> which then takes care of the error handling, since we already
> have the logic for C functions via PyArg_ParseTuple*().
> A decorator could then apply the proxy as needed or ignore this
> for older Python versions without breaking compatibility
> (or a PyPI extension could provide the same proxy logic for
> older versions).
>
> FWIW: I don't think the use case for positional only arguments
> to Python functions is strong enough to warrant breaking
> backwards compatibility by introducing new syntax.
>
> --
> Marc-Andre Lemburg
> eGenix.com
>
> Professional Python Services directly from the Experts (#1, Mar 02 2017)
 Python Projects, Coaching and Consulting ...  http://www.egenix.com/
 Python Database Interfaces ...   http://products.egenix.com/
 Plone/Zope Database Interfaces ...   http://zope.egenix.com/
> 
>
> ::: We implement business ideas - efficiently in both time and costs :::
>
>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
>Registered at Amtsgericht Duesseldorf: HRB 46611
>http://www.egenix.com/company/contact/
>   http://www.malemburg.com/
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Positional-only parameters

2017-03-02 Thread Victor Stinner
2017-03-02 14:23 GMT+01:00 Steven D'Aprano :
>> Replace "replace(self, old, new, count=-1, /)" with "replace(self,
>> old, new[, count=-1])" (or maybe even not document the default
>> value?).
>
> That isn't right. It would have to be:
>
> replace([self, old, new, count=-1])
>
> if all of the arguments are positional-only. But that makes it look like
> they are all optional! A very strong -1 to this.
>
>> Python 3.5 help (docstring) uses "S.replace(old, new[, count])".
>
> Should be:
>
> S.replace(old, new[, count], /)
>
> which shows that all three arguments are positional only, but only count
> is optional.

Oh, I didn't notice the weird count parameter: positional-only, but no
default value?

I would prefer to avoid weird parameters and use a syntax which can be
written in Python, like:

   def replace(self, old, new, /, count=-1): ...

When a function has more than 3 parameters, I like the ability to pass
arguments by keyword for readability:

   "xxx".replace("x", "y", count=2)

It's more explicit than:

   "xxx".replace("x", "y", 2)

By the way, I proposed once to convert open() parameters after
filename and mode to keyword-only arguments, but Guido didn't want to
break the backward compatibility ;-)

   open(filename, mode, *, buffering=-1, ...)

Victor
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Positional-only parameters

2017-03-02 Thread Victor Stinner
2017-03-01 21:52 GMT+01:00 Terry Reedy :
> + 1 also. When people write a Python equivalent of a built-in function for
> documentation or teaching purposes, they should be able to exactly mimic the
> API.

Yeah, Serhiy said basically the same thing: it's doable, but complex
without builtin support for positional-only arguments.

I dislike subtle differences between C and Python, and positional-only
is a major difference since it has a very visible effect on the API.

After having used PHP for years, I really enjoyed Python keyword
arguments and default values. I was very happy to not have to
"reimplement" the "keyword arguments with default values" feature in
each function (*).

Basically, I would like the same thing for positional-only arguments :-)

(*) Example (found on the Internet) of PHP code pattern for keywords, enjoy ;-)

function doSomething($arguments = array()) {
// set defaults
$arguments = array_merge(array(
"argument" => "default value",
), $arguments);

var_dump($arguments);
}

Victor
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 14:08, Serhiy Storchaka wrote:
> On 02.03.17 12:04, M.-A. Lemburg wrote:
>> This is not new syntax, nor is it a keyword. It's only a
>> new singleton and it is well usable outside of function
>> declarations as well, e.g. for class attributes which are
>> not yet initialized (and which can accept None as value).
> 
> If it is not a keyword, it could be used in expressions, e.g. assigned
> to a variable or passed to a function. It could be monkey-patched or
> hidden by accident (as True and False in Python 2).

Yes, sure.

My proposal was just to address the problems of
changing Python syntax and making it possible to define
positional only arguments in Python functions/methods in
a backwards compatible way.

The same could be had by adding a C function proxy to Python
which then takes care of the error handling, since we already
have the logic for C functions via PyArg_ParseTuple*().
A decorator could then apply the proxy as needed or ignore this
for older Python versions without breaking compatibility
(or a PyPI extension could provide the same proxy logic for
older versions).

FWIW: I don't think the use case for positional only arguments
to Python functions is strong enough to warrant breaking
backwards compatibility by introducing new syntax.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] add __contains__ into the "type" object

2017-03-02 Thread Ryan Hiebert
By itself, I don't see using the ``in`` syntax to check for ``instanceof`` as a 
big benefit, given the overhead of learning that new concept. However, given in 
the light of a bigger concept, I think it may make more sense.

If we accept that it may be desirable to work with types as set-like objects, 
apart from (in most cases) iteration, then some other shorthands become 
reasonable too.

Other set operators, such as::

list <= object  # issubclass(list, object)

Plus the other obvious comparisons.

Other set operators can be used for typing::

list | set   #  same or similar to typing.Union[list, set]
mixin1 & mixin2  # Represents classes that inherit from mixin1 and mixin2

When we bring typing into it, it would be cool if those resultant values also 
were able to do instance and subclass checks. They currently raise an error, 
but I think it would be possible to do if this were all built into ``type``.

And, of course, if we're bringing typing to ``type``, we can replace things 
like ``typing.List[int]`` with ``list[int]``, and putting those directly into 
signatures.

I think it would be somewhat odd to bring in *some* of the set operators to 
types, but leave off ``__contains__`` and inequality comparisons.


This is not a proposal of all of this, just pointing out that there are further 
applications to this concept. At least in the case of the typing examples, I 
think that there are some simplifications to be had by thinking this way. 
Reasons against also exist, of course, but like everything it's a trade-off to 
consider.


I have a repo that starts some of this, though it's currently broken due to 
lack of love in the middle of a refactor. I haven't tried to add any typing 
stuff, but that seems like an obvious extension. I wouldn't expect type 
checkers to work with a 3rd party module like this, but it could help 
demonstrate the ideas.

https://github.com/ryanhiebert/typeset

If anyone is interested enough to help flesh out this proof of concept, I'd be 
grateful for some collaboration, or being let know of other work like it.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Paul Moore
On 2 March 2017 at 14:24, Steven D'Aprano  wrote:
> I like this! If the caller doesn't provide a value, the parameter
> remains unbound and any attempt to look it up will give a NameError or
> UnboundLocalError.

Hmm. But those exceptions currently indicate with almost 100%
certainty, a programming error (usually a mis-spelled name or a
control flow error). The proposal makes them a normal runtime
behaviour, in certain circumstances. What would happen if you
mis-spelled the name of the optional parameter? You'd get a NameError
from using the wrong name, rather than from the user not supplying a
value.

I don't think re-using NameError is a good idea here.
Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Stephan Houben
So let's turn the question around:
Since Coverity is user-extensible (and supports Python),
can you write a Coverity rule which detects wrong use of some given
NoDefault sentinel
with a useful level of reliability?

Actually I feel this should be feasible.

(And if so, mission accomplished?)

Stephan

2017-03-02 15:18 GMT+01:00 Chris Angelico :
> On Fri, Mar 3, 2017 at 1:15 AM, Stephan Houben  wrote:
>> I do not think such a magic linter can be written.
>> It seems an obvious instance of the Halting Problem to me.
>
> Yeah it can :) Static analysis is pretty impressive these days. Check
> out tools like Coverity, which can analyse your source code and tell
> you that, at this point in the code, it's possible for x to be >100
> and y to have only 100 bytes of buffer, and then you index past a
> buffer. You could do the same to track down the origin of an object in
> Python.
>
> However, I think this is far from an ideal solution to the problem.
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Steven D'Aprano
On Thu, Mar 02, 2017 at 10:03:29AM +0200, Serhiy Storchaka wrote:

> I propose to add a new syntax for optional parameters. If the argument 
> corresponding to the optional parameter without default value is not 
> specified, the parameter takes no value. As well as the "*" prefix means 
> "arbitrary number of positional parameters", the prefix "?" can mean 
> "single optional parameter".

I like this! If the caller doesn't provide a value, the parameter 
remains unbound and any attempt to look it up will give a NameError or 
UnboundLocalError.

The only question is, how often do we need a function with optional 
parameter that don't have a default? I've done it a few times, and used 
the sentinel trick, but I'm not sure this is common enough to need 
support from the compiler.

It is a really clever solution though.


 
> Alternative syntaxes:
> 
> * "=" not followed by an expression: "def get(store, key, default=)".

Too easy to happen by accident if you accidently forget to add the 
default, or delete it.


> * The "del" keyword: "def get(store, key, del default)".

This feature has nothing to do with del.


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Chris Angelico
On Fri, Mar 3, 2017 at 1:15 AM, Stephan Houben  wrote:
> I do not think such a magic linter can be written.
> It seems an obvious instance of the Halting Problem to me.

Yeah it can :) Static analysis is pretty impressive these days. Check
out tools like Coverity, which can analyse your source code and tell
you that, at this point in the code, it's possible for x to be >100
and y to have only 100 bytes of buffer, and then you index past a
buffer. You could do the same to track down the origin of an object in
Python.

However, I think this is far from an ideal solution to the problem.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Steven D'Aprano
On Thu, Mar 02, 2017 at 01:08:42PM +0100, M.-A. Lemburg wrote:

> Sorry for the confusion. NoDefault would be usable just like
> any other singleton.

But that is exactly the trouble! We already have a singleton to indicate 
"no default" -- that is spelled None.

Occasionally, we need to allow None as a legitimate value, not just as a 
sentinel indicating a missing value. So the current practice is to 
create your own sentinel. That just pushes the problem back one more 
level: what happens when you have a function where the new NoDefault 
singleton is a legitimate value? You need a *third* sentinel value. And 
a fourth, and so on...


> There would only be one case where it would cause an exception,
> namely when you declare a parameter as having NoDefault as value.
> This would trigger special logic in the argument parsing code to
> disallow using that parameter as keyword parameter.

Did you miss Serhiy's comment?

Optional parameters without default value can be 
positional-or-keyword, keyword-only or positional-only (if 
the latter is implemented).

It doesn't matter whether the parameter is positional or keyword, or how 
you call the function:

f(NoDefault)
f(x=NoDefault)

the effect should be the same.

But I think that's the wrong solution. If it were a good solution, we 
should just say that None is the "No Default" value and prohibit passing 
None as an argument. But of course we can't do that, even if we were 
willing to break backwards compatibility. There are good reasons for 
passing None as a legitimate value, and there will be good reasons for 
passing NoDefault as a legitimate value too.

The problem with having a special value that means "no value" is that it 
actually is a value. Serhiy has a good idea here: cut the gordian knot 
by *avoiding having a value at all*. The parameter name remains unbound. 
If you don't pass a value for the optional parameter, and then try to 
access the parameter, you get a NameError exception! That's really 
clever and I like it a lot.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Paul Moore
On 2 March 2017 at 13:11, Serhiy Storchaka  wrote:
> On 02.03.17 14:20, Paul Moore wrote:
>>
>> So I guess I'm +0.5 on the proposed "positional only parameters"
>> syntax, and -1 on any form of new language-defined sentinel value.
>
>
> My proposition is not about "positional-only parameters".

Bah, sorry. I'm getting muddled between two different threads. I'm not
having a good day, it seems :-(

On the proposed feature, I don't like any of the proposed syntaxes
(I'd rate "default=" with no value as the least bad, but I don't like
it much; "default?" as opposed to "?default" is a possible option).
I'm not convinced that the version using the new syntax is any easier
to read or understand - the sentinel pattern is pretty well-understood
by now, and a built-in replacement would need to result in noticeably
simpler code (which this proposal doesn't seem to).

Agreed that the help() output is ugly. It would of course be possible
to give the sentinel a nicer repr, if you wanted:

>>> class Sentinel(object):
... def __repr__(self): return ""
...
>>> _sentinel = Sentinel()
>>> def get(store, key, default=_sentinel):
...   pass
...
>>> help(get)
Help on function get in module __main__:

get(store, key, default=)

Whether it's worth doing this depends on the application, of course
(just like it's possible to hide the name of the sentinel if it
matters sufficiently).

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] add __contains__ into the "type" object

2017-03-02 Thread Chris Angelico
On Fri, Mar 3, 2017 at 12:44 AM, Steven D'Aprano  wrote:
> Compare to the OP's suggestion:
>
> 23 in int
>
> This doesn't even make sense unless you have been exposed to a very
> small subset of theoretical computer science which treats classes as
> sets and instances as elements of those sets. To everyone else,
> especially those with a background in "ordinary" OOP, it looks like
> nonsense.
>
> (Personally, I'm a bit dubious about conflating is-a and element-of
> operations in this way, it feels like a category mistake to me, but for
> the sake of the argument I'll accept it.)

I've seen languages in which types can be the RHO of 'is', so this
would look like:

23 is int

Obviously that depends on types not themselves being first-class
objects, but it makes a lot more sense than a containment check.

But I'm trying to think how frequently I do *any* type checking in
production code. It's not often. It doesn't need syntax.
isinstance(23, int) works fine.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] add __contains__ into the "type" object

2017-03-02 Thread Steven D'Aprano
On Thu, Mar 02, 2017 at 04:23:08AM +0100, Jürgen A. Erhard wrote:

> > The OP seems to be proposing that we reflect this identity between
> > types and sets in Python by spelling "isinstance(obj, T)" as "obj in
> > T" and "issubclass(S, T)" as "S <= T". This proposal has some solid
> > theory behind it and I don't think it would be hard to implement, but
> > it doesn't seem like a particularly useful change to me. It wouldn't
> > really enable anything we can't do now, and it may be confusing to
> > people reading code that "obj in list" does something completely
> > different from "obj in list()".
> 
> So?  Compare to "fn" vs "fn()" now.  Yes, some people are confused.
> So what.  You *do* have to learn things.

I don't understand what this comparison is supposed to show. `fn` is a 
name. `fn()` does a function call on whatever object is bound to `fn`. 
How is that relevant to the question of adding a completely separate 
set-like interface to isinstance and issubclass?


> And "enable anything we can't do now".  That argument was used any
> number of times on this list, and even before this very list even
> existed.

It has been used many times. That is because it is a GOOD argument. We 
don't just add every single random feature that people can think of. 
("Hey, wouldn't it be AWESOME if Class*str returned a list of class 
methods that contained the string in their name???") The new 
functionality, spelling or syntax has to add some benefit to make up for 
the extra cost:

- the cost to develop this new feature or syntax;
- the cost to write new tests for this feature;
- the cost to document it;
- the cost to documentation in books and the web that are now
  obsolete or incorrect;
- the cost for people to learn this feature;
- the cost for people to decide whether to use the old or the
  new spelling; 

and so forth. 


> Still, we got decorators (they don't enable anything we
> couldn't do without them, and we actually can still do what they do
> without using them).

Indeed, but you are missing that decorator syntax brings some VERY 
important benefits that are a clear win over the old way:

@decorate
def spam():
...


versus 

def spam():
...

spam = decorate(spam)


The decorator syntax avoids writing the function name three times, but 
more importantly, it puts the decoration right at the start of the 
function, next to the signature, where it is more obvious and easier to 
see, instead of way down the end, which might be many lines or even 
pages away. That's a very big win that makes decorator syntax the One 
Obvious Way to decorate functions and classes.

Compare to the OP's suggestion:

23 in int

This doesn't even make sense unless you have been exposed to a very 
small subset of theoretical computer science which treats classes as 
sets and instances as elements of those sets. To everyone else, 
especially those with a background in "ordinary" OOP, it looks like 
nonsense.

(Personally, I'm a bit dubious about conflating is-a and element-of 
operations in this way, it feels like a category mistake to me, but for 
the sake of the argument I'll accept it.)

So the benefit applies only to a tiny subset of users, but the cost is 
carried by everyone.


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Positional-only parameters

2017-03-02 Thread Steven D'Aprano
On Tue, Feb 28, 2017 at 10:17:31PM +0100, Victor Stinner wrote:

> My question is: would it make sense to implement this feature 
[positional only parameters]
> in Python directly? 

+0 on positional-only parameters.


> If yes, what should be the syntax? Use "/" marker?

I think that / makes a nice pun with * and is easy to remember.

I dislike the proposed double-leading-only underscore convention, as 
that makes the names look like *private* parameters the caller shouldn't 
provide at all. And it leads to confusion:

def function(__a, b, _c, * __d):
...

So __a is positional-only, b could be positional or keyword, _c is 
private, and __d is keyword-only but just happens to start with two 
underscores. Yuck.

I think that [...] is completely unacceptable. It is a very common 
convention to use square brackets to flag optional arguments when 
writing function signatures in documentation, e.g.:

Help on class zip in module builtins:

class zip(object)
 |  zip(iter1 [,iter2 [...]]) --> zip object


It would be confusing to have [...] have syntactic meaning different to 
that convention.


> Use the @positional() decorator?

I suppose a positional() decorator would be useful for backporting, but 
I wouldn't want it to be the One Obvious Way to get positional 
arguments.


> By the way, I read that "/" marker is unknown by almost all Python
> developers, 

Of course it is not well known -- it is only new, and not legal syntax 
yet! Unless they are heavily using Argument Clinic they probably won't 
recognise it.


> and [...] syntax should be preferred, but
> inspect.signature() doesn't support this syntax. Maybe we should fix
> signature() and use [...] format instead?

-1


> Replace "replace(self, old, new, count=-1, /)" with "replace(self,
> old, new[, count=-1])" (or maybe even not document the default
> value?).

That isn't right. It would have to be:

replace([self, old, new, count=-1])

if all of the arguments are positional-only. But that makes it look like 
they are all optional! A very strong -1 to this.


> Python 3.5 help (docstring) uses "S.replace(old, new[, count])".

Should be:

S.replace(old, new[, count], /)

which shows that all three arguments are positional only, but only count 
is optional.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Serhiy Storchaka

On 02.03.17 14:20, Paul Moore wrote:

So I guess I'm +0.5 on the proposed "positional only parameters"
syntax, and -1 on any form of new language-defined sentinel value.


My proposition is not about "positional-only parameters".


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] get() method for list and tuples

2017-03-02 Thread Steven D'Aprano
On Wed, Mar 01, 2017 at 02:56:44AM +0100, Michel Desmoulin wrote:

> > first_item = (alist[0:1] or ["ham"])[0]
> 
> Come on, I've been doing Python for more than a decade and never saw
> anybody doing that. Even reading it in a code would make me scratch my
> head for a moment with a "what is it doing that for?".

These days, it might be better to write it as:

first_item = alist[0] if len(alist) else "ham"

but I remember the days when slicing was normal and using the `or` trick 
was standard operating procedure.


> You are trying to hard to provide a counter argument here.

In context, all I'm saying is that you don't *have* to catch IndexError. 
There are alternatives. That is all.


> Me, I have to deal SOAP government systems, mongodb based API built by
> teenagers, geographer data set exports and FTP + CSV in marina systems
> (which I happen to work on right now).
> 
> 3rd party CSV, XML and JSON processing are just a hundred of lines of
> try/except on indexing because they have many listings, data positions
> is important and a lot of system got it wrong, giving you inconsistent
> output with missing data and terrible labeling.

This is all very well and good, and I feel your pain for having to deal 
with garbage data, but I don't see how this helps you. You talk about 
missing data, but lists cannot contain missing data from the middle. 
There's no such thing as a list like:

[0, 1, 2, 3, , , , , , , 10, 11, 12]

where alist[3] and alist[10] will succeed but alist[4] etc will raise 
IndexError. So I'm still trying to understand what this proposal gets 
you that wouldn't be better solved using (say) itertools.zip_longest or 
a pre-processing step to clean up your data.


> And because life is unfair, the data you can extract is often a mix of
> heterogeneous mappings and lists / tuples. And your tool must manage the
> various versions of the data format they send to you, some with
> additional fields, or missing ones. Some named, other found by position.

Maybe I'm underestimating just how awful your data is, but I'm having 
difficulty thinking of a scenario where you don't know what kind of 
object you are processing and have to write completely type-agnostic 
code:

for key_or_index in sequence_of_keys_or_indexes:
result = sequence_or_mapping[key_or_index]


I'm sure that there is lots of code where you iterate over dicts:

for key in keys:
result = mapping.get(key, default)

and likewise code where you process lists:

for i in indexes:
try:
result = sequence[i]
except IndexError:
result = default

# could be re-written using a helper function:
for i in indexes:
result = get(sequence, i default)

but I've never come across a data-processing situation where I didn't 
know which was which.

That second version with the helper function would be *marginally* nicer 
written as a method call. I grant you that!


> This summer, I had to convert a data set provided by polls in africa
> through an android form, generated from an XML schema, send as json
> using Ajax, then stored in mongodb... to an excel spread sheet (and also
> an HTML table and some JS graphs for good measure).
> 
> Needingless to say I dealt with a lot of IndexError. Grepping the
> project gives me:
> 
> grep -R IndexError | wc -l
> 33
> 
> In contrast I have 32 KeyError (most of them to allow lazy default
> value), and 3 decorators.

So 33 is "a lot", but 32 KeyErrors is "in contrast" and presumably a 
little.


> Apparently IndexError is an important error because if I grep the
> virtualenv of the project:
> 
> grep -R IndexError | wc -l
> 733
> 
> Ok, it's a pretty large project with 154 dependancies, but it's still
> almost 7 IndexError by package on average. So it's not a rare use case.

You don't know that every one of those can be replaced by list.get(). 
Some of them might be raising IndexError; some of them may be 
documenting that a function or method raises IndexError; etc.


> I also see it regularly in my classes. Students try it because they
> learned it works with dict. It makes sense.

I never said it didn't. But I wonder whether it gives *enough* benefit 
to be worth while.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] add __contains__ into the "type" object

2017-03-02 Thread Clint Hepner

> On 2017 Mar 2 , at 2:53 a, Stephan Houben  wrote:
> 
> A crucial difference between a set and a type is that you cannot
> explicitly iterate over the elements of a type, so while we could implement
> 
> x in int
> 
> to do something useful, we cannot make
> 
> for x in int:
>print(x)
> 

__contains__ was introduced to provide a more efficient test than to simply 
iterate over the elements one by one. I don’t see why something has to be 
iterable
in order to implement __contains__, though.

class PositiveInts(int):
def __contains__(self, x):
return x > 0

N = PostiveInts()

> Because if we could, we could implement Russell's paradox in Python:
> 
> R = set(x for x in object if x not in x)
> 
> print(R in R)

object is not the equivalent of the paradoxical set of all sets. It’s closer to 
the set of
all valid Python values. That includes all valid Python set values, but a Python
set is not mathematical set; it’s a *finite* collection of *hashable* values.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Chris Angelico
On Thu, Mar 2, 2017 at 11:22 PM, Stephan Houben  wrote:
> Would this also apply if we provide or capture the keyword arguments using
> ** ?
>
> I.e.
> f(**{"x": NoDict})
>
> (lambda **kw: kw)(x=NoDict)
>
> In that case I see a problem with this idiom:
>
> newdict = dict(**olddict)
>
> This would now start throwing errors in case any of the values of olddict
> was NoDefault.
>

You shouldn't be returning NoDefault anywhere, though, so the only
problem is that the error is being reported in the wrong place. If
this were to become syntax, enhanced linters could track down exactly
where NoDefault came from, and report the error, because that's really
where the bug is.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 13:22, Stephan Houben wrote:
> OK, I get it, I think.
> 
> I presume it is really the object identity which matters, not the syntax,
> so:
> 
> y = NoDefault
> f(x=y)
> 
> would be equally an error.

Yes.

> Would this also apply if we provide or capture the keyword arguments using
> ** ?
> 
> I.e.
> f(**{"x": NoDict})

I think you meant NoDefault here.

> (lambda **kw: kw)(x=NoDict)
> 
> In that case I see a problem with this idiom:
> 
> newdict = dict(**olddict)
> 
> This would now start throwing errors in case any of the values of olddict
> was NoDefault.

Continuing the example, this case would throw an error as well:

kwargs = {'x': NoDefault)

f(**kwargs)
e.g. TypeError('x is a positional only parameter')

However, only because f "declared" x as optional positional
parameter.

If you'd pass the same dict to a function g as in:

def g(x):
pass

g(**kwargs)

it would not raise an exception, since Python functions always
allow passing in keyword parameters for positional parameters
(unlike C functions, which only allow this if configured that way).

> Stephan
> 
> 
> 
> 2017-03-02 13:08 GMT+01:00 M.-A. Lemburg :
> 
>> On 02.03.2017 12:31, Stephan Houben wrote:
>>> I am not sure if I fully understand the proposal then.
>>>
>>> NoDefault would be special syntax so that this would be disallowed:
>>>
>>> f(NoDefault)
>>>
>>> but this would be allowed:
>>> def f(x=NoDefault):
>>>...
>>>
>>> and also this:
>>>
>>> x is NoDefault
>>>
>>> So this would seem to require an exhaustive list of syntactic contexts
>>> in which NoDefault is allowed. I mean, can I do:
>>>
>>> x = NoDefault
>>>
>>> ?
>>>
>>> I observe that I can always get to the underlying NoDefault object in
>> this
>>> way:
>>>
>>> (lambda x=NoDefault:x)()
>>>
>>> So what happens if I do:
>>>
>>> f((lambda x=NoDefault:x)())
>>>
>>> ?
>>
>> Sorry for the confusion. NoDefault would be usable just like
>> any other singleton.
>>
>> There would only be one case where it would cause an exception,
>> namely when you declare a parameter as having NoDefault as value.
>> This would trigger special logic in the argument parsing code to
>> disallow using that parameter as keyword parameter.
>>
>> Example:
>>
>> def f(x=NoDefault):
>> # x is an optional positional parameter
>> if x is NoDefault:
>> # x was not passed in as parameter
>> ...
>> else:
>> # x was provided as parameter
>> ...
>>
>> These would all work fine:
>>
>> f()
>> f(1)
>> f(None)
>>
>> This would trigger an exception in the argument parsing code:
>>
>> f(x=NoDefault)
>>
>> e.g. TypeError('x is a positional only parameter')
>>
>> This would not trigger an exception:
>>
>> f(NoDefault)
>>
>> since x is not being used as keyword parameter and the
>> function f may want to pass the optional positional parameter
>> down to other functions with optional positional paramters
>> as well.
>>
>> Is this clearer now ?
>>
>> Note: The name of the singleton could be something else
>> as well, e.g. NoKeywordParameter :-)
>>
>>> Stephan
>>>
>>>
>>> 2017-03-02 12:15 GMT+01:00 M.-A. Lemburg :
>>>
 On 02.03.2017 11:22, Stephan Houben wrote:
> In cases like this I would recommend creating the sentinel yourself:
>
> NoDefault = object()
>
> def get(store, key, default=NoDefault):
>if default is NoDefault:
> # do something
>
> You can arrange to not export NoDefault so that the client code cannot
 even
> access
> the sentinel value.

 Yes, I know... I've been using the mxTools NotGiven since 1998.

> This is strictly preferable over having yet another global
> value meaning "no value", since that just moves the goal posts:
> clients will complain they cannot pass in a default=NoDefault and get
 back
> NoDefault.

 Not really. NoDefault would mean: no value provided, not that
 you don't want a value. As a result, passing NoDefault would
 not be allowed, since then you'd be providing a value :-)

> Stephan
>
>
> 2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :
>
>> On 02.03.2017 10:06, Serhiy Storchaka wrote:
>>> On 02.03.17 10:36, M.-A. Lemburg wrote:
 Why a new syntax ? Can't we just have a pre-defined sentinel
 singleton NoDefault and use that throughout the code (and also
 special case it in argument parsing/handling)?

 def get(store, key, default=NoDefault):
 if store.exists(key):
 return store.retrieve(key)
 ...
>>>
>>> This means adding a new syntax. NoDefault should be a keyword (we can
>>> reuse existing keyword couldn't be used in expression), and it should
 be
>>> accepted only in the specific context of declaring function
>> parameter.
>>
>> This is not new syntax, nor is it a keyword. It's only a
>> new singleton and it is well usable 

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Ivan Levkivskyi
On 2 March 2017 at 13:20, Paul Moore  wrote:

> On 2 March 2017 at 11:31, Stephan Houben  wrote:
> > NoDefault would be special syntax so that this would be disallowed:
> >
> > f(NoDefault)
>
> [...]
>
> So I guess I'm +0.5 on the proposed "positional only parameters"
> syntax, and -1 on any form of new language-defined sentinel value.
>
>
This is also my opinion.

--
Ivan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Stephan Houben
OK, I get it, I think.

I presume it is really the object identity which matters, not the syntax,
so:

y = NoDefault
f(x=y)

would be equally an error.

Would this also apply if we provide or capture the keyword arguments using
** ?

I.e.
f(**{"x": NoDict})

(lambda **kw: kw)(x=NoDict)

In that case I see a problem with this idiom:

newdict = dict(**olddict)

This would now start throwing errors in case any of the values of olddict
was NoDefault.

Stephan



2017-03-02 13:08 GMT+01:00 M.-A. Lemburg :

> On 02.03.2017 12:31, Stephan Houben wrote:
> > I am not sure if I fully understand the proposal then.
> >
> > NoDefault would be special syntax so that this would be disallowed:
> >
> > f(NoDefault)
> >
> > but this would be allowed:
> > def f(x=NoDefault):
> >...
> >
> > and also this:
> >
> > x is NoDefault
> >
> > So this would seem to require an exhaustive list of syntactic contexts
> > in which NoDefault is allowed. I mean, can I do:
> >
> > x = NoDefault
> >
> > ?
> >
> > I observe that I can always get to the underlying NoDefault object in
> this
> > way:
> >
> > (lambda x=NoDefault:x)()
> >
> > So what happens if I do:
> >
> > f((lambda x=NoDefault:x)())
> >
> > ?
>
> Sorry for the confusion. NoDefault would be usable just like
> any other singleton.
>
> There would only be one case where it would cause an exception,
> namely when you declare a parameter as having NoDefault as value.
> This would trigger special logic in the argument parsing code to
> disallow using that parameter as keyword parameter.
>
> Example:
>
> def f(x=NoDefault):
> # x is an optional positional parameter
> if x is NoDefault:
> # x was not passed in as parameter
> ...
> else:
> # x was provided as parameter
> ...
>
> These would all work fine:
>
> f()
> f(1)
> f(None)
>
> This would trigger an exception in the argument parsing code:
>
> f(x=NoDefault)
>
> e.g. TypeError('x is a positional only parameter')
>
> This would not trigger an exception:
>
> f(NoDefault)
>
> since x is not being used as keyword parameter and the
> function f may want to pass the optional positional parameter
> down to other functions with optional positional paramters
> as well.
>
> Is this clearer now ?
>
> Note: The name of the singleton could be something else
> as well, e.g. NoKeywordParameter :-)
>
> > Stephan
> >
> >
> > 2017-03-02 12:15 GMT+01:00 M.-A. Lemburg :
> >
> >> On 02.03.2017 11:22, Stephan Houben wrote:
> >>> In cases like this I would recommend creating the sentinel yourself:
> >>>
> >>> NoDefault = object()
> >>>
> >>> def get(store, key, default=NoDefault):
> >>>if default is NoDefault:
> >>> # do something
> >>>
> >>> You can arrange to not export NoDefault so that the client code cannot
> >> even
> >>> access
> >>> the sentinel value.
> >>
> >> Yes, I know... I've been using the mxTools NotGiven since 1998.
> >>
> >>> This is strictly preferable over having yet another global
> >>> value meaning "no value", since that just moves the goal posts:
> >>> clients will complain they cannot pass in a default=NoDefault and get
> >> back
> >>> NoDefault.
> >>
> >> Not really. NoDefault would mean: no value provided, not that
> >> you don't want a value. As a result, passing NoDefault would
> >> not be allowed, since then you'd be providing a value :-)
> >>
> >>> Stephan
> >>>
> >>>
> >>> 2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :
> >>>
>  On 02.03.2017 10:06, Serhiy Storchaka wrote:
> > On 02.03.17 10:36, M.-A. Lemburg wrote:
> >> Why a new syntax ? Can't we just have a pre-defined sentinel
> >> singleton NoDefault and use that throughout the code (and also
> >> special case it in argument parsing/handling)?
> >>
> >> def get(store, key, default=NoDefault):
> >> if store.exists(key):
> >> return store.retrieve(key)
> >> ...
> >
> > This means adding a new syntax. NoDefault should be a keyword (we can
> > reuse existing keyword couldn't be used in expression), and it should
> >> be
> > accepted only in the specific context of declaring function
> parameter.
> 
>  This is not new syntax, nor is it a keyword. It's only a
>  new singleton and it is well usable outside of function
>  declarations as well, e.g. for class attributes which are
>  not yet initialized (and which can accept None as value).
> 
>  The only special casing would be in function call
>  parameter parsing to signal errors when the parameter
>  is used as keyword parameter.
> 
>  --
>  Marc-Andre Lemburg
>  eGenix.com
> 
>  Professional Python Services directly from the Experts (#1, Mar 02
> 2017)
> >>> Python Projects, Coaching and Consulting ...
> http://www.egenix.com/
> >>> Python Database Interfaces ...
> http://products.egenix.com/
> >>> Plone/Zope Database Interfaces ...
> http://zope.egenix.com/
>  

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 12:31, Stephan Houben wrote:
> I am not sure if I fully understand the proposal then.
> 
> NoDefault would be special syntax so that this would be disallowed:
> 
> f(NoDefault)
> 
> but this would be allowed:
> def f(x=NoDefault):
>...
> 
> and also this:
> 
> x is NoDefault
> 
> So this would seem to require an exhaustive list of syntactic contexts
> in which NoDefault is allowed. I mean, can I do:
> 
> x = NoDefault
> 
> ?
> 
> I observe that I can always get to the underlying NoDefault object in this
> way:
> 
> (lambda x=NoDefault:x)()
> 
> So what happens if I do:
> 
> f((lambda x=NoDefault:x)())
> 
> ?

Sorry for the confusion. NoDefault would be usable just like
any other singleton.

There would only be one case where it would cause an exception,
namely when you declare a parameter as having NoDefault as value.
This would trigger special logic in the argument parsing code to
disallow using that parameter as keyword parameter.

Example:

def f(x=NoDefault):
# x is an optional positional parameter
if x is NoDefault:
# x was not passed in as parameter
...
else:
# x was provided as parameter
...

These would all work fine:

f()
f(1)
f(None)

This would trigger an exception in the argument parsing code:

f(x=NoDefault)

e.g. TypeError('x is a positional only parameter')

This would not trigger an exception:

f(NoDefault)

since x is not being used as keyword parameter and the
function f may want to pass the optional positional parameter
down to other functions with optional positional paramters
as well.

Is this clearer now ?

Note: The name of the singleton could be something else
as well, e.g. NoKeywordParameter :-)

> Stephan
> 
> 
> 2017-03-02 12:15 GMT+01:00 M.-A. Lemburg :
> 
>> On 02.03.2017 11:22, Stephan Houben wrote:
>>> In cases like this I would recommend creating the sentinel yourself:
>>>
>>> NoDefault = object()
>>>
>>> def get(store, key, default=NoDefault):
>>>if default is NoDefault:
>>> # do something
>>>
>>> You can arrange to not export NoDefault so that the client code cannot
>> even
>>> access
>>> the sentinel value.
>>
>> Yes, I know... I've been using the mxTools NotGiven since 1998.
>>
>>> This is strictly preferable over having yet another global
>>> value meaning "no value", since that just moves the goal posts:
>>> clients will complain they cannot pass in a default=NoDefault and get
>> back
>>> NoDefault.
>>
>> Not really. NoDefault would mean: no value provided, not that
>> you don't want a value. As a result, passing NoDefault would
>> not be allowed, since then you'd be providing a value :-)
>>
>>> Stephan
>>>
>>>
>>> 2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :
>>>
 On 02.03.2017 10:06, Serhiy Storchaka wrote:
> On 02.03.17 10:36, M.-A. Lemburg wrote:
>> Why a new syntax ? Can't we just have a pre-defined sentinel
>> singleton NoDefault and use that throughout the code (and also
>> special case it in argument parsing/handling)?
>>
>> def get(store, key, default=NoDefault):
>> if store.exists(key):
>> return store.retrieve(key)
>> ...
>
> This means adding a new syntax. NoDefault should be a keyword (we can
> reuse existing keyword couldn't be used in expression), and it should
>> be
> accepted only in the specific context of declaring function parameter.

 This is not new syntax, nor is it a keyword. It's only a
 new singleton and it is well usable outside of function
 declarations as well, e.g. for class attributes which are
 not yet initialized (and which can accept None as value).

 The only special casing would be in function call
 parameter parsing to signal errors when the parameter
 is used as keyword parameter.

 --
 Marc-Andre Lemburg
 eGenix.com

 Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/
 
>> 

 ::: We implement business ideas - efficiently in both time and costs :::

eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
Registered at Amtsgericht Duesseldorf: HRB 46611
http://www.egenix.com/company/contact/
   http://www.malemburg.com/

 ___
 Python-ideas mailing list
 Python-ideas@python.org
 https://mail.python.org/mailman/listinfo/python-ideas
 Code of Conduct: http://python.org/psf/codeofconduct/

>>>
>>>
>>>
>>> 

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Stephan Houben
I am not sure if I fully understand the proposal then.

NoDefault would be special syntax so that this would be disallowed:

f(NoDefault)

but this would be allowed:
def f(x=NoDefault):
   ...

and also this:

x is NoDefault

So this would seem to require an exhaustive list of syntactic contexts
in which NoDefault is allowed. I mean, can I do:

x = NoDefault

?

I observe that I can always get to the underlying NoDefault object in this
way:

(lambda x=NoDefault:x)()

So what happens if I do:

f((lambda x=NoDefault:x)())

?

Stephan


2017-03-02 12:15 GMT+01:00 M.-A. Lemburg :

> On 02.03.2017 11:22, Stephan Houben wrote:
> > In cases like this I would recommend creating the sentinel yourself:
> >
> > NoDefault = object()
> >
> > def get(store, key, default=NoDefault):
> >if default is NoDefault:
> > # do something
> >
> > You can arrange to not export NoDefault so that the client code cannot
> even
> > access
> > the sentinel value.
>
> Yes, I know... I've been using the mxTools NotGiven since 1998.
>
> > This is strictly preferable over having yet another global
> > value meaning "no value", since that just moves the goal posts:
> > clients will complain they cannot pass in a default=NoDefault and get
> back
> > NoDefault.
>
> Not really. NoDefault would mean: no value provided, not that
> you don't want a value. As a result, passing NoDefault would
> not be allowed, since then you'd be providing a value :-)
>
> > Stephan
> >
> >
> > 2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :
> >
> >> On 02.03.2017 10:06, Serhiy Storchaka wrote:
> >>> On 02.03.17 10:36, M.-A. Lemburg wrote:
>  Why a new syntax ? Can't we just have a pre-defined sentinel
>  singleton NoDefault and use that throughout the code (and also
>  special case it in argument parsing/handling)?
> 
>  def get(store, key, default=NoDefault):
>  if store.exists(key):
>  return store.retrieve(key)
>  ...
> >>>
> >>> This means adding a new syntax. NoDefault should be a keyword (we can
> >>> reuse existing keyword couldn't be used in expression), and it should
> be
> >>> accepted only in the specific context of declaring function parameter.
> >>
> >> This is not new syntax, nor is it a keyword. It's only a
> >> new singleton and it is well usable outside of function
> >> declarations as well, e.g. for class attributes which are
> >> not yet initialized (and which can accept None as value).
> >>
> >> The only special casing would be in function call
> >> parameter parsing to signal errors when the parameter
> >> is used as keyword parameter.
> >>
> >> --
> >> Marc-Andre Lemburg
> >> eGenix.com
> >>
> >> Professional Python Services directly from the Experts (#1, Mar 02 2017)
> > Python Projects, Coaching and Consulting ...  http://www.egenix.com/
> > Python Database Interfaces ...   http://products.egenix.com/
> > Plone/Zope Database Interfaces ...   http://zope.egenix.com/
> >> 
> 
> >>
> >> ::: We implement business ideas - efficiently in both time and costs :::
> >>
> >>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> >> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
> >>Registered at Amtsgericht Duesseldorf: HRB 46611
> >>http://www.egenix.com/company/contact/
> >>   http://www.malemburg.com/
> >>
> >> ___
> >> Python-ideas mailing list
> >> Python-ideas@python.org
> >> https://mail.python.org/mailman/listinfo/python-ideas
> >> Code of Conduct: http://python.org/psf/codeofconduct/
> >>
> >
> >
> >
> > ___
> > Python-ideas mailing list
> > Python-ideas@python.org
> > https://mail.python.org/mailman/listinfo/python-ideas
> > Code of Conduct: http://python.org/psf/codeofconduct/
> >
>
> --
> Marc-Andre Lemburg
> eGenix.com
>
> Professional Python Services directly from the Experts (#1, Mar 02 2017)
> >>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
> >>> Python Database Interfaces ...   http://products.egenix.com/
> >>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/
> 
>
> ::: We implement business ideas - efficiently in both time and costs :::
>
>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
>Registered at Amtsgericht Duesseldorf: HRB 46611
>http://www.egenix.com/company/contact/
>   http://www.malemburg.com/
>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Positional-only parameters

2017-03-02 Thread אלעזר
Here's a proof-of-concept for the decorator. It does not address the issue
of passing aliases to positional arguments to **kwargs - I guess this
requires changes in the CPython's core.

(Sorry about the coloring, that's how it's pasted)

from inspect import signature, Parameter
from functools import wraps


def positional_only(n):
def wrap(f):
s = signature(f)
params = list(s.parameters.values())
for i in range(n):
if params[i].kind != Parameter.POSITIONAL_OR_KEYWORD:
raise TypeError('{} has less than {} positional
arguments'.format(f.__name__, n))
params[i] = params[i].replace(kind=Parameter.POSITIONAL_ONLY)
f.__signature__ = s.replace(parameters=params)
@wraps(f)
def inner(*args, **kwargs):
if len(args) < n:
raise TypeError('{} takes at least {} positional
arguments'.format(f.__name__, n))
return f(*args, **kwargs)
return inner
return wrap


@positional_only(2)
def f(a, b, c):
print(a, b, c)


help(f)
# f(a, b, /, c, **kwargs)

f(1, 2, c=2)

# f(1, b=2, c=3)
# TypeError: f takes at least 2 positional arguments


@positional_only(3)
def g(a, b, *, c):
print(a, b, c)

# TypeError: g has less than 3 positional arguments

Elazar
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Stephan Houben
In cases like this I would recommend creating the sentinel yourself:

NoDefault = object()

def get(store, key, default=NoDefault):
   if default is NoDefault:
# do something

You can arrange to not export NoDefault so that the client code cannot even
access
the sentinel value.

This is strictly preferable over having yet another global
value meaning "no value", since that just moves the goal posts:
clients will complain they cannot pass in a default=NoDefault and get back
NoDefault.

Stephan


2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :

> On 02.03.2017 10:06, Serhiy Storchaka wrote:
> > On 02.03.17 10:36, M.-A. Lemburg wrote:
> >> Why a new syntax ? Can't we just have a pre-defined sentinel
> >> singleton NoDefault and use that throughout the code (and also
> >> special case it in argument parsing/handling)?
> >>
> >> def get(store, key, default=NoDefault):
> >> if store.exists(key):
> >> return store.retrieve(key)
> >> ...
> >
> > This means adding a new syntax. NoDefault should be a keyword (we can
> > reuse existing keyword couldn't be used in expression), and it should be
> > accepted only in the specific context of declaring function parameter.
>
> This is not new syntax, nor is it a keyword. It's only a
> new singleton and it is well usable outside of function
> declarations as well, e.g. for class attributes which are
> not yet initialized (and which can accept None as value).
>
> The only special casing would be in function call
> parameter parsing to signal errors when the parameter
> is used as keyword parameter.
>
> --
> Marc-Andre Lemburg
> eGenix.com
>
> Professional Python Services directly from the Experts (#1, Mar 02 2017)
> >>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
> >>> Python Database Interfaces ...   http://products.egenix.com/
> >>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/
> 
>
> ::: We implement business ideas - efficiently in both time and costs :::
>
>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
>Registered at Amtsgericht Duesseldorf: HRB 46611
>http://www.egenix.com/company/contact/
>   http://www.malemburg.com/
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 10:06, Serhiy Storchaka wrote:
> On 02.03.17 10:36, M.-A. Lemburg wrote:
>> Why a new syntax ? Can't we just have a pre-defined sentinel
>> singleton NoDefault and use that throughout the code (and also
>> special case it in argument parsing/handling)?
>>
>> def get(store, key, default=NoDefault):
>> if store.exists(key):
>> return store.retrieve(key)
>> ...
> 
> This means adding a new syntax. NoDefault should be a keyword (we can
> reuse existing keyword couldn't be used in expression), and it should be
> accepted only in the specific context of declaring function parameter.

This is not new syntax, nor is it a keyword. It's only a
new singleton and it is well usable outside of function
declarations as well, e.g. for class attributes which are
not yet initialized (and which can accept None as value).

The only special casing would be in function call
parameter parsing to signal errors when the parameter
is used as keyword parameter.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Positional-only parameters

2017-03-02 Thread Ethan Furman

On 03/01/2017 11:41 PM, Stephan Houben wrote:


I have a slight variant of the decorator proposal.
Rather than specify a count, let the decorator implement the typeshed dunder 
convention:

@positional_only
 def replace(self, __old, __new, count=-1):

(I imagine this decorator would also treat "self" as position_only,
so no need for __self.)

Pros:
1. Consistent with the typeshed convention.


Only a pro if you like that convention.  ;)


2. Avoids a count.
3. Strictly opt-in, so hopefully keeps those @#?! underscore preservationists 
from picketing my lawn (again!).


Using a decorator is also strictly opt-in.

Oh, and did someone say it was time for the protest?

[--]   [--]
[  ]   [  ]
[ NO MORE UNDERSCORES! ]   [ NO MORE UNDERSCORES! ]
[  ]   [  ]
[--]   [--]
  | | | |
  | | | |
  | | | |
  | | | |
  |-| |-|

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Ivan Levkivskyi
On 2 March 2017 at 09:36, M.-A. Lemburg  wrote:

> On 02.03.2017 09:03, Serhiy Storchaka wrote:
> > Function implemented in Python can have optional parameters with default
> [...]
>
Why a new syntax ? Can't we just have a pre-defined sentinel
> singleton NoDefault and use that throughout the code (and also
> special case it in argument parsing/handling)?
>

I think for the sane reason that we didn't add Undefined to PEP 484 and PEP
526:
Having "another kind of None" will cause code everywhere to expect it.
(Plus Guido didn't like it)

--
Ivan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 09:03, Serhiy Storchaka wrote:
> Function implemented in Python can have optional parameters with default
> value. It also can accept arbitrary number of positional and keyword
> arguments if use var-positional or var-keyword parameters (*args and
> **kwargs). But there is no way to declare an optional parameter that
> don't have default value. Currently you need to use the sentinel idiom
> for implementing this:
> 
> _sentinel = object()
> def get(store, key, default=_sentinel):
> if store.exists(key):
> return store.retrieve(key)
> if default is _sentinel:
> raise LookupError
> else:
> return default
> 
> There are drawback of this:
> 
> * Module's namespace is polluted with sentinel's variables.
> 
> * You need to check for the sentinel before passing it to other function
> by accident.
> 
> * Possible name conflicts between sentinels for different functions of
> the same module.
> 
> * Since the sentinel is accessible outside of the function, it possible
> to pass it to the function.
> 
> * help() of the function shows reprs of default values. "foo(bar= object at 0xb713c698>)" looks ugly.
> 
> 
> I propose to add a new syntax for optional parameters. If the argument
> corresponding to the optional parameter without default value is not
> specified, the parameter takes no value. As well as the "*" prefix means
> "arbitrary number of positional parameters", the prefix "?" can mean
> "single optional parameter".
> 
> Example:
> 
> def get(store, key, ?default):
> if store.exists(key):
> return store.retrieve(key)
> try:
> return default
> except NameError:
> raise LookupError

Why a new syntax ? Can't we just have a pre-defined sentinel
singleton NoDefault and use that throughout the code (and also
special case it in argument parsing/handling)?

def get(store, key, default=NoDefault):
if store.exists(key):
return store.retrieve(key)
...

I added a special singleton NotGiven to our mxTools long ago for
this purpose.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] add __contains__ into the "type" object

2017-03-02 Thread אלעזר
This suggestion is really problematic IMHO.

"isinstance" is a nominal check. I can't ask "isinstance(x, Callable[int,
int])" because that would imply solving the halting problem. so
"isinstance(x, Y)" does not mean "is it true that x is an element of the
type Y" but rather "is it true that x was created by a constructor of some
superclass of Y". It is not a type-theoretic question but a question of
origin and intent.

With regard to readability, this will be completely confusing for me. "in"
is a question about inclusion in a collection, not some set-theoretic
inclusion. Otherwise we should also as "x in f" as an equivalent to "not
not f(x)", as is in set theory.

Elazar
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] PEP 8 coding style included in grammar ?

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 01:04, Barry Warsaw wrote:
> On Mar 01, 2017, at 03:04 PM, Mathieu BEAL wrote:
> 
>> I was wondering why the PEP coding style (
>> https://www.python.org/dev/peps/pep-0008/) is not natively included in python
>> grammar ?
> 
> Well, the simple answer is that the grammar predates PEP 8 (or any PEP) by
> many years.

... plus PEP 8 is a style guide, not a fixed set of rules. You
are free to extend it, mix and match it, to suit your own needs.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Optional parameters without default value

2017-03-02 Thread Serhiy Storchaka
Function implemented in Python can have optional parameters with default 
value. It also can accept arbitrary number of positional and keyword 
arguments if use var-positional or var-keyword parameters (*args and 
**kwargs). But there is no way to declare an optional parameter that 
don't have default value. Currently you need to use the sentinel idiom 
for implementing this:


_sentinel = object()
def get(store, key, default=_sentinel):
if store.exists(key):
return store.retrieve(key)
if default is _sentinel:
raise LookupError
else:
return default

There are drawback of this:

* Module's namespace is polluted with sentinel's variables.

* You need to check for the sentinel before passing it to other function 
by accident.


* Possible name conflicts between sentinels for different functions of 
the same module.


* Since the sentinel is accessible outside of the function, it possible 
to pass it to the function.


* help() of the function shows reprs of default values. "foo(bar=object at 0xb713c698>)" looks ugly.



I propose to add a new syntax for optional parameters. If the argument 
corresponding to the optional parameter without default value is not 
specified, the parameter takes no value. As well as the "*" prefix means 
"arbitrary number of positional parameters", the prefix "?" can mean 
"single optional parameter".


Example:

def get(store, key, ?default):
if store.exists(key):
return store.retrieve(key)
try:
return default
except NameError:
raise LookupError

Alternative syntaxes:

* "=" not followed by an expression: "def get(store, key, default=)".

* The "del" keyword: "def get(store, key, del default)".

This feature is orthogonal to supporting positional-only parameters. 
Optional parameters without default value can be positional-or-keyword, 
keyword-only or positional-only (if the latter is implemented).


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/