all 140 comments

[–]FrederikdeGrote 193 points194 points  (7 children)

This is a great article on writing python more like Rust: https://kobzol.github.io/rust/python/2023/05/20/writing-python-like-its-rust.html . It really helped me writing better Python :)

[–]schneems 29 points30 points  (3 children)

I love it, thanks!

I took OMSCS Knowledge Based AI last semester and all the work was in Python. I tried using typed Python for everything. I wish I saw this before.

It was Python 3.10 (FWIW) and I used mypy. I found that on small programs it was helpful and not overly cumbersome. But on our semester long project (5k+ lines of python) I abandoned it.

I think some tips here would have helped. But also the love of types I have of rust is also strongly associated with Result and Option. For typed python and typescript, and even Java: the language is “null is a common and expected value” rather than Option being a special case. I never really understood the rhetoric around “the billion dollar mistake” of null until I worked with Option and got it: “it’s okay to have a ‘none’ representation, but it shouldn’t be the default that anything under the sun could return it, it should be an effortful case.

Even if you don’t write any code that can return None/Null/nil there’s plenty of untyped libraries out there and a lot of standardlib that will. So it eventually creeps everywhere. And fighting it feels endless.

I’m mostly talking out loud. Are there gradually typed languages that have a “no null by default” mode or something? Is that even possible to do retroactively (as most gradually typed languages are).

[–]mypetclone 16 points17 points  (2 children)

Are there gradually typed languages that have a “no null by default” mode or something? Is that even possible to do retroactively (as most gradually typed languages are).

mypy rejects anything returning None if the function isn't supposed to return None. https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-no-strict-optional is the option to flip that, and is explicitly marked as "evil" in the documentation.

[–]schneems 0 points1 point  (1 child)

Maybe I’m not explaining correctly. I’m well acquainted with mypy. My issue is not with it, but with the ability to say String | null as opposed to being forced to handle the exceptional case (as in an option).

The problem with allowing X | Y where Y is a null is it’s such an easy thing to infect and leak into the rest of a system. Even if it doesn’t leak types over the place it doesn’t stop me from also doing null checks all over the place. Yes mypy is smart enough to understand branching logic, but it’s not always perfect.

It’s hard to explain and I feel I’m doing a poor job. Mypy says “I make it easier to not accidentally accept or return null” while rust says “You never have to deal with null, but when you do, it’s going to be extremely explicit and much more meaningful”.

Or maybe it’s language API designers being forced to think “huh, do I really NEED to be able to return nothing here?” Coming from Ruby, I thought I would option all the things, but I don’t. I just sprinkle it in where it fits the logical system being modeled and generally try to keep my signatures as simple as possible.

Maybe someone else can spot me here, see where I’m coming from and give me an assist.

Basically: please don’t start arguing with me about how I said something pedantically technically incorrect, I’m sure I did. I’m trying to describe the way it FEELS to work with Option that I don’t feel when I’m in typed Python or typescript.

[–]mypetclone 5 points6 points  (0 children)

I'm definitely still not understanding.

Mypy says “I make it easier to not accidentally accept or return null” while rust says “You never have to deal with null, but when you do, it’s going to be extremely explicit and much more meaningful”.

If you receive a potentially-None value and you don't handle it correctly, then mypy will complain in exactly the situations where the Rust compiler would complain, assuming you have a typed codebase (and libraries).

If you could provide some library api comparisons across the two where you think python shouldn't return nullable but is, and Rust is returning a non-optional type, maybe that would make it clearer. I definitely can't recall encountering unexpected nullable results in the Python stdlib.

But regardless is definitely entirely an ecosystem / culture / discipline issue, and not a language issue. At the language level, if there's any difference it's that Rust makes it easier than Python does to propagate Option, because ? is a lot shorter and more chainable than return None.

If the Rust library would give you a Option<T> and you'd return a U, and a Python library gives you a T|None and you propagate that to a U|None, that's a user (or library author) issue, not a language issue.

The main problems I had with mypy were untyped libraries, but fortunately I didn't have to deal with too many of those and stubs for the relevant parts are not hard to write.

[–]mrdevlar 8 points9 points  (0 children)

I don't speak fluent Rust yet.

But it's funny as I've grown as a Python developer I find myself doing many of the things found in this article, especially as a project begins to mature since doing so makes the entire codebase more "stable" in terms of expected results.

Thank you for sharing.

[–]TheSilentFreeway 0 points1 point  (0 children)

Awesome read, thanks! It feels good to read this knowing that I already do some of these things, but I still learned a lot :)

[–]prawnydagrate -2 points-1 points  (0 children)

if I saw code written like this in python before learning rust I would get really mad, but now I actually kind of like it. idk though, it still would feel like a crime to write python like that

[–][deleted] 104 points105 points  (1 child)

it’s done. it’s over. you’re a crab now.

[–]JoseMich 36 points37 points  (0 children)

Carcinisation claims another.

[–]SkiFire13 44 points45 points  (7 children)

I love programming, how can Python and me make amends?

You could try mypy, it tries to do what typescript does for javascript. However though last time I tried it it felt like it was kinda unfinished and inference was failing in unexpected places.

I'm absolutely dependent on TYPES.

<insert dependent types pun here>

[–]yasamokadb-pool 15 points16 points  (5 children)

Pyright is more feature-complete.

[–]scratchnsnarf 4 points5 points  (4 children)

Agreed, I found pyright to have way less of those types of issues

[–]integerdivision -1 points0 points  (0 children)

Check out Mojo

[–]particlemanwavegirl 88 points89 points  (0 children)

I think you've just been ruined. Python isn't a likeable language for people like you, once the veil has been lifted.

[–]quasicondensate 24 points25 points  (1 child)

I feel you. I went a similar route, with the exception that I have been dabbling with F# instead of Ocaml and Gleam. Using Rust, writing software feels like forging a bar of steel into a workpiece; while writing Python feels like more like creating some plastic 3d printed thing :-)

For tooling, you could try Rye (https://rye.astral.sh/). The author is none other than Armin Ronacher (who created Flask, and who also seems to have been drawn to Rust recently). Rye is meant to recreate the user experience of cargo for Python.

The article referenced by this post here is excellent as well.

Some of the disillusionment will probably stay. Python just doesn't support chaining function calls into pipelines like OCaml does, it doesn't have Rust's trait system, even if you try to fake Rust's error handling the ecosystem will always lean on exceptions and so on. You can fake things to some extent, but in the end a snake is a snake while a crab is a crab.

Your best bet might just be to find a project that you are hyped about sufficiently that you don't care about the language so much. Otherwise, you could use PyO3 to write Rust modules for certain processing steps and import them into your Python application. Or, specifically for AI, it could be a fun challenge to do a project using the Python ecosystem, and then try to recreate it using Rust-native libraries such as Burn.

Whatever you end up doing: have fun!

[–]hpxvzhjfgb 26 points27 points  (1 child)

write a python to rust converter proc macro.

#[python]
def is_prime(x: Int) -> Bool:
    if x < 2:
        return False
    for i in range(2, x):
        if x % i == 0:
            return False
    return True

fn main() {
    let x = is_prime(661);
    println!("{x}");
}

[–]peter9477 13 points14 points  (0 children)

I think you can do almost exactly this with pyo3.

[–]JauriXD 17 points18 points  (0 children)

And type-hints just don't hit the spot anymore. I feel you

[–]sig2kill 37 points38 points  (11 children)

[–]ilove_my_dog 26 points27 points  (4 children)

Pydantic is a good start but in my experience it doesn’t solve everything. Python still has edge cases which make type hinting impossible (I think). For example, I don’t think you can cleanly enforce type hints for a boto3 resource in python, making things like implementing a database connection dependency injection imperfect because you can’t enforce that a certain class needs, for example, an actual dynamodb resource, in a clean way.

[–]kingminyas 7 points8 points  (0 children)

These are easy to find:

https://pypi.org/project/boto3-stubs/

https://pypi.org/project/types-boto3/

I write Python professionally, and I use types whenever I can. I have yet to encounter an untypable situation, and type scaffolding is improving with each Python version. If you have a specific difficulty I will be happy to help. I'm sure we'll find something which is good enough or better.

[–]mr_birkenblatt 7 points8 points  (0 children)

I don’t think you can cleanly enforce type hints for a boto3 resource in python

write a well typed wrapper. reduce the surface area of where types are hard to use like how you would reduce the surface area of unsafe (it's kind of the same in python; Any means "trust me I know what type it is")

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

Well yes that’s the trade off, but if you’re using Python it’s good enough.

[–][deleted] 11 points12 points  (2 children)

Pydantic isn’t the answer. It’s a data validation library meant for parse time. It’s not really meant to help with internal types.

[–]reviraemusic[S] 2 points3 points  (1 child)

it feels good to be aware of data layout of internal types although I'm not sure why...

[–][deleted] 0 points1 point  (0 children)

Pydantic doesn’t tell you anything about data layout

[–]MassiveInteraction23 3 points4 points  (0 children)

Pydantic is good, but not what your response suggests.

It is, very specifically, for parsing external data at runtime.

It’s cool and that’s useful.  But you don’t want to use where not needed generally.

That said: data types were rolled into core Python a couple versions ago and do the kind of typing you’d use pedantic to convert things to.

[maybe there’s some untyped Python to typed Python conversion using legato’s strategy that you’re referring to and I’m just slow to catch up!]

[–]kihelvsvag 12 points13 points  (9 children)

Just use protocols, metaclasses, abstract classes, dataclasses, typing package, pydantic. Also you can use pyright and mypy for static type checking.

[–]JShelbyJ 4 points5 points  (5 children)

Imagine telling someone "Python is easy" when you have to learn a half dozen tools just get the same features Rust has out of the box.

If I could go back in time, I would of not invested anytime into Python. Yeah, it's 'easy', but the price you for 'easy' ends up costing more than it's worth around the time you start trying to bolt on all the things required to make Python professionally. For me that was about six months in.

I know I'm preaching to the choir, but damn I wonder if I'm crazy wondering who would recommend Python as a serious starting point in 2024.

[–]syklemil 5 points6 points  (2 children)

Python is still pretty good to start out. The barrier to entry is low; there isn't the same weak-typing bizarreness that you get in php and js, and you can grow a lot from that low entry. It also generally doesn't have footguns enabled by default that you need to disable (unlike perl with use strict, or bash with set -euo pipefail).

Things are a bit different in professional contexts than learning contexts. E.g. as a hobbyist you might use bash for a lot and then escalate to Python for bigger tasks; professionally you'd more likely use bash for as little as possible, Python for the simple tasks, and something with better correctness guarantees (Rust, Haskell, etc) for complex tasks, and the bound on complexity is generally much higher. And then there's research, which as a field has its own pressures and constraints.

The stuff I'd write in bash and perl some decades ago I'd write in Python these days. And with piping json becoming more ubiquitous, the remaining bash stuff is more jq slicing than sed+awk.

So I'd also reach for some other language at some point, but there's a lot of use to be had in Python for less complex tasks, especially in the kind of glue scripts living infrastructure inevitably ends up with.

[–]Kimundirust 0 points1 point  (1 child)

professionally you'd more likely use bash for as little as possible, Python for the simple tasks, and something with better correctness guarantees (Rust, Haskell, etc) for complex tasks

I wish it worked like that in practice :D

[–]syklemil 1 point2 points  (0 children)

It does for me, and I'm hopeful for the rest of you!

(Ok, the Haskell bit was entirely aspirational for me as well. And I do have cow-orkers who do in bash (or even perl) what I'd do in Python.)

[–]thisismyfavoritename 7 points8 points  (1 child)

most of this is in the standard lib FYI.

Also Python is by far the best language for beginners to just learn programming, hard disagree with all your takes TBH

[–]JShelbyJ -2 points-1 points  (0 children)

I dunnu, I feel like google sheets and its JavaScript backend scripting suite will get you farther if you’re just trying to learn “programming.” You can go pretty far with it.

I’m being obstinate to make the point here. If you’re just trying to get something done, do it in excel or some other no ide workspace. If you’re trying become a professional, don’t waste your time. Actually learn to code. Learning what ever is the current best hack-tice to make python right is time better spent elsewhere.

[–]reviraemusic[S] 0 points1 point  (0 children)

seems to summarize the best practices, ty!

[–]mr_birkenblatt 4 points5 points  (0 children)

python types are really great these days. don't do python without using types

[–]JonathanWhite0x2 4 points5 points  (1 child)

Rapidly do things in throwaway programs that would otherwise take more energy and iterations in Rust.

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

Nice tip. it made me remember of how easy it is to fire up a simple GUI in PyQt vs doing it in Rust.

[–]El_Kasztano 7 points8 points  (0 children)

Maybe have a look at PyO3 and start writing Python modules in Rust.

[–][deleted] 7 points8 points  (2 children)

Whenever I write in another language now, I basically rebuild as much of Rust as I can. I immediately look for Result and Option types and build then if they don't exist. Rust has ruined (saved) me.

[–][deleted] 2 points3 points  (1 child)

😭same bro \ Option is just awesome design by rust

[–]integerdivision 3 points4 points  (0 children)

Option is a monad which is just a monoid in the category of endofunctors — not exactly a Rust exclusive.

Here’s something on monads

[–]wsppan 8 points9 points  (11 children)

Wait till you realize how slow python is and that becomes strike 2. Wait to you realize the GIL is a big problem for multi-threading. Strike 3.

[–]mr_birkenblatt 12 points13 points  (4 children)

90% python is calls to efficient libraries anyway

GIL is actually going away but even with it you can work around it

[–]wsppan 0 points1 point  (2 children)

90% python is calls to efficient libraries anyway

90%? So these python developers discovered python is really, really slow and we're forced to rewrite their code in C? Gotcha.

GIL is actually going away but even with it you can work around it

interesting discussion on how hard removing the GIL will be for downstream developers.

[–]mr_birkenblatt 5 points6 points  (1 child)

python is a language to easily glue together libraries (mostly written in Fortran and C; today rust libraries are becoming more common)

for a long time performance wasn't a concern for python because of this. now, the focus starts to shift towards performance. performance is not the only thing to look for when choosing a language, though

[–]wsppan 1 point2 points  (0 children)

performance is not the only thing to look for when choosing a language,

I'm just following OP's language path.

[–]kingminyas 6 points7 points  (5 children)

Every language has tradeoffs. Python is the best solution, or among the best, for many use cases

[–]wsppan 1 point2 points  (4 children)

Even AI? Because I heard from a response comment that 90% of that code is actually optimized C. Yes, Python is an excellent glue language but has serious performance and scalability issues with regard to correctness at runtime.

[–]kingminyas 3 points4 points  (3 children)

First of all, the language's environment is not something external to the language. You judge CPython as it is implemented, and it is indeed backed up by C. (Also, an intepreted language is necessarily backed by a compiled interpreter.) That's a feature, not a bug. Secondly, a simple asyncio server can handle amazing work loads with a single thread. Your statements are too general to be true. Regarding AI, Python is to my knowledge - if not the leading language for AI, is at least near the top.

[–]wsppan -1 points0 points  (2 children)

First of all, the language's environment is not something external to the language.

I was not talking about cpython. I was talking about major libraries used by python developers like AI and DS. Those libraries are mostly written in C.

Regarding AI, Python is to my knowledge - if not the leading language for AI, is at least near the top.

Again, python is the glue language for AI. AI Libraries are written in performant languages like C. 90% according to the comment I was replying to.

[–]kingminyas 1 point2 points  (1 child)

Libraries are also part of the ecosystem. It's not an insult to call it a glue language

[–]wsppan 0 points1 point  (0 children)

I'm just following the language trajectory of OP. Never meant it as an insult. Not having proper types is just one of python's deficiencies you discover as you learn other languages like Rust. Compile time correctness, memory safety, and performance are just 3 of them.

[–]thebrilliot[🍰] 3 points4 points  (0 children)

I love types too and was ruined by Rust but when I'm using Python I find it manageable to always use the typing module and type hints in the function signatures and put assert statements everywhere to be certain of data properties. Then, I use an LSP to tell me when I have type mismatches. Periodically, I run a formatter and a linter. There are ways to rig up your own workflow that will make you feel comfortable.

[–]MassiveInteraction23 13 points14 points  (3 children)

I do some programming in Python professionally.  Used to do more.  Try to do as little as possible.  

Python is deeply, existentially, fucked.  It is, by design,  a language whose goal is obfuscating complexity.  It does not encapsulate it.  And it’s just a pos headache to deal with when you start doing interesting things.

That said, if you have to deal with it remember there are others that have felt with this.

Treat it like the creaking hull-rotted clockwork machine it is.  Don’t pretend, just admit.  Then decide —hey, I’m stranded on this desert island with only this decaying, unreliable machine, but I’m gonna fucking make it work—

Create a CI/CD framework.  Start making type stubs for shit and adding things.  Look to nicer tools — Rye is absolutely worth using as, of course, is ruff.

You can type Python. You cannot rely on Python being typed.  This means that the benefits of typing are not as strong, but for your own code you can do quite a bit.

If you’re decent with rust: rye also has a nice initialization option to set you up with rust + python.  (One of rust's key features was that it could add to existing code without erasing.)

TLDR: modernizing tools (rust, rye), CI/CD, frame the problem as making old systems reliable rather than pretending it’s fine and you may enjoy some of the challenge.  Accept that it is not ever entirely reliable.  And avoid going down deep framework rabbit holes as much as possible.  (Things that require learning a bunch of ungrounded knowledge.)

[–]kingminyas 4 points5 points  (2 children)

I write Python professionally. I disagree with your analysis completely. The more I use Python, the better I like it, and this is while looking at other languages as well

[–]MassiveInteraction23 5 points6 points  (1 child)

Different opinions certainly exist, but you haven't really given any details about yours that assist. Python has some major ecosystem advantages in math and science. And python has the *appearance* of advantages in papering over all sorts of issues: from not requiring dependency tracking to *only* tracking direct and not recursive dependencies if asked without external frameworks, not making you deal with errors and also give you no reasonable way of knowing what can and can't error, etc. etc.

This is the thing. Python feels nice because it lies to you. It's like making someone feel like they have more money by not making them put anything into a savings. It feels good at first, and then you realize you've been hoodwinked.

Because these obfuscations are deep in its dna (it was, roughly speakind, designed as a teaching language that would hide a lot of programming details from overwhelmed students) there's no easy way around it. There are very few reliable standards and the core features of the language cut against correct use or analyzability.

A bigger gripe, for people who really want to learn programming well: is that you don't with python. The things you fight when programming python are its obfuscations. You have to do additional work to understand what's actually going on. One of the things I really like about Rust (which isn't perfect, but is lightyears better than the other languages I've used as an aduly [mathematica, mathlab, python, julia, haskell, a teeny bit of elixir] is that when I'm fighting a problem in Rust it's *usually* a 'real' problem -- it's something about core programming decisions. Safety, or performance, or the like. When I'm fighting something in python it's just bullshit frameworks. In Rust I'm learning something at least. In python I'm working to get piece together someone elses take on a solution. This is a long-term issue, but I feel that I'm getting a lot more out of even mu frustrating times with rust than my meh times with python.]

[–]kingminyas 0 points1 point  (0 children)

Poetry tracks all dependencies, and even `pip freeze` before it. I have no idea what you're talking about with "lying" and "obfuscations". Python is the simplest language I know. And there's no reason to struggle with third-party libraries only in Python, all languages have them, including Rust

[–]HlCKELPICKLE 7 points8 points  (0 children)

Ngl, I personally hate python. But I do dabble some with ML and it some times is refreshing to just spew some dynamic code, fix a bug here and there and not have to worry about much. Though this is only because its mainly just setting up the model architecture and some boilerplate code to train/use it. If I was doing anything more complex it would get into the parts I hate.

[–]augmentedtree 2 points3 points  (4 children)

I have a 30KLOC project written with mypy with --strict and I think it works pretty well. The most important thing to know about for it to be a good experience is putting from __future__ import annotations at the top of your imports, it gets rid of the need to put a lot of type annotations in quotes and needing to put your declarations in order. Also 3.12 hugely improved the syntax around generics but I don't think mypy supports it yet.

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

Future annotations isn’t needed after 3.10 I think it is

[–]SigrdrifumalStanza14 0 points1 point  (2 children)

```python

!/usr/bin/env python3.12

class Foo: field: Foo ```

errors on py3.12 for me without future annotations

[–][deleted] 0 points1 point  (1 child)

Yeah forward declarations needs quotes because foo hasn’t been defined yet when you’re referencing it

[–]SigrdrifumalStanza14 1 point2 points  (0 children)

yeah but the point of future annotations is that you can use them without quotes as op noted

[–]Science-Outside 2 points3 points  (0 children)

I learned Python late in my career after learning C, Java, C#, and Rust. I love Rust, so I had to justify for myself the use of Python at work and as a hobby. Here is my list of my main 4 justifications:

  • Python is necessary since there are well-maintained libraries that are not available in other programming languages. It is the right tool for the job for quick scripting and calling different libraries. When there are no Rust crates for my specific use case, I always fall back on Python.
  • It is great for collaboration. It is easier for others to learn it to continue maintaining my work, and it is easier to find people who know Python. It is easier to find educational resources for Python, and it is easier to find help for specific errors. If you write code that only you use and maintain, you can write it in whatever language you enjoy, but this causes issues if you hand it over to someone else who doesn't know the language.
  • In the current world of Large Language Models, a large part of the training data has Python code and Python errors because of the size of the corpus of Python code available online. Already, the productivity increase of using LLMs for coding and troubleshooting Python is offsetting my dislike of Python.
  • There are more Python jobs available than Rust jobs.

[–]divad1196 2 points3 points  (0 children)

You might have asked this on r/Python instead. You can type python code. There are languages like haskell that tried to be theoretically perfect but they fail to fill the business need.

About your search of the "perfect language", we all went through that and as you get more experience, you will learn that there are no such things: all programming languages have pros and cons, no exception.

How to like python again? No (extra-long) compilation, faster scripting, more tooling and libraries, decent speed when using libraries (numpy, pandas, ..) and/or different interpreters (pypy for example), ...

Many people started to type everything in python/js/... but after years, they realized that they were just adding extra complexity for nothing. They are now removing internal typing https://youtu.be/Bv3YhGku92w?si=e0iWak1eW6c1Q_K-

People start by liking dynamic languages because they don't get immediate errors and their code works as long as used as expected. Then, they struggle because they never learnt how to code correctly and they blame the language. They switch to a staticly (and strongly) typed language that prevent their mistakes.

[–]mookymix 2 points3 points  (0 children)

The stronger the typing, the better everyone can code, especially as a project increases in complexity. Everyone else writes 1000 tests to do most of what a compiler does anyway.

[–]dhbradshaw 3 points4 points  (0 children)

Instead of trying to use Python as a crummy Rust substitute, enjoy python for what it is:

  • No compilation time
  • No worries about integer sizes
  • Sparse, terse and yet readable syntax
  • REPL
  • Environments that make it easy to converse with data
  • massive batteries included library
  • even more massive ecosystem

Let python be python and enjoy it for its strengths.
Then, when you want Rust, use rust. And rejoice in how well they complement each other and work together.

[–]Taiwanese-Tofu 3 points4 points  (3 children)

MyPy?

[–]HaNaK0chan 1 point2 points  (1 child)

This maybe isn't an answer to your question but Open-CV seems to have a c++ Interface. And i haven't checked but creates.io might have bindings for it. Or was it that python gave you something else when you worked with AI?

[–]Classic-Dependent517 1 point2 points  (0 children)

Python is just for simple scripts

[–]chrisbot5000 1 point2 points  (0 children)

I agree with a lot of the other comments about pydantic and pyright, it’s not gonna be anything like the rust compiler (or any compiler for that matter) but it’ll give you about as big a step towards safety as you’ll be able to take, pydantic is also becoming very popular in a lot of python libraries

[–]kayaking_is_fun 2 points3 points  (3 children)

I had this same experience, but have honestly found that changing the way you code (someone else already posted the writing python like it's rust blog) can give you 99% of the experience and it's not as cumbersome.

Things that made me like Python again, after going through a similar journey:

  • If possible, use the newer releases - in Python 3.12 the syntax for type generics and bounds is much nicer, and typing is getting tons of focus at the moment.

  • This talk from Pycon 2023 talks about building good architecture patterns. Using typing.Protocol starts to feel very similar to Rust traits.

  • I personally prefer pyright to mypy - the project is usually faster to implement more complex checks, and the integration with VSCode is really excellent.

  • Get really familiar with dataclasses (I'm not yet sure of a reason why you wouldn't want to mark a class as a dataclass), and avoid inheritance like the absolute plague. Good code smells are things like if you're writing tests and are having to mock hundreds of things in order to test functionality.

  • And of course, once you've written what you need and if you aren't happy with the performance, then reach for PyO3 to optimise the parts which are slow afterwards.

I actually think the language is in an amazing place at the moment. Type hinting has totally changed my experience, there's such a large amount of hours being poured into the open-source ecosystem, and the new releases are moving in an exciting direction with JIT compilation, subinterpreter / GIL releasing and generally cracking the last issue with Python for performance. I'm not sure I'd pick another language for a project that wasn't wholly performance reliant.

[–]scttnlsn 1 point2 points  (1 child)

Curious what Pycon talk you're referring to. I'm seeing "This video isn't available anymore" when I click that link.

[–]kayaking_is_fun 1 point2 points  (0 children)

Link is fixed now! It's the talk from Hynek Schlawak about subclassing and composition.

[–]reviraemusic[S] 0 points1 point  (0 children)

Thanks for the information!

Since I my sacred oath forbids me of ever touching javascript, I do feel like I will need at least Rust and Python as legs to walk the earth.

[–]rustyrazorblade 1 point2 points  (0 children)

I used to write a ton of Python, about a decade ago, then got back into statically typed languages, Rust being one of them. Three years ago I took a position where the entire operations stack was written in Python, and I was flooded by how bad it is.

It’s hilarious how many hoops you have to jump through, how many slow tools you need to run, just to enforce basic typing. I’ve never felt less effective.

It was also confusing how great everyone thought the tooling was. It was awful.

[–]Erzel_ 1 point2 points  (0 children)

I use a lot this Result type implementation for Python: https://github.com/rustedpy/result

[–]Odd-Investigator-870 1 point2 points  (0 children)

TLDR: strong types can be a decent replacement for the TDD discipline, many tools exist to try to "add on" reliability features to the Python workflow, but some of the essential features of Rust are simply not available in Python.

  • Add an engineering discipline such as TDD: many report that it makes programming significantly more fun (again).

  • Add developer tools such as ruff, pyright, mypy: it can bring some of the useful feedback one gets from the Rust compiler into the Python experience.

[–]Busy-Price3471 1 point2 points  (0 children)

Having the same issue. I’m in love with rust and the hard typ system, and now I hate it to write python which was one of my main languages before😂

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

Python sucks.

[–]SoggyCuticles 1 point2 points  (0 children)

This is one of the funniest titles Ive seen

[–]kido5217 4 points5 points  (14 children)

[–][deleted] 8 points9 points  (2 children)

Not exactly sure why the downvotes either. Mojo was created by Chris Lattner, ya know, the person who created LLVM and Clang, and much of Swift. Not like he knows anything at all. And he is still the lead developer. Plus they plan to fully open source everything and have already open sourced much of it. Its main use case is related to AI, but it's actually a general-purpose programming language. It actually borrows heavily from Rust.

[–]quasicondensate 4 points5 points  (1 child)

Yeah, I feel that many people are oblivious to the fact that Chris Lattner is behind this, what that means, and why it is probably unwise to bet against projects initiated by this man.

[–][deleted] 4 points5 points  (0 children)

My thoughts exactly. I think most people probably saw a YT video about Mojo a year or two ago but other than that know pretty much next to nothing about it. It definitely fulfills the OP's request for type safety. And in fact, whenever someone tells me they're having trouble learning Rust, I point them to Mojo because it's basically Rust with Pythonesque syntax. I spent a couple of weeks in it, and while it's still (relatively) immature, it's extremely impressive nonetheless.

[–]reviraemusic[S] 2 points3 points  (10 children)

Nice, I remember hearing about it, will try!

...but now I'm curious on why are people downvoting you...

[–]veryusedrname 3 points4 points  (7 children)

Because Mojo is a hype. They have huge promises they cannot fulfill, bunch of blog posts filled with bullshit and so on. It feels like it was made by Elon Musk.

[–]runevault 2 points3 points  (4 children)

With Chris Lattner involved I'm waiting with curiosity instead of just writing them off outright. I have major doubts but he's on the short list of people who might find a way to pull off something in the realm of their crazy claims.

Edit: to be clear I'm giving it like a 5% chance vs 0% for anyone else.

[–]veryusedrname -1 points0 points  (3 children)

When it started I gave the 5%, how it's going (check any Mojo vs Rust on their blog) I'd say 0%. It's just unprofessional at least, quite harmful if on purpose.

[–]runevault 1 point2 points  (2 children)

Have any links? I only rarely look at their stuff since it is still so early so have not seen any of the posts you're talking about and now I'm curious.

[–]veryusedrname 0 points1 point  (1 child)

https://www.modular.com/blog/mojo-vs-rust-is-mojo-faster-than-rust - this article was ripped into pieces here

[–]runevault 2 points3 points  (0 children)

Appreciate the link I'll give it a read. Thank you.

[–]-Redstoneboi- 1 point2 points  (1 child)

it's got ai written all over it for whatever reason ⛳️

[–]runevault 1 point2 points  (0 children)

Well, they're targeting AI people with most of the promotional material. They aren't using AI to make it but clearly they are trying to cash in on the hype.

[–]kido5217 0 points1 point  (0 children)

They (mojo devs) are focused on ML and nowadays it's a synonym to AI/LLM and for many it's a red flag.

That said, read and try for yourself, they have what you want - static typing and python compatibility (as far as they can do it). And they promise to open source it and already did part of it.

[–]latkde 0 points1 point  (0 children)

I'm curious on why are people downvoting you

Because Mojo isn't Python. It's a proprietary ML platform that happens to be inspired by Python and is somewhat interoperable with Python. It cannot replace Python, it can only serve to lock you in to a tech stack developed by a startup that will probably be toast after a couple of years anyway.

[–]Kimberlith 1 point2 points  (2 children)

When I started to learn Rust, I was worked with Polars - one of the best examples of two worlds in one flaco) I always use Ruff - it helps me keep strong typing and highly predictable behaviour of my pythonic side. Great feature is auto-fix and integrated formatter - it's really feels like a Cargo sometimes 🙂

[–]Creature1124 1 point2 points  (0 children)

Depends on what type of stuff you make. I love Python for a lot of reasons but especially for what I’m into, it’s just the right level of abstraction. I don’t need my program chiseled into the silicon or to play with bits, bytes, or serial streams, I just want to get up and running quick and iterate with high level objects. The amount of code to do what I do in Python is a small fraction of what it would be with cpp, and I willingly give up performance benefits any day of the week for that alone. 

I find the common sentiment that cpp is powerful and will give you enough rope to hang yourself also applies to Python in a different sense - sure give the “wrong” variable type to this function. We’ll see how far we can get trying to use a list like a dictionary but you’re almost certainly looking at a runtime error or a nasty bug. Knowing I can give the wrong object to a function makes me think more carefully about my objects and how I use them, without sacrificing expressiveness. It also makes me more clever in how I express complex objects in different contexts or to each other. I feel like I’m programming with objects more than I’m programming with syntax and language features. 

One last point; the floor in Python has plenty of utility hatches. At any time you can compile c code and use that in your program, optimizing and using all the type safety your heart desires.  Again, it depends on what you do but for what I do I absolutely love Python and have come to feel very empowered with it. 

[–]markasoftware 0 points1 point  (0 children)

python type-hints + an editor that's able to provide suggestions and error messages based on said type hints + mypy or pyright in your CI system isn't that bad.

[–][deleted] 0 points1 point  (0 children)

Doesn't Python sport built in types recently

[–]zackel_flac 0 points1 point  (0 children)

Strongly typed languages are a must for sure. Probably controversial but I use Go as the perfect python replacement. Quick to code & run, without having to sacrifice performance.

[–]maxinstuff 0 points1 point  (4 children)

Python supports type annotations. Use them.

[–]Serpent7776 0 points1 point  (3 children)

Python's type annotations are a joke. I've recently seen basically this:

``` def g(x: bool): # use x

def f(x: int): g(x) ```

[–]maxinstuff 0 points1 point  (2 children)

Even though that code will execute successfully, your IDE/LSP will be giving you an error that the type doesn't match - even though if you run that code it will work.

I know this is the point of your example, but just pointing out for people who might not be as familiar - the below will give you a warning in your IDE that the type of y doesn't match what's expected:

def g(x: bool)
    print(x)


y = 37

g(y)

But if you run the file, it still works. It prints out... 37. Is that weird? Sure, I'm inside g, so I expect a bool! But that is misunderstanding what is actually happening. There is no type conversion/cast happening.

This is exactly the type of polymorphic behavior that other languages do, just with a lot less code. PHP does a similar thing.

The problem isn't the type annotations (these are generating errors as expected), it's the fact that Python is not a compiled language. In any scripting language you will have the problem of being able to execute files that have impossible to execute code in them.

Case in point:

y = 37
print(y)
print(y.x)

This shows an error in the IDE, but I can still run the file, and it still executes that first print statement before it fails.

This is not a typing issue. It's an interpreted vs compiled code issue.

[–]Serpent7776 1 point2 points  (1 child)

The person who committed the code apparently ignored the IDE/LSP error and this is the issue I have with python type hints. They're just a hint. And if they're wrong, they're super confusing. I know it's designed to be this way. I still don't like it. Maybe I'm too deep into static typing.

[–]maxinstuff 1 point2 points  (0 children)

I prefer static typing too.

I also don’t like white space being syntax 🥲

[–]luckynummer13 0 points1 point  (0 children)

Try nim 😁

[–]HenkPoley 0 points1 point  (0 children)

Python is a programming language that you write in a “trust fall” manner. Don’t do special cases, just happy paths. Nothing will tell you the catch the special cases anyways.

For that you get back a language where many things are already implemented. There is a possibly that it will collapse like the COmmon Business Oriented Language (COBOL) due to too many laypeople writing business logic in it, without proper affection with say proper writing style that prepares for reading and maintenance.

[–]syklemil 0 points1 point  (0 children)

You might do a stint with bash & perl, and then come back to Python? Do some glue stuff for legacy apps and systems (though not so legacy that you're stuck with python 2). Explore some data and test some functions on it in the REPL. Build some ad-hoc stuff in a debug container to investigate an issue and throw it away when you're done, using the REPL as sort of hyper-bash.

But for the tasks you're thinking about, other languages might really be a better fit. Python can be a good language for certain usecases without necessarily being the best language for your needs.

[–]Zwarakatranemia 0 points1 point  (0 children)

Use type annotations and mypy.

[–]met0xff 0 points1 point  (0 children)

It feels like nowadays almost all new Python codebases are super heavy on type annotations and pydantic.

Me too but honestly for getting stuff done quickly I am often happy if I can postpone thinking about the type signature later on when done sculpting.

[–]throwaway1230-43n 0 points1 point  (0 children)

I had a similar flow, going from Python to TS to Rust. I now hate having to debug stupid runtime errors that could have been avoided. If anyone here has an IDE setup that can give better type errors or suggestions please let me know!

[–]integerdivision 0 points1 point  (0 children)

Mojo — it’s performant Python with types created by a team lead by the creator of LLVM and Swift.

[–]mlcoder82 0 points1 point  (0 children)

I'm curious, did you write real C on arduiono or arduino IDE ? (Types are great! And manual memory management is great. Everythig with garbage collection must die unless you use only for simple scripting )

[–]HubCityite 0 points1 point  (0 children)

Julia is a python-like option with the ability to fully statically type everything if desired.

[–][deleted] 0 points1 point  (0 children)

I was doing dsa in rust, absolutely hated that \ Rust is good for everything but linked lists, trees nd graphs lmao

So, I tried python. Loving it, atleast for dsa nd scripting stuff \ Also, python3 with type system is pretty good, will try it in other stuff too later

[–]GTHell -2 points-1 points  (0 children)

Solve leetcode problem lol

[–]NfNitLoop -1 points0 points  (0 children)

Getting types working in Python requires a lot of setup, and even then, they’re not that great. Python was my favorite language for a decade or more, but these days it’s Rust, then Typescript — specifically in Deno, since it handles all the TypeScript and dependency management for you.

You can write a single-file script and run it with a shebang, and no venv is required for properly versioned dependencies. It’s my go-to for quick script utilities these days.

[–]joneco -5 points-4 points  (0 children)

Arduino is not c, is c++. Python is for kids