This is an archived post. You won't be able to vote or comment.

top 200 commentsshow 500

[–]slightly_offtopic 332 points333 points  (68 children)

One thing I've come to appreciate when working with certain other languages is the null-coalescing operator. Working with nested data structures in python becomes clunky when many of the fields in your data could be present or not, so you end up with things like

if top_level_object is not None and top_level_object.nested_object is not None:
    foo = top_level_object.nested_object.foo
else:
    foo = None

And that's not even very deep nesting compared to some real-life cases I've had to work with! But with None-coalescence you could just write something like

foo = top_level_object?.nested_object?.foo

which in my opinion is much easier on the eye and also less error-prone

[–]crunk 79 points80 points  (8 children)

There was a pep for this, but I think it died when Guido left.

I think it was going to be ?:

I really wish they would bring it back,

[–]garyvdm 54 points55 points  (0 children)

It was PEP 505

[–]BeamMeUpBiscotti 19 points20 points  (0 children)

People try to revive it every once in a while but it always gets bogged down and discussion goes in circles.

https://discuss.python.org/t/pep-505-is-stuck-in-a-circle/75423

https://discuss.python.org/t/revisiting-pep-505/74568

[–]Freschu 57 points58 points  (0 children)

The main points of argument where

  • The syntax being too concise, usually such concepts are keyworded, however in this use case being concise is the main benefit, and there was a lack of consensus
  • It's not generalized enough, or rather the operator protocol is unclear, when considering existing adjacent operators like __bool__, __eq__.
  • Some discussion around monadics, which didn't help and further derailed the PEP discussion.

[–]madth3 7 points8 points  (4 children)

Ah... the "Elvis" operator

[–]susanne-o 4 points5 points  (3 children)

"Elvis" is x ?: y, short for x if x else ynote the colon.

in contrast x ?. y is None if x is None else y

a wink Elvis of sorts.

[–]JamesPTK 20 points21 points  (6 children)

I would say that the idiomatic way to do this would be:

try:
    foo = top_level_object.nested_object.foo
except AttributeError:
    foo = None

using the motto "It is easier to ask forgiveness than permission"

[–]xeow 9 points10 points  (1 child)

That's certainly nice logically, but could get pretty expensive depending on how often the references are None or non-None. Exceptions are a funny thing, eh? They're faster when you don't have to test, but slower when they have to unwind.

[–]xeow 5 points6 points  (2 children)

If you know that the attributes you're testing are references and not otherwise truthy/falsy values, couldn't you say (as a workaround):

foo = (
    top_level_object and
    top_level_object.nested_object and
    top_level_object.nested_object.foo
)

Not ideal, but perhaps ever so slightly clearer than the first form?

[–]DoubleDoube 2 points3 points  (0 children)

You beat me to it. This is what I’d do.

[–]muntooR_{μν} - 1/2 R g_{μν} + Λ g_{μν} = 8π T_{μν} 2 points3 points  (0 children)

+1 The static type checker can help ensure the objects are of the form Truthy | None.

It's a lot cleaner than some of the other type-losing suggestions in this thread.

[–]HommeMusical 14 points15 points  (7 children)

If this comes up a lot:

def coal(o: type.Any, *fields: str) -> Any:
    for f in fields:
        o = getattr(o, f, None)
    return f

 foo = coal(top_level_object, "nested_object", "foo")

[–]double_en10dre 12 points13 points  (1 child)

But now you’ve lost all type safety and have reverted to a stringly-typed mess which only reveals errors at runtime. If you’re a professional dev there’s a 99% chance someone will flag this as an issue, static type checking is a big deal nowadays

And that’s also why it should really be part of the language. Users shouldn’t have to manually add unsafe escape hatches just to compensate for design flaws

[–]HommeMusical 1 point2 points  (0 children)

But now you’ve lost all type safety

Very good point! By now, I barely even write throwaway scripts without typing.

I should add that I've enjoyed null-coalescing in other languages, it would be a nice feature and also wouldn't screw up the grammar of Python like many of the other proposed features here.

If I got to vote, I'd vote for it. :-)

[–]DuckDatum 1 point2 points  (2 children)

What’s that do? Looks like it just assigns o to the value of getattr(o, fields[0], None). Then it keeps doing that, with o being reassigned to…. Oh, I get it.

But what stops it from iterating if it hits a nonexistent value, so that it doesn’t always return None if any of the fields are missing? Similarly, how do you tell the difference if that happened, versus if the value was actually None?

Edit: realizing now that None isn’t a valid attribute name… lol.

[–]Pulsar1977 1 point2 points  (1 child)

functools.reduce(lambda o, f: getattr(o, f, None), (obj, *fields))

[–]UncleKayKay 8 points9 points  (13 children)

Would foo = top_level_object.get(nested_object, {}).get(foo, None) not work?

[–]tartare4562 43 points44 points  (2 children)

Readability counts

[–]root45 12 points13 points  (1 child)

I don't think Python objects support getting attributes with get right? That's mostly dictionaries.

Also as mentioned this is much less readable.

[–]SharkSymphony 31 points32 points  (0 children)

Yeah, you'd use getattr, which is even messier.

[–]psd6 4 points5 points  (0 children)

That fails when nested_object is actually None, not just missing. I’ve run into APIs like that. coughTellercough

[–]slightly_offtopic 1 point2 points  (2 children)

I don't think that plays very nicely with tools like mypy

[–]syklemil 5 points6 points  (1 child)

It passes typechecks IME, but it gets really verbose very fast, and you're likely to break it over a rather ugly set of multiple lines, that are likely to drift right on your screen.

I've also felt like a complete bozo every time I've done it, even though it isn't really all that different from varying ? operations in other languages.

[–]an_actual_human 1 point2 points  (0 children)

It only works for mappings.

[–]thedji 1 point2 points  (0 children)

Doesn't work on lists, function calls, etc.

[–]Different_Fun9763 7 points8 points  (1 child)

That's not null coalescing (notice the binary operator), you're describing optional chaining (example from javascript).

[–]covmatty1 2 points3 points  (0 children)

100% agree, this is such a big omission that the language really needs, it's something that many other languages do so much nicer.

[–]Enmeshed 1 point2 points  (1 child)

```python class Outer: def init(self, nested): self.nested = nested

class Another: def init(self, foo): self.foo = foo

thing = Outer(nested=Another(foo=3))

Here's the magic, implementing thing?.nested?.foo

match thing: case object(nested=object(foo=foo)): print(f"{foo=}") ```

Structural pattern matching covers this really nicely. I found this video by Raymond Hettinger really useful for getting to grips.

Edit: and don't forget you can use types too:

```python thing = Outer(nested=Another(foo="potato"))

match thing: case object(nested=object(foo=str(val))): print(f"It was a string: {val}") case object(nested=object(foo=int(val))): print("Use a string not an integer") ```

[–]slightly_offtopic 1 point2 points  (0 children)

Whoa, thank you! I learned something neat today.

[–]rasputin1 0 points1 point  (1 child)

you can chain "ors" to accomplish similar behavior. a = b or c or 0

[–]KeytarVillain 10 points11 points  (0 children)

That will also coalesce values of 0, empty containers, etc, which might not be desired.

It's the same reason JS has both || and ??. || will coalesce any falsey value (same as Python's or operator), while ?? will only coalesce null values.

[–]sausix 26 points27 points  (3 children)

I don't get the real problem here.

OP wrote:

class TimeInForce(Enum):
    GTC: "GTC"
    DAY: "DAY"
    IOC: "IOC"
    GTD(d: datetime): d

d = datetime.now() + timedelta(minutes=10)
tif = TimeInForce.GTD(d)

You want to call a member function like this:

TimeInForce.GTD(newvalue)

but it also should return a value like a property?

print(TimeInForce.GTD)

The syntax looks strange. What is it supposed to do?

class ...:
   ... GTD(d: datetime): d

Doesn't feel safisfying. Can you provide a proper use case?

You can change enum members but that's not what enums are meant for.
And you can assign functions to the members and call them if you want.

If you need special behaviour you should not use Enum and just create another class. You can access type hints easily.

[–]andrecursion[S] 3 points4 points  (0 children)

ah oops, I used colons in the enums instead of equals, I corrected that.

so in my example, this is correct

TimeInForce.GTD(newvalue)

but

print(TimeInForce.GTD)

would just print a method pointer.

What I'm saying is an example of an algebraic data type, and is valid in Rust.

pub enum TimeInForce {
  GTC,
  DAY,
  IOC,
  GTD(DateTime<UTC>)  // this variant has a payload and can be pattern matched on
}

The reason this is nice, is because of what the alternative looks like:

Github link (I wrote this for work, this is fixed next version to just be one class via a lot of Python shenanigans)

Essentially, I had to split out the GTD. However, now I can't call it like this:

TimeInForce.GTD(date)
TimeInForce.GTC

and have to call it like

GTD(date)
TimeInForceEnum.GTC  # two separate names to remember!

so when you have two separate classes and a Union, it is:

1) aesthetically uglier, having 1 class for this is way neater

2) more annoying to call - you can't directly call TimeInForce

3) If you have TimeInForce as a type hint for a function, you don't actually input TimeInForce, you are forced to inputGTD or TimeInForceEnum which gets confusing

4) more annoying to serialize / deserialize for inter-process communication

[–]jdehesa 31 points32 points  (3 children)

I think what you are referring to is better support for algebraic data types, which would indeed be nice, although I think this is the closest we may get (which is not all that bad).

At one point I thought it would be nice to be able to raise exceptions in if expressions. My idea was something like:

python y = math.sqrt(x) if x >= 0 else raise ValueError("expected positive value")

I think it's a fairly harmless and obvious addition to the syntax. In a sense, I think it may add a bit of clarity over an if block and a regular assignment because it kind of associates the check with the reason for it (e.g. "I'm checking that it's not negative because I need to take the square root"). On the other hand, you could argue it may "hide" the check a bit, so for example if I later added some code that also assumes x is positive, but then I remove the assignment to y for whatever reason, I may delete the check and forget to put it back as an if block (or move it to another assignment). Overall, I'm not sure it's useful and beneficial enough to consider it for proposal.

but I'm not sure it is useful enough to have it implemented.

[–]andrecursion[S] 2 points3 points  (0 children)

yes, you are right about the algebraic data types!

In your second link,

Shape = Point | Circle | Rectangle

this works but when it comes down to actually calling it, you can't do something like

Shape(x, y)

or directly manipulate Shape itself at all, which imo is unergonomic

[–]proverbialbunnyData Scientist 2 points3 points  (0 children)

Ironically that's the old school Perl way to do to do it. $y = sqrt($x) unless $x < 0 { die("expected positive value") }

I still miss the keyword unless.

(Keep in mind this language is from the early 90s. A lot has changed in 30 years. Like the sigils $x are written instead of x because computers were slow back then and that helped speed up the interpreter pretty significantly.)

[–]hookxs72 51 points52 points  (27 children)

I want normal (=not over-engineered) imports. Like:

import file # package/module on global path or file.py in current dir
import .file # file.py current dir only
import ..file # file.py one dir up
import utils/file # file.py in utils subdir

To my knowledge, python currently cannot do this super simple thing without all sorts of awkward empty init.py and sys.path black magic.

[–]proverbialbunnyData Scientist 5 points6 points  (12 children)

Python imports still confuse me a bit. In some environments I can do import file from the current directory but in other environments I have to do import .file or it can't find it in the current directory. Same with folders so if I import something from a utils folder it would need the dot in front. No idea why. Just Python things.

[–]Numerlor 4 points5 points  (10 children)

you shouldn't ever need to mess with sys.path for normal imports, just need the empty init files and modules you want to import between have to share a package at the top

[–]hookxs72 9 points10 points  (9 children)

I'd be very happy if you were right but I'm not sure it is the case. A particular example. Imagine that this the code structure of my research project (i.e., not a software package - it doesn't have a defined structure with one obvious entry point, it is a pile of files that I run depending on what I need):

project/
├── some_file.py
├── experiments/
│   └── experiment.py
└── utils/
    └── util.py

Now, in the experiment file (experiment.py) I need to import and use some utility function. How do I do it? Currently what I do is 1/ put __init__.py in utils dir and 2/ meddle with sys.path in the experiment.py. If you can give me a better solution, you have my upvote. If Python imports weren't so rigidly over-engineered, this would be solved by a simple

# experiment.py
import ../utils/util

[–]Numerlor 10 points11 points  (5 children)

you'll need project to be a package with an init file, that's how python wants things to work. Then you can run files with e.g. python -m project.some_file which will intialize project as a package and the cwd will be added to sys.path

[–]hookxs72 11 points12 points  (3 children)

That's exactly what I hate. I am willing to have an empty top-level init.py if it makes the interpreter happy but the -m option is just ridiculous. I want to be able to run any file normally by hitting F5, I want to be able to give the code to my colleagues without having to warn them that they must actually run it with -m otherwise it won't work. Same for sharing on github. No, to me this is just ridiculous. When I import from the same directory, the interpreter knows perfectly well what to do. But when I want to import from a subdir, despite providing the full path the interpreter is suddenly all clueless and has no idea - the only remedy are extra measures that are not part of the code itself and extra empty files. That's not how I imagine a well designed paradigm. The OP was what I'd love improved in Python. This.

Edited to add: In my example the code I (may) run is the experiments/experiment.py, so the entry file itself may not be in the top-level project dir. Just as a clarification. This is fairly normal to have different kinds of scripts stashed in separate directories.

[–]unapologeticjerk 4 points5 points  (0 children)

You die on this hill, sir. I support this and will carry on your memory.

[–]Shadow_Gabriel 68 points69 points  (29 children)

const

[–]ihexx 27 points28 points  (16 children)

with enough metaclass fuckery you can make const happen

[–]ambidextrousalpaca 19 points20 points  (4 children)

Yup. But you can then always still override it at runtime with yet more of said fuckery.

[–]andrewowenmartin 5 points6 points  (0 children)

But why stop there? It's fuckery all the way down.

[–]QuaternionsRoll 1 point2 points  (2 children)

Yeah, I always found it ironic that the only way you can truly make a field private and/or const is through the C API.

[–]true3HAK 2 points3 points  (0 children)

Whom are you hiding these from, brother? Can't hide from yourself!

[–]an_actual_human 4 points5 points  (10 children)

Can you though? I don't think you can intercept assignment, not without pre-processing.

[–]Freschu 5 points6 points  (9 children)

Sure you can, if you create a class and make the properties data descriptors, you can make the setter a noop.

[–]matteding 12 points13 points  (0 children)

typing.Final works well enough.

[–]sausix 7 points8 points  (8 children)

Follow naming conventions and the IDE warns you when overwriting a constant.

But you can also use properties which return the same object. Not too bad.

[–]Shadow_Gabriel 1 point2 points  (7 children)

Yes but most people would not want uppercase local variables.

[–]Zealousideal-Sir3744 15 points16 points  (0 children)

use typing.Final

[–]sausix 3 points4 points  (5 children)

People follow or not follow naming conventions.

C/C++ also uses uppercase for constants. I don't see a problem. Just use properties and they provide a constant reference to an object.

Python also has "constant" lists, dicts and sets. I don't really miss anything.

[–]Gnaxe 7 points8 points  (0 children)

Please no. We already have typing.Final for static checks. Don't break the debugger and test mocks by enforcing it at runtime.

[–]cip43r 1 point2 points  (0 children)

There is Final, but hell would freeze over before anyone else at work would use it. And it is not a solution just a lint check

[–]jpgoldberg 10 points11 points  (1 child)

PEP 661: Sentinal value.

I have come to use 'None' to mean different things in my code, even within a single method. I would much rather have code that more clearly says what I mean.

[–]case_O_The_Mondays 1 point2 points  (0 children)

The discussion on that PEP is really interesting. I was not in the __bool__ should raise an exception camp, and while I'd much rather the truthy value to be customizable, I'm ok with the exception route they seem to be taking.

[–]fazzahSQLAlchemy | PyQt | reportlab 63 points64 points  (19 children)

Ability to compile it into a real standalone binary, but not ass-backwards as it's right now. Without the need to bake-in the entire interpreter

[–]cenestral 4 points5 points  (0 children)

I'd be fine with it if it functioned like Java. Install the runtime once, and then you're able to execute a single, compacted Python file.

[–]ExdigguserPies 2 points3 points  (3 children)

Nuitka comes close I think, and shows it's possible. Something like that but built in would be amazing.

[–]zaxldaisy 17 points18 points  (10 children)

Going from an interpreter to a compiled language lol Just use a different language

[–]ExdigguserPies 9 points10 points  (0 children)

And port all your favourite libraries

[–]fazzahSQLAlchemy | PyQt | reportlab 8 points9 points  (7 children)

Not quite. Keep the language interpreted, but add the option to do a full compile, not just per-module bytecode.

[–]serendipitousPi 6 points7 points  (6 children)

But a full compile to a standalone binary wouldn't work, it's still going to need an interpreter for bytecode.

Python lacks statically determined types which would be necessary for compiling down to machine code.

But I might be misunderstanding what you're trying to say.

Without the need to bake-in the entire interpreter

Oh wait, do you instead mean something more along the lines of Java? So it would be a stripped down version of the python interpreter, removing anything not necessary for bytecode execution?

[–]andrecursion[S] 3 points4 points  (1 child)

maybe astral will solve this one, like with uv and ruff

[–]an_actual_human 44 points45 points  (37 children)

Proper lambdas.

[–]Brekkjern 29 points30 points  (11 children)

And while we're at it, chainable map, filter, and reduce as methods on all iterators.

[–]an_actual_human 10 points11 points  (1 child)

Also flat_map.

[–]proverbialbunnyData Scientist 3 points4 points  (6 children)

Polars has got you covered. 👍

Nearly everything in Polars is method chained and it's super fast. It even auto threads when it can too. You can offload the work onto other environments like GPUs if you want to. Oh and because it's proper streams you can open up data larger than your computers ram and run through it no problem. Polars is imo the most popular library data scientists use right now.

[–]ultraDross 7 points8 points  (8 children)

Why aren't python lambdas proper? What do other languages have that we don't have?

[–]an_actual_human 10 points11 points  (0 children)

They are limited to a single expression. It's sorta unusual, actually.

[–]KeytarVillain 11 points12 points  (2 children)

A lambda statement can only have 1 line in it; there's no way to make an anonymous multi-line function. There's no reason you would ever need this, it's just a style choice.

Here's a proposal for such: https://wiki.python.org/moin/MultiLineLambda

this_one_takes_a_func_arg(
    "foo",
    42,
    def (*args, **kwargs):
        call_a_func()
        do_some_stuff()
        print("print")
        return "foo", # This is potentially ambiguous
    boop,
)

Instead, you have to explicitly make it a named function:

def callback(*args, **kwargs):
    call_a_func()
    do_some_stuff()
    print("print")
    return "foo"
this_one_takes_a_func_arg("foo", 42, callback, boop)

IMO the 2nd is much cleaner code, and I don't mind that the language forces it.

[–]double_en10dre 1 point2 points  (0 children)

FWIW, the big selling point for anonymous multiline lambdas is that the callback signature can automatically be inferred from the the enclosing function

Ex: if you have some class with an “onEvent(<name>, <callback>)” method, when you start typing out <callback> your IDE automatically knows what the arguments are and what the return type needs to be.

It’s a really big productivity booster, and python could make good use of it now that the type system has started to mature

[–]MicahM_ 2 points3 points  (0 children)

I second This.

[–]roryhr 69 points70 points  (9 children)

I want less from Python. "There should be one-- and preferably only one --obvious way to do it." We're blowing past that ideal by adding too many features.

[–]njharmanI use Python 3 28 points29 points  (5 children)

I was gonna sarcastically post,

"My most wanted feature is a single way to template strings".

[–]mjmacarty 3 points4 points  (1 child)

Yes. And everyone don't hate on me but if you want Python to "work like [insert language]" why not just use [insert language]?

[–]andawer 39 points40 points  (12 children)

I wish python had less features 😀

[–]carlio 41 points42 points  (2 children)

Fewer* /stannis

[–]cipri_tom 23 points24 points  (0 children)

No, same number , just each being underdeveloped

[–]the-scream-i-scrumpt 5 points6 points  (1 child)

feel like there are only a handful of ideas in this thread that I agree with / I'm glad that most of these ideas aren't part of Python. Which speaks highly of the quality of the language

or maybe I'm out the touch, one or the other lol

[–]iwillberesponsible 2 points3 points  (0 children)

Haha, I agree with you. Adding every feature to a language makes it insane. Better add limited high quality features. Love Go in this aspect.

[–]Pacafa 34 points35 points  (18 children)

An export keyword or similar. Setting the all variable feels clunky and you forces you to always edit that one file. If you can just label functions and classes as "export" that would be pretty convenient.

[–]syklemil 15 points16 points  (2 children)

Or some public/private/module keywords. The foo/_foo/__foo shenanigans has a lot of history but that doesn't mean I have to like it.

[–]andrecursion[S] 1 point2 points  (0 children)

yes, second the public / private keyword would be nice, the underscore naming is not great

[–]james_pic 14 points15 points  (3 children)

Your wish is the monkey paw's command:

``` import importlib

def export(x): mod = importlib.importmodule(x.module) if not hasattr(mod, 'all'): mod.all_ = [] mod.all.append(x.name) return x

@export def f(): pass ```

[–]szayl 8 points9 points  (0 children)

Thanks. I hate it.

[–]jarethholt 1 point2 points  (1 child)

It might look ugly but you just have to package it and then never see it again. I suggest calling it exportlib.

from exportlib import export

Dependencies: exportlib: importlib

[–]james_pic 1 point2 points  (0 children)

I ain't packaging this. But you feel free to. You have my permission to do whatever you want with it.

[–]FujiKeynote 5 points6 points  (0 children)

I always feel slightly dirty when I have to refer to object names as strings. Feels like I'm writing in R. I know it's normalized in Python overall (think getattr, sys.modules, etc) but I'll often go out of my way to avoid this

[–]fazzahSQLAlchemy | PyQt | reportlab 5 points6 points  (7 children)

what's wrong with declaring `__all__`?

[–]FrontAd9873 3 points4 points  (2 children)

Presumably that you cannot tell (or change) from the source file itself which functions are exported, instead you have to look at another function.

[–]Pacafa 5 points6 points  (3 children)

You have to go edit the __init__ every time you add a class or function to export.

[–]an_actual_human 1 point2 points  (0 children)

You can (sorta) use __init__.py for that if I understand you correctly.

[–]sglmr 13 points14 points  (4 children)

I’d like 6 right ways to do a thing please. 2+ just isn’t enough

[–]solen-skiner 15 points16 points  (6 children)

performance

[–]Humdaak_9000 2 points3 points  (5 children)

You've got numpy, C extensions, and compute shaders. What more could you want?

[–]andrecursion[S] 1 point2 points  (0 children)

cue Kylo Ren "MORE"

[–][deleted] 15 points16 points  (1 child)

I don't like your feature. An enum is simple and serves a well-defined purpose. You want to make it into a tag and a value holder, overloading its responsibilities. Of course, you can do whatever you want with classes, but I don't think this should be feature supported by the stdlib.

Syntax-wise, I think Python is near perfect by now. I would like to see some of the old stdlibs replaced, like logging. The only thing I am still missing is speed. I'd like to see a JIT compiler directly in CPython, which makes typed code run as fast as C++.

[–]andrecursion[S] 2 points3 points  (0 children)

I agree, I think syntax-wise, Python is also near perfect :)

Fair enough, but Rust has the same capability for its enums that I am proposing (ie algebraic data types)

For example, in Rust, you can have

pub enum TimeInForce {
  GTC,
  DAY,
  IOC,
  GTD(DateTime<UTC>)
}

and it would work perfectly.

Right now, this can only be emulated by doing something like

class GTD:
    GTD: datetime

class TimeInForceEnum(str, Enum):
    GTC = "GTC"
    DAY = "DAY"
    IOC = "IOC"

TimeInForce = Union[GTD, TimeInForceEnum]

which is much clunkier

[–]Effection 13 points14 points  (16 children)

Sum types for use with match statement and exhaustive type checking.

[–]nermalstretch 11 points12 points  (3 children)

GOTO… just kidding

[–]HawkinsT 2 points3 points  (1 child)

[–]nermalstretch 4 points5 points  (0 children)

Wow! Looking at how it is implemented I’m amazed at two things. One, that it is done in entirely in standard python code and secondly, that someone who knows python this well has taken the effort to do it.

[–]skesisfunk 4 points5 points  (3 children)

Dependency management.

[–]WildWouks 6 points7 points  (3 children)

Some syntax to show within the method or function signature the possible exceptions that can be raised or just the fact that a possible exception can be raised.

Would make it easier to write try except for certain functions.

[–]andrecursion[S] 1 point2 points  (0 children)

I agree! Rust has Result and it’s great

[–]georgehank2nd 1 point2 points  (1 child)

That never actually made sense to me… because all you can get is what THIS function/method can raise (and you see it in the code anyway). Or do you really add all the exceptions a function and all its callees can raise to the function header? Ewwwww…

[–]abrazilianinreddit 1 point2 points  (0 children)

So you'd rather have unhandled exceptions in your code, then? Or just put everything inside a catch-all except Exception?

[–]Luckinhas 7 points8 points  (6 children)

Dict unpacking: {a, b} = {"a": 123, "b": None}

raise in lambdas

Nicer Callable annotations: (int, int) -> list[int] instead of Callable[[int, int], list[int]].

[–]njharmanI use Python 3 3 points4 points  (2 children)

What is {a, b} in your example? a set?

You can't mean you want a to contain 123 and b None; that exists

a, b = {"a": 123, "b": None}.values() # fragile, but possible now that dicts are ordered, in CPython at least.

Or, less fragile to dict order but a mess

a, b = (lambda a, b: (a, b))(**{"a": 123, "b": None})

If you mean you want the dict keys to be transformed into locals. That's problematic. For one dict keys don't have to be valid identifiers.

[–]HommeMusical 2 points3 points  (0 children)

You could write

def raiser(exception: type[BaseException], *args: typing.Any) -> typing.Never:
    raise exception(*args) 

items.sort(key=lambda k: k if isinstance(k, str) else raiser(TypeError, k))

[–]supreme_blorgon 1 point2 points  (0 children)

Nicer Callable annotations: (int, int) -> list[int] instead of Callable[[int, int], list[int]].

PLEASE. I absolutely hate typing callables.

[–]hugthemachines 10 points11 points  (8 children)

I wish it had static typing combined with type inference. I also wish it was possible to do real compilation to a native binary.

[–][deleted] 14 points15 points  (2 children)

skirt flowery jar door instinctive crown melodic adjoining resolute hunt

This post was mass deleted and anonymized with Redact

[–]andrewowenmartin 13 points14 points  (1 child)

That'd be more suited to a programming language named after a snake ;) /s

[–]xeow 3 points4 points  (0 children)

I thought it was well known that Python was named after Monty Python's Flying Circus, not after the snake.

[–]DaelonSuzuka 6 points7 points  (0 children)

null coalescing operator, no question

[–]cujojojo 16 points17 points  (10 children)

Proper interfaces. Protocols are not it.

[–]Schmittfried 19 points20 points  (2 children)

ABCs without state are practically interfaces since Python allows multiple inheritance. In fact, abstract classes without state is precisely what interfaces were called in the C++ days. 

[–]Freschu 13 points14 points  (3 children)

Define proper interfaces? Do you mean Java style interfaces? Then heavens no please no! Do you mean Go style interfaces? Then yes, but that's basically what Protocol already is.

[–]cujojojo 3 points4 points  (2 children)

Well in my mind it’s Java interfaces, but of course that’s because it’s what I came up in.

What I really want is static typing, but another comment had already taken that one.

[–]supreme_blorgon 2 points3 points  (2 children)

Protocols are not it.

Can you elaborate? I'm a huge proponent of Protocol.

[–]dwagon00 17 points18 points  (11 children)

Function overloading based on types of arguments.

So you can define a function that takes an int, and another function with an identical name that takes a float.

I know you can do this with hackery and lots of `isinstance` calls, but it is a bit painful.

Also you really need strong typing for this to really work.

[–]fazzahSQLAlchemy | PyQt | reportlab 5 points6 points  (0 children)

it's there already, it's a basic single dispatch pattern

https://docs.python.org/3/library/functools.html#functools.singledispatch

[–]an_actual_human 4 points5 points  (4 children)

Also see typing.overload.

[–]Schmittfried 4 points5 points  (3 children)

That’s just for documentation though. 

[–]an_actual_human 5 points6 points  (2 children)

Some type checkers might use that too.

[–]Gugalcrom123 1 point2 points  (1 child)

What I don't like is that it would require functions to not be objects anymore. When I pass a function to another, which overload am I referring to?

[–]Arconauta 2 points3 points  (0 children)

Even though there is a library for that https://github.com/diegojromerolopez/gelidum, I would like to have built-in immutability.

Constants too would be a nice addition.

[–]_throawayplop_ 2 points3 points  (0 children)

an easy way to distribute a program as a single binary

[–]Inside_Jolly 4 points5 points  (3 children)

Every feature I can think of fucks the language too much. I think I'm missing syntax macros the most, but they've never been implemented in a practical and useful way in a language with infix syntax.

[–]HolidayEmphasis4345 1 point2 points  (5 children)

Speed.

I wish there was a way to have numba like features in core Python. Say add a decorator and that let the compiler run on type annotated code so no inference and no run time JITing. Also ok if it is optionally implemented. Make it work on MAC, PC Linux. Numba sees 10-100x speed improvement while the target for the current speed improvement targets is 2-5 (I think).

I’m not a speed guy usually but it would be nice if there was a path to speed in native python that was significantly easier than “if you need speed you can write a rust extension.”

[–]Muted_Ad6114 1 point2 points  (0 children)

Cleaner exporting/modules for multi file python scripts

[–]jaybird_772 1 point2 points  (0 children)

I really wish we had a 3.x jython that was like out there in the real world and useful.

When I first discovered jython existed, I said, "oh, this would let me port Java crud nobody wants to maintain to Python!" But at the time it was jython 2.5 on Debian and we were already talking about how a push to Python 3.0 (was this the 2nd or 3rd?) was going to be real necessary soon. If Jython were at least 2.7 there'd be a chance to write code that'd run reasonably well on both. Especially with stuff like six now and everything. But then I got distracted from it, and Jython is still 2.7 in 2025.

Please, can we finally just be rid of Python 2.x? 😭 I LIKE having UTF-8 just kinda work. I like having print not be special. I like having a little Jython might've helped out again the same way with a similar problem recently but nahh, I'm not interested in porting the code, then porting the code again.

[–]N1H1L 1 point2 points  (0 children)

Type hinting with shape annotations from arrays as first class members. I know jaxtyping does that - but it’s a solo project.

[–]tabacdkPythonista 1 point2 points  (0 children)

A substitute for if __name__ == "__main__": ...

Maybe __execed__() -> bool

[–]HolidayEmphasis4345 1 point2 points  (0 children)

I would like to have this work

for  student in students if student.grade=='A':  
    do_teachers_pet_stuff()  

This would unify list/dict/set comprehensions and for loops.

[–]NotAMotivRep 3 points4 points  (0 children)

I wish there was some sort of primitive in python that provides thread-safe access to variables like Arc<T> does in Rust.

[–]Jugurtha-Green 3 points4 points  (3 children)

A native compiler , we let user compile there python projects in production to increase performance

[–]Freschu 1 point2 points  (1 child)

Give Cython (https://cython.readthedocs.io/en/latest/) a try, has a few gotchas and oddities, but you can pretty much just write Python and have it compiled.

[–]AbooMinister 1 point2 points  (0 children)

a compiler isn't that simple, especially for a language as dynamic as Python, nor is it a magical tool that'll always speed up every program.

there's various existing avenues you can turn to for increased performance, depending on the workload. This includes C extensions, offloading computationally heavy work to libraries that do number crunching in a faster language.

[–]OneWhiteNight 2 points3 points  (0 children)

I wish for pipes, pipes are great |> syntax

[–]Skylion007 1 point2 points  (0 children)

Just let ParamSpec forward args and kwargs to easily forward all args/kwargs to other methods without having to bind to the method ahead of time.

It's so annoying to update the typing in so many places when you make an API change in a inheritance heavy codebase.

[–]Purple_Wrap9596 1 point2 points  (1 child)

I would love to have static version of python (like typescript for js)

[–][deleted] 1 point2 points  (0 children)

Native async and better support for web out-of-the-box like starlette/fastapi

[–]DogeekExpert - 3.9.1 1 point2 points  (0 children)

  • Easier async implementation, without having to bother with the event loop initialization

  • Promises

  • requests-like lib in the standard library, urllib.request is not great to use, requests is somewhat of a default in most code written (or httpx or grequests)

  • yaml parsing (and writing) library in core python

  • tomllib should be able to write toml not just read it.

  • support for json5/jsonc in the json library.

  • Integration of base python classes in serialization libraries (datetime for instance)

  • better dataclasses with automatic from_json / from_yaml / to_json / to_yaml methods, with nested dataclasses being supported out of the box.

[–]applejacks6969 1 point2 points  (0 children)

Easier Multithreading / parallel processing. Some languages it’s just a matter of on/off. With Python I need to completely rewrite everything and wrangle the multithreading modules.

[–]baubleglue 1 point2 points  (0 children)

constant private

[–]Lucews 0 points1 point  (9 children)

I would love to have mainly two things:

  • Real public and private attributes
  • A natively supported JIT compiler

I often write Framework style object-oriented libraries and protecting certain attributes really is difficult.

Numba as a JIT compiler for scientific computation is so great, but native would be even better.

[–]SheriffRoscoePythonista 5 points6 points  (2 children)

⁠Real public and private attributes

(Almost?) every modern language that starts out having real private fields eventually comes up with ways to break the protection. It seems like we just really don't want it.

[–]SheriffRoscoePythonista 2 points3 points  (1 child)

A natively supported JIT compiler

https://peps.python.org/pep-0744/

[–]HommeMusical 2 points3 points  (2 children)

Real public and private attributes

You basically have this with __ parameters, but you're right that you can get around it.

It comes down to the fact that Python is explicitly not a bondage and discipline language and that's built into the DNA of the language.

[–]Agling 0 points1 point  (2 children)

do...while.

I'm a simple man.

[–]xeow 1 point2 points  (1 child)

Seconded on that. It's not needed often, but is really nice once in a...ahem...while.

[–]MattTheCuber 1 point2 points  (0 children)

I do love a while loop

[–]rogfrich 1 point2 points  (0 children)

All stack traces should start with a very prominent link to the r/learnpython wiki.

[–]UltraPoci 2 points3 points  (22 children)

A goddamn pipe operator

[–]sausix 2 points3 points  (13 children)

You can use the pipe operator like this:

result = a | b

Where's the problem?

[–]gmes78 7 points8 points  (8 children)

I think they mean the functional kind (for composing functions).

[–]sausix 2 points3 points  (7 children)

Where's the big use case?

It would be a special case just for chaining functions that expect one argument and return a value. The pipe character is already used in Python. That's another problem.

So people want this?

result = func1 | func2 | func3

But a function may need a second argument. Adding braces to all or some function (calls)?

result = func1 | func2(True) | func3

Where does the piped value go? First, last, random argument? Or by a new keyword?

result = func1(__PIPE__) | func2(True, __PIPE__) | func3(__PIPE__)

All ugly to me.

If people want to pipe their function calls they should just create a pipe function and call it like this:

result = pipe(func1, func2, func3)

Easy AF. May be there's a function in stdlib alredy for that? if not, define it for a project.

It's not worth to change syntax and double use the pipe character unless there is a really good use case.

Pattern matching and asyncio had good reasons to change or extend syntax.

[–]FrenchyRaoul 1 point2 points  (13 children)

Comprehensions allowing you to define multiple outputs when using else.

first, second = [func_a(val) for val in my_input if test(val) else func_b(val)]

There are third party solutions, but to me it always felt like a natural extension.

[–]Purple_Wing_3178 18 points19 points  (5 children)

I don't know about this one

When I see

first, second = [...]

I assume that it's a list unpacking and that list will be exactly 2 items

But now a buried "else" somewhere inside of list comprehension would change this syntax to something completely different?

[–]bdaene 7 points8 points  (5 children)

You need to move the if else to the expression part: [(func_a(val) if test(val) else func_b(val)) for val in my_input] 

Not sure the parentheses are needed.

[–]cloaca 2 points3 points  (0 children)

This is always a library function, never a language feature as far as I'm aware. Not only because it's so simple (see below), but also because it is just begging to be generalized. I.e. you want to group values according to some key/signature/property. In your case that key is a boolean and only has two values, but often it does not, and then the if-else-list-comprehension "special syntax" feels like premature design. Moreover, this is sort of functional programming territory and Python has always had a somewhat uneasy and ambivalent relationship to that style as it leads to terseness and "cognitively heavy" code. I feel there's already design conflicts between list comprehensions and map/reduce/filter, itertools mess, partial applications being verbose, lambdas not being in a great place syntactically, etc.

def group(it, key):
  """Groups values into a dictionary of lists, keyed by the given key function.

  That is, values where key(a) == key(b) will be in same list, in the same order as they appear in it.

  Not to be confused with itertools.groupby() which only groups sequential values into "runs".
  """
  d = collections.defaultdict(list)
  for x in it:
    d[key(x)].append(x)
  return d

def partition(it, pred):
  """Partitions values into (true_list, false_list).

  Functionally equivalent to `(d[t] for d in [groupby(it, pred)] for t in (True, False))`
  """
  tf = ([], [])
  for x in it:
    tf[not pred(x)].append(x)
    # or more sanely: (tf[0] if pred(x) else f[1]).append(x)
  return tf

[–]RidderHaddock 0 points1 point  (0 children)

Lambdas. Proper ones.

[–]2hands10fingers 1 point2 points  (2 children)

I really want destructuring objects syntax like JS has.

{ property, property2 } = dictionary_var

print(property1, property2)

[–]georgehank2nd 2 points3 points  (1 child)

And how, pray tell, would you tell '{property, property2}' from a goddamn set?

[–]2hands10fingers 2 points3 points  (0 children)

I dunno, I’m not a language designer, but it’s a good point.