Also with pydantic
you can define a field as Optional
, so the None-aware operators are useful anyway.
It wouldnât be, but I think your use of the term âvalidâ is a bit misleading. No one is saying this is to work around invalid code. The syntax proposal is to deal with data structures where an attribute is defined to be optional. So in your hypothetical, the type checkers would require that you use getattr()
or hasattr()
as appropriate to avoid raising an AttributeError. With the proposed syntax the type checkers would still do the same checks, but the suggestion is the overall written code would be more succinct and easier to follow. So both scenarios lead to the same outcome, just with different approaches to the coding.
For me, itâs more about making scripting easier than correctness of code as the proposed syntax doesnât enable some new coding abilities that Python didnât have before. And for long-lasting production code, being more verbose in this specific instance isnât the end of the world.
Hmm, donât we need to tell them first that the attribute might be missing?
class Foo:
def __init__(self, bar: int = None):
if bar is not None:
self.bar: NotRequired[int] = bar
foo = Foo()
foo.bar # Error
foo.bar? # OK
But there might be some problems with arbitrary attributes: Typing: `NotRequired`-like for potentially-absent class attributes?.
Good example (even if NotRequired
is only for TypedDict
s, but itâs not important). Now I catch there could be attributes defined conditionally, so they can be present or not. I tried your code in my IDE (PyCharm) and actually its static type checker does not emit a warning if I try to access bar
. So with this kind of classes, the Guidoâs proposal is useful.
My question is: is this pattern commonly used? Guido posted a real world example in TypeScript, but not in Python.
Well, yes, youâre right, itâs only a syntactic sugar, but itâs quite handy. NULL checks are frequent when you code.
I was able to track down the source of several dozen ?
in a web application. It was used to protect against a single possible missing HTML element. While thatâs quite rare, if the element was missing, the entire call tree would execute, short-circuiting at every ?
.
The use of optional fields is not rare in Python. This could lead to entire call trees short-circuiting on ?
quite often, unless proper guards were implemented.
The postfix notation seems quite confusing to me (especially when switching between JS and Python).
I think event?["timeRange"]?["startTime"]
is good.
And yes, it has to convert AttributeErrors and KeyErrors to None
for it to be fully useful.
Iâm also eagerly waiting for this feature, itâs tiresome having to put guards around most key accesses from a json api.
What I can tell about the opinions of people regarding this PEP from what I read :
?
is a meaningful character for âsafeâ operations.- Let refer
??
,?.
,?[...]
as âsafe orâ, âsafe accessâ, âsafe indexationâ, these would be useful but are cryptic, and quantitative usage of them would decrease readability of the code.
One possibility could be to introduce a âfamily of safe operatorsâ with this kind of explicit names :
?or
, ?dot
, ?at
, âŚ
So that one can write :
maybe_some_value ?or some_value # safe or
maybe_object ?dot maybe_attribute ?dot attribute # safe access
some_list ?at maybe_index # safe indexation
Also possibly more operators :
some_dict ?get maybe_key # safe dictionary access
?exist "maybe_some_object" # safe object reference
This may not be as concise as the OP syntax but might be more explicit and readable.
Also, from my usage cases, I use None checks mainly within class constructors.
One usage I frequently require is about mutually exclusive arguments for contructors, so maybe some ?mutex
(following the âfamily of safe operatorsâ syntax just above) function can be pertinent :
class Person:
def __init__(self, name, age=None, birth_year=None):
self.name = name
match ?mutex [age, birth_year]: # asserting exactly one list element is not None
case 0 : self.age = age
case 1 : self.age = current_year - birth_year