expr or instead
expr if expr is not None else instead
def Raise(err):
raise err
self.totalsizeof or Raise(SizeofError(...))
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
instead if expr is None else expr
It is PEP 505.
I agree we should resume the discussion on this PEP though (for 3.7), I'm not completely sure why it stalled.
Ralph
Another issue already discussed in PEP 505 is a conflict with IPython
(Jupyter Notebook), which uses ? and ?? as custom syntax to request
help. But maybe it can be taught to only recognize those when they're
the last character(s) on the line?
I find the '?.' syntax very ugly, much more so in the examples of chained attributes.
A much better way to handle the use case is to wrap objects in a class that gives this "propagating None" behavior with plain attribute access. A nice implementation was presented in this thread.
https://github.com/kirbyfan64/_frozensafemockobjectimplementation
In all seriousness, though, I really feel like that would be the ultimate bug magnet, since it'd be easy to forget to un-wrap the object afterwards.
--
Ryan
[ERROR]: Your autotools build scripts are 200 lines longer than your program. Something’s wrong.
http://kirbyfan64.github.io/
class NoneCoalesce(object):"Standard operations on object for 'is not None'"def __init__(self, obj):self.obj = objdef __getattr__(self, name):try:return getattr(self.obj, name)except AttributeError:return NoneCoalesce(None)def __getitem__(self, item):try:return self.obj[item]except (TypeError, KeyError):return NoneCoalesce(None)def __call__(self, *args, **kwds):try:return self.obj(*args, **kwds)except TypeError:return NoneCoalesce(None)def __bool__(self):return self.obj is not Nonedef __repr__(self):return "NoneCoalesce[%r]" % self.objdef __str__(self):return "NoneCoalesce[%r]" % self.objdef __len__(self):try:return len(self.obj)except TypeError:return 0
>>> from boltons.dictutils import OrderedMultiDict>>> from NoneCoalesce import NoneCoalesce>>> omd = OrderedMultiDict()>>> omd['a'] = 1>>> omd['b'] = 2>>> omd.add('a', 3)>>> nc = NoneCoalesce(omd)>>> nc or "Spanish Inquisition"Out[8]: NoneCoalesce[OrderedMultiDict([('a', 1), ('b', 2), ('a', 3)])]>>> nc.spam or "Spam"Out[9]: 'Spam'>>> nc['nope'].bar.baz()Out[10]: NoneCoalesce[None]>>> nc['a']Out[11]: 3>>> nc.getlist('a')Out[12]: [1, 3]
On Sat, Sep 10, 2016 at 4:10 PM, Guido van Rossum <gu...@python.org> wrote:
>
> So you're offering `NoneCoalesce(x).bar` as less-ugly alternative to
> `x?.bar`... Color me unconvinced.
No, I'm offering a more realistic use pattern:
> for x in get_stuff():
>
> x = NoneCoalesce(x)
>
> # ... bunch of stuff with x ...
> # ... more stuff with nested keys or attributes ...
>
> x2 = x.foo
>
> x3 = x.bar.baz[x2]
>
> x4 = x(x.val)
>
> result = x3(x4)
>
>
As a less ugly alternative in the fairly uncommon case that you want None coalescing as the behavior of getting attributes, keys, call values, etc. that may or may not be available (AND where you don't want to wrap all of those access patterns in one try/except block).
In contrast, the ugly version of even this pretty simple toy code with the hypothetical syntax would be:
> for x in get_stuff():
>
> # ... bunch of stuff with x ...
>
> # ... more stuff with nested keys or attributes ...
>
> x2 = x?.foo
>
> x3 = x?.bar?.baz?[x2]
>
> x4 = x?(x?.val)
>
> result = x3?(x4)
This second case looks absolutely awful to me. And real world uses, if implemented, would quickly get much worse than that.
So you're offering `NoneCoalesce(x).bar` as less-ugly alternative to
`x?.bar`... Color me unconvinced.
for x in get_stuff():
x = NoneCoalesce(x)
# ... bunch of stuff with x ...# ... more stuff with nested keys or attributes ...
x2 = x.foo
x3 = x.bar.baz[x2]
x4 = x(x.val)
result = x3(x4)
for x in get_stuff():
# ... bunch of stuff with x ...
# ... more stuff with nested keys or attributes ...
x2 = x?.foo
x3 = x?.bar?.baz?[x2]
x4 = x?(x?.val)
result = x3?(x4)
On Sep 10, 2016 4:45 PM, "Guido van Rossum" <gu...@python.org> wrote:
>
> There seems to be a major misunderstanding here. A None-coalescing
> operator is not for catching AttributeError, it's a shortcut similar
> to "a or b" except that it checks for "a is None" rather than bool(a).
That's exactly what the wrapper does. Except it converts all the regular operators into their None-coalescing versions by putting the extra checks into the wrapped object itself.
Now admittedly, this DOES mean that the behavior of operations is somewhat different depending on whether they are wrapped objects or not. False-like is a different thing than None-like.
This really MUST BE essentially a way a catching AttributeErrors though. With the proposed syntax 'x?.foo?.bar' will resolve even if x has no 'foo'. So 'x?.'foo' has to be something special. I guess that special thing could be a 3.7-style None that responds to new operators, but that's essentially still *wrapping* a 3.6-style None.
In my mind, as I say, the question marks look ugly, especially when repeated in chained operations (attribute, call, item get). But even if they didn't feel bad visually, I don't believe the use case is common enough to warrant dedicated syntax. Even if my keyboard had some character I thought was beautiful and intuitive for that meaning, it's still an extra cognitive burden to distinguish the plain from None-coalescing versions of every operation, especially for learners.
Another problem is that the question mark still doesn't actually get the special 'a or b' behavior. For that you still need 'a if a is not None else b'. Or I guess, in concept, 'a ?or b'. For what it's worth, the wrapper gives you the special 'a or b' semantics by casting non-Nones as truthy... But again, 'a' has to have been wrapped first.
No. PEP 505 actually solves the problem without ever catching
AttributeError. Please read it.
Ok, I have been thinking of the behavior too broadly. I realize now that `x?.foo` might still simply raise an AttributeError if x is neither None nor a thing with a foo attribute.
The class I wrote is definitely too aggressive for the behavior described. On the other hand, by being narrower in behavior there feels like even less motivation for new syntax.
How much of the time is a branch of the None check a single fallback value or attribute access versus how often a suite of statements within the not-None branch?
I definitely check for None very often also. I'm curious what the breakdown is in code I work with.
What I was getting at with "essentially" was that it would *do the same thing* that an AttributeError does. That is, if `x.foo` can't be evaluated (i.e. x doesn't have an attribute 'foo'), then access is informally "an error." The hypothetical "x?.foo" catches that "error" and substitutes a different value. The particular implementation under-the-hood is less important for most programmers who might use the construct (and I think documentation would actually give an informal equivalent as something similar to what I put in the NoneCoalesce class).
(3).x # AttributeError{}.x # AttributeError
None.x # AttributeError
(3)?.x # still AttributeError
{}?.x # still AttributeError
None?.x # None
None.__class__ # <type 'NoneType'>
None?.__class__ # None
(3).real # 3{}.values # <built-in method ...>None.__class__ #<type 'NoneType'>
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
Both this discussion, PEP 505, and the one a year ago, tend to mix up 2 related but separate proposals:w(A) Add a None-coalescing operator (like C# a ?? b, what you would write in Python as "a or b" if it didn't have the falsy gotcha)(B) Add some None-aware navigation operators ( The "?.", "?()", "?[]", or what you would write in python as "a and a.attribute" if it didn't have the falsy gotcha)
On Sun, Sep 11, 2016 at 6:00 PM, David Mertz <me...@gnosis.cx> wrote:
> None if a is None else a.foo
This is the crux of the matter to me. It's just too verbose, and the
`if` and `else` keywords are lost in the noise of all the other words
on the line. Plus the big win when it applies) is that if `a` is in
fact something more complex, like `f(a)`, repeating it twice sounds
like a performance penalty, and that's where `f(a)?.foo` really
shines.
>>> def f(a):.... if random() < .01:.... return None.... class V: pass.... v = V().... v.foo = random()*a.... return v
In the form of:
val = do_thing() except ThingError: "default"
But it also can deal with many common operations in Python without the
need to add more operators or variants:
val = my_list[0] except IndexError: "default"
val = iterable[0] except TypeError: next(iter(iterable))
val = int(param) except ValueError: man.nan
Another problem is PEP 505 -- it
is full of discussion but its specification is unreadable due to the
author's idea to defer the actual choice of operators and use a
strange sequence of unicode characters instead.
The idea is that we can easily have both "regular" behavior and None coalescing just by wrapping any objects in a utility class... and WITHOUT adding ugly syntax. I might have missed some corners where we would want behavior wrapped, but those shouldn't be that hard to add in principle.
How much of the time is a branch of the None check a single fallback value or attribute access versus how often a suite of statements within the not-None branch?
I definitely check for None very often also. I'm curious what the breakdown is in code I work with.
The way I recall it, we arrived at the perfect syntax (using ?) and
semantics. The issue was purely strong hesitation about whether
sprinkling ? all over your code is too ugly for Python, and in the end
we couldn't get agreement on *that*. Another problem is PEP 505 -- it
is full of discussion but its specification is unreadable due to the
author's idea to defer the actual choice of operators and use a
strange sequence of unicode characters instead.
If someone wants to write a new, *short* PEP that defers to PEP 505
for motivation etc. and just writes up the spec for the syntax and
semantics we'll have a better starting point. IMO the key syntax is
simply one for accessing attributes returning None instead of raising
AttributeError, so that e.g. `foo?.bar?.baz` is roughly equivalent to
`foo.bar.baz if (foo is not None and foo.bar is not None) else None`,
except evaluating foo and foo.bar only once.
On Sat, Sep 10, 2016 at 10:14 AM, Random832 <rand...@fastmail.com> wrote:
> On Sat, Sep 10, 2016, at 12:48, Stephen J. Turnbull wrote:
>> I forget if Guido was very sympathetic to null-coalescing operators,
>> given somebody came up with a good syntax.
>
> As I remember the discussion, I thought he'd more or less conceded on
> the use of ? but there was disagreement on how to implement it that
> never got resolved. Concerns like, you can't have a?.b return None
> because then a?.b() isn't callable, unless you want to use a?.b?() for
> this case, or some people wanted to have "a?" [where a is None] return a
> magic object whose attribute/call/getitem would give no error, but that
> would have to keep returning itself and never actually return None for
> chained operators.
> _______________________________________________
> Python-ideas mailing list
> Python...@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
--
--Guido van Rossum (python.org/~guido)
I propose that the next phase of the process should be to pick the
best operator for each sub-proposal. Then we can decide which of the
sub-proposals we actually want in the language, based on a combination
of how important the functionality is and how acceptable we find the
spelling.
--Guido
15 Жов 2016 08:11 "Nick Coghlan" <ncog...@gmail.com> пише:
>
> On 15 October 2016 at 13:36, Guido van Rossum <gu...@python.org> wrote:
> > I'm not usually swayed by surveys -- Python is not a democracy. Maybe
> > a bunch of longer examples would help all of us see the advantages of
> > the proposals.
>
> Having been previously somewhere between -1 and -0, I've been doing a
> lot more data mining and analysis work lately, which has been enough
> to shift me to at least +0 and potentially even higher when it comes
> to the utility of adding these operators (more on that below).
>
It is a real pleasure to read Nick's posts, and here he says _exactly_ what I wanted to say, but in a much clearer way than I could.
(Disclaimer: I am working with semi-structured data most of time)
--
Ivan
Regarding the spelling details, my current preferences are as follows:
* None-coalescing operator: x ?or y
* None-severing operator: x ?and y
* None-coalescing augmented assignment: x ?= y
* None-severing attribute access: x?.attr
* None-severing subscript lookup: x?[expr]
>>> foo_exists ? bar_never_evaluated
foo_exists
>>> foo_missing ? foo_exists
foo_exists
>>> foo_missing ? bar_missing
foo_missing>>> foo_exists = 'foo'
>>> foo_exists ?= bar_never_evaluated
>>> foo_exists == 'foo'
True
>>> foo = Missing
>>> bar_exists = 'bar'
>>> foo ?= bar_exists
>>> foo == 'bar'
True
>>> foo = None
>>> bar_missing = Missing
>>> foo ?= bar_missing
>>> foo == None
True>>> ?(foo_exists).bar.baz
foo_exists.bar.baz
>>> ?(foo_exists)[bar][baz]
foo_exists[bar][baz]
>>> ?(foo_missing).bar.baz
Missing
>>> ?(foo_missing)[bar][baz]
Missing
>>> ?(foo_exists).bar.baz_missing
Traceback...
AttributeError: <foo_exists.bar> object has no attribute 'baz_missing'
>>> ?(foo_exists)[bar][baz_missing]
Traceback...
KeyError: 'baz_missing'
>>> ?(foo_missing).bar.baz_missing
Missing
>>> ?(foo_missing)[bar][baz_missing]
MissingI'm not usually swayed by surveys -- Python is not a democracy. Maybe
a bunch of longer examples would help all of us see the advantages of
the proposals.
> In terms of "bunch of longer examples", what did you have in mind?
> I could take some popular library and rewrite a section of it with
> the proposed operators, but that would depend on the response to
> the previous paragraph.
I gather you think you have a deadlock here. The way to break it is
to just do it. Pick a syntax and do the rewriting. My memory of some
past instances is that many of the senior devs (especially Guido) will
"see through the syntax" to evaluate the benefits of the proposal,
even if they've said they don't particularly like the initially-
proposed syntax. Unfortunately here the most plausible syntax is one
that Guido has said he definitely doesn't like: using '?'. The
alternatives are pretty horrible (a Haskell-like 'maybe' keyword, or
the OPEN SQUARE character used by some logicians in modal logic -- the
problem with the latter is that for many people it may not display at
all with their font configurations, or it may turn into mojibake in
email.
OTOH, that case was an astral character -- after Guido announced his
opposition to '?', the poster used PILE OF POO as the operator. OPEN
SQUARE is in the basic multilingual plane, so probably is OK if the
recipient can handle Unicode. '?' vs. '□': maybe that helps narrow
the choice set?
> Unfortunately here the most plausible syntax is one
> that Guido has said he definitely doesn't like: using '?'. The
> alternatives are pretty horrible (a Haskell-like 'maybe' keyword, or
> the OPEN SQUARE character used by some logicians in modal logic -- the
> problem with the latter is that for many people it may not display at
> all with their font configurations, or it may turn into mojibake in
> email.
I think you mean WHITE SQUARE? At least, I can not see any "OPEN SQUARE"
code point in Unicode, and the character you use below □ is called WHITE
SQUARE.
> OTOH, that case was an astral character -- after Guido announced his
> opposition to '?', the poster used PILE OF POO as the operator. OPEN
> SQUARE is in the basic multilingual plane, so probably is OK if the
> recipient can handle Unicode. '?' vs. '□': maybe that helps narrow
> the choice set?
I cannot wait for the day that we can use non-ASCII operators. But I
don't think that day has come: it is still too hard for many people
(including me) to generate non-ASCII characters at the keyboard, and
font support for some of the more useful ones are still inconsistent or
lacking.
For example, we don't have a good literal for empty sets. How about ∅?
Sadly, in my mail client and in the Python REPR, it displays as a
"missing glyph" open rectangle. And how would you type it?
Ironically, WHITE SQUARE does display, but it took me a while to realise
because at first I thought it too was the missing glyph character. And I
still have no idea how to type it.
Java, I believe, allows you to enter escape sequences in source code,
not just in strings. So we could hypothetically allow one of:
myobject\N{WHITE SQUARE}attribute
myobject\u25a1attribute
as a pure-ASCII way of getting
myobject□attribute
but really, who is going to do that? It is bad enough when strings
contain escape sequences, but source code?
So even though I *want* to use non-ASCI operators, I have to admit that
I *can't* realistically use non-ASCII operators. Not yet.
Wishing-that-somebody-can-prove-me-wrong-ly y'rs,
--
Steve
> I think you mean WHITE SQUARE? At least, I can not see any "OPEN
> SQUARE" code point in Unicode, and the character you use below □
> is called WHITE SQUARE.
You're right, I just used a common Japanese name for it. I even
checked the table to make sure it was BMP but didn't notice the proper
name which is written right there. Sorry for the confusion.
Paul Moore writes:
> Personally, I'm not even sure I want non-ASCII operators until
> non-ASCII characters are common, and used without effort, in natural
> language media such as email (on lists like this), source code
> comments, documentation, etc.
The 3 billion computer users (and their ancestors) who don't live in
the U.S. or Western Europe have been using non-ASCII, commonly,
without effort, in natural language media on lists like this one for
up to 5 decades now. In my own experience, XEmacs lists have
explictly allowed Japanese and Russian since 1998, and used to see the
occasional posts in German, French and Spanish, with no complaints of
mojibake or objections that I can recall. And I have maintained
XEmacs code containing Japanese identifiers, both variables and
functions, since 1997.
I understand why folks are reluctant, but face it, the technical
issues were solved before half our users were born. It's purely a
social problem now, and pretty much restricted to the U.S. at that.
> For better or worse, it may be emoji that drive that change ;-)
I suspect that the 100 million or so Chinese, Japanese, Korean, and
Indian programmers who have had systems that have no trouble
whatsoever handling non-ASCII for as long they've used computers will
drive that change.
My point wasn't so much about dealing with the character set of
Unicode, as it was about physical entry of non-native text. For
example, on my (UK) keyboard, all of the printed keycaps are basically
used. And yet, I can't even enter accented letters from latin-1 with a
standard keypress, much less extended Unicode. Of course it's possible
to get those characters (either by specialised mappings in an editor,
or by using an application like Character Map) but there's nothing
guaranteed to work across all applications. That's a hardware and OS
limitation - the hardware only has so many keys to use, and the OS
(Windows, in my case) doesn't support global key mapping (at least not
to my knowledge, in a user-friendly manner - I'm excluding writing my
own keyboard driver :-)) My interest in East Asian experience is at
least in part because the "normal" character sets, as I understand it,
are big enough that it's impractical for a keyboard to include a
plausible basic range of characters, so I'm curious as to what the
physical process is for typing from a vocabulary of thousands of
characters on a sanely-sized keyboard.
In mentioning emoji, my main point was that "average computer users"
are more and more likely to want to use emoji in general applications
(emails, web applications, even documents) - and if a sufficiently
general solution for that problem is found, it may provide a solution
for the general character-entry case. (Also, I couldn't resist the
irony of using a :-) smiley while referring to emoji...) But it may be
that app-specific solutions (e.g., the smiley menu in Skype) are
sufficient for that use case. Or the typical emoji user is likely to
be using a tablet/phone rather than a keyboard, and mobile OSes have
included an emoji menu in their on-screen keyboards.
Coming back to a more mundane example, if I need to type a character
like é in an email, I currently need to reach for Character Map and
cut and paste it. The same is true if I have to type it into the
console. That's a sufficiently annoying stumbling block that I'm
inclined to avoid it - using clumsy workarounds like referring to "the
OP" rather than using their name. I'd be fairly concerned about
introducing non-ASCII syntax into Python while such stumbling blocks
remain - the amount of code typed outside of an editor (interactive
prompt, emails, web applications like Jupyter) mean that editor-based
workarounds like custom mappings are only a partial solution.
But maybe you are right, and it's just my age showing. The fate of APL
probably isn't that relevant these days :-) (or ☺ if you prefer...)
Paul
Before Unicode emoji were prevalent, ASCII emoticons dominated, and
it's not uncommon for multi-character sequences to be automatically
transformed into their corresponding emoji. It isn't hard to set
something up that does these kinds of transformations for other
Unicode characters - use trigraphs for clarity, and type "/:0" to
produce "∅". Or whatever's comfortable for you. Maybe rig it on
Ctrl-Alt-0, if you prefer shift-key sequences.
ChrisA
It's certainly not difficult, in principle. I have (had, I lost it in
an upgrade recently...) a little AutoHotkey program that interpreted
Vim-style digraphs in any application that needed them. But my point
was that we don't want to require people to write such custom
utilities, just to be able to write Python code. Or is the feeling
that it's acceptable to require that?
Paul