[HN Gopher] Python's "disappointing" superpowers
       ___________________________________________________________________
        
       Python's "disappointing" superpowers
        
       Author : nalgeon
       Score  : 111 points
       Date   : 2023-02-01 15:37 UTC (7 hours ago)
        
 (HTM) web link (lukeplant.me.uk)
 (TXT) w3m dump (lukeplant.me.uk)
        
       | fallingfrog wrote:
       | Don't fool yourself- if your programming language has an eval()
       | function, you are writing in Lisp and you are a Lisp programmer
       | now. Embrace it!
       | 
       | All joking aside, I do think Python is pretty handy.
        
         | tmtvl wrote:
         | Oh no, Lisp is so much more powerful. For example you can
         | update the definition of a class in a running system and update
         | all existing instances of that class. When an error occurs you
         | can inspect local variables in any of the stack frames and
         | execute commands in them. And that is only the tip of the
         | iceberg, Lisp is, as far as I know, without equal in terms of
         | power.
        
           | progval wrote:
           | > you can update the definition of a class in a running
           | system and update all existing instances of that class
           | 
           | Like this?                   >>> class MyClass:         ...
           | attr = 0         ...          >>> my_object = MyClass()
           | >>> MyClass.attr = 42         >>> my_object.attr         42
           | >>> MyClass.method = lambda self: self.attr         >>>
           | my_object.method()         42
           | 
           | > When an error occurs you can inspect local variables in any
           | of the stack frames and execute commands in them
           | 
           | What is the difference with
           | https://lukeplant.me.uk/blog/posts/pythons-disappointing-
           | sup... ?
        
       | [deleted]
        
       | DarkNova6 wrote:
       | Before I read this article I was not aware of exclusive
       | advantages to dynamic typing.
       | 
       | At least now I know what is achievable despite its presence.
        
         | ImprobableTruth wrote:
         | Which of these do you think require dynamic typing?
        
           | joshuamorton wrote:
           | A lot of the orm style things are not really feasible in
           | static-er languages without clunky approaches like codegen.
        
             | ImprobableTruth wrote:
             | What part specifically? Java is (in)famous for its orms
             | after all. Unless you want to count that as clunky codegen?
             | I'd argue that all metaprogramming boils down to that
             | though.
        
               | david2ndaccount wrote:
               | Java is actually a very dynamic runtime with a very
               | static language front end.
        
               | arcturus17 wrote:
               | The thread is about programming semantics though, so what
               | does that have to do with anything?
        
               | DarkNova6 wrote:
               | _cough_ Reflection. This also includes Annotations which
               | can give clear semantics to code generation.
        
               | jononomo wrote:
               | Unless you want to count Java as clunky? Well, I
               | definitely think Java is clunky. This article by Steve
               | Yegge, titled "Execution in the Kingdom of Nouns" sums up
               | Java for me: https://www.eecis.udel.edu/~decker/courses/2
               | 80f07/paper/King...
        
           | DarkNova6 wrote:
           | that's the point, none of these examples are intrinsically
           | linked to dynamic typing.
        
       | amelius wrote:
       | Is there any language out there that improves on Python in
       | various ways but still allows convenient access to literally the
       | entirety of Python's ecosystem of libraries?
        
         | sundarurfriend wrote:
         | PythonCall [1] and PyCall [2] provide pretty convenient ways to
         | interoperate with Python from the Julia language.
         | 
         | It has great package/environment management, excellent
         | (potentially close-to-C) performance, automatic type inference,
         | and a good set of interactive tools that make for a rich REPL.
         | 
         | But any such FFI (from any language) is an additional point-of-
         | failure, an extra gear that could break and has to be
         | maintained. And on the con side of Julia, there's an initial
         | compilation time (which is improving version to version, but
         | still a factor to consider).
         | 
         | Also it should be mentioned that the advantage of Python is not
         | only its ecosystem of libraries, but also the vast array of
         | tutorials and learning resources, and of development tools.
         | Those are areas where most other languages have to play catch-
         | up with Python, especially a relative newcomer like Julia.
         | 
         | [1] https://github.com/cjdoris/PythonCall.jl [2]
         | https://github.com/JuliaPy/PyCall.jl/
        
         | qsort wrote:
         | Hy: https://docs.hylang.org/en/stable/
         | 
         | I tend to stick to vanilla python though, mainly because Hy is
         | too much of an hassle for my use cases.
        
         | DarkNova6 wrote:
         | GraalVM myb?
        
         | cb321 wrote:
         | While I agree with the @elcritch reply
         | (https://news.ycombinator.com/item?id=34616755) that Nim is
         | just nicer overall, depending upon one's idea of "convenient
         | access to literally the entirety", Cython may be more to your
         | liking as mentioned else thread:
         | https://news.ycombinator.com/item?id=34616052
         | 
         | While usually pitched as "only" a language for fast extension
         | modules and/or bindings to existing C/C++ code, Cython is
         | really a language in its own right. https://cython.org/ has
         | some more details.
         | 
         | It works by generating C code that calls the regular CPython
         | API, managing all the ref count and tuple jazz that's rather a
         | hassle to write in C directly. Then you run a C compiler
         | against this code and it literally just links against the
         | CPython .so's/DLLs. So, it's not just calling module code the
         | same way as CPython, but actually calling the core built-in to
         | Python code the same way as well.
         | 
         | As you add more `cdef` type annotations to your cython code,
         | the generated C code becomes closer & closer to hand-written C
         | code (both in hazards and efficiency).
         | 
         | Of course, a caveat is that may be Cython also doesn't improve
         | upon Python very much as a language, except for allowing
         | gradual static typing.
        
         | elcritch wrote:
         | I've come to really enjoy programming in Nim. Note that Nim is
         | very different language despite sharing a similar syntax.
         | However, I feel it keeps a lot of the "feel" of Python 2 days
         | of being a fairly simple neat language but that lets you do
         | things at compile time (like compile time duck typing).
         | 
         | There's a good Python -> Nim bridge:
         | https://github.com/yglukhov/nimpy
        
         | bayesian_horse wrote:
         | Coconut, F# (Fable)...
         | 
         | https://github.com/vindarel/languages-that-compile-to-python
        
           | dunefox wrote:
           | F# is a great language... I wish I could use it at work.
        
         | lostmsu wrote:
         | Any .NET language with https://github.com/pythonnet/pythonnet
        
       | revskill wrote:
       | Let's stop calling "dynamic" and "static" versus "runtime" and
       | "comptime" instead ?
       | 
       | Also, "dynamic code generation" for "meta programming" ?
        
         | [deleted]
        
       | benreesman wrote:
       | I kinda hope we can just let Python be Python: it's in a global-
       | ish maximum for what it's for, and I suspect any big move away
       | from that will make it worse overall.
       | 
       | Obviously things like UTF-8 support, or maybe getting a clean
       | lexical scope option, or other "fixes" are good. Performance
       | improvements are good.
       | 
       | But there are lots of mainstream languages that have mature
       | static type systems, strong metaprogramming facilities, higher
       | performance, or all of the above.
       | 
       | I'd _way_ rather see effort go into getting the package
       | management thing figured out, or the static analysis stuff
       | improved further than any big movement in the language proper.
       | 
       | Just my 2c.
        
       | lordgroff wrote:
       | I maintain Python code bases for a living, and feel that the
       | language has simply been pushed too far. Static typing in Python
       | doesn't give you the advantage of actually static typing and even
       | IDE support is -- well it's not terrible, just not great.
       | 
       | The thing is, once we go through all this static typing exercise
       | in Python, we get no performance advantages, and the whole thing
       | seems bolted on, with worse semantics than most modern typed
       | languages. And yes, it can stifle undeniable advantages a dynamic
       | language like Python can provide.
       | 
       | Python remains a fantastic prototyping and scripting language,
       | but my feeling is that it now handles more than it should.
        
         | phlakaton wrote:
         | I think the mistake is to assume that Python's type hints form
         | a complete static typing system. Of course they fall short if
         | you think that's what they're supposed to be. I think of it
         | instead as a sometimes-useful subset of checks that you might
         | get from a static typing system, and I use it in those places
         | in my projects where I think it will be the most useful. The
         | very fact that I can _think_ of it as an option I can enable
         | puts it in a totally different space from traditional static
         | typing systems.
        
           | arcturus17 wrote:
           | Yea this is exactly how it feels to me. Like "reinforced
           | dynamic".
        
         | zerodensity wrote:
         | I also maintain a large python codebase at work, typing makes
         | things simpler. For example using pydantic 90% of serialization
         | code just goes away. Mypy eliminates a large number of bugs.
         | Also when working with multiple people in the same codebase
         | typing makes intent so much clearer. The type system itself is
         | not perfect but it's a clear improvement of not having it at
         | all.
        
           | arcturus17 wrote:
           | I could not agree more. I'm fairly language agnostic but
           | typed Python with pydantic is a joy to work with.
        
           | ReflectedImage wrote:
           | I disagree, it makes things more complicated by bringing in
           | concepts such as generics.
           | 
           | Using MyPy will on average double your bug count per software
           | feature. You might not think it does that. But if you
           | actually go and measure it, the bugs go through the roof.
           | There are studies on this. It's for subtle reasons revolving
           | around where bugs come from in code.
        
         | [deleted]
        
         | ImprobableTruth wrote:
         | Honestly, static typing encouraging data shape documentation
         | alone makes it worth it to me. Yes, they're pretty hacky in
         | Python and don't feel great, but I'm sure it'll continue to
         | improve.
         | 
         | I'm just so over having to guess what a function might accept
         | or return. Life is too short to spend it constantly reverse
         | engineering code because people can't be arsed to write proper
         | documentation.
        
         | cameroncairns wrote:
         | There have been some efforts to utilize the type hints to give
         | performance boosts. There's a project called mypyc that
         | apparently has been used by black (python formatting library)
         | that will compile type hinted python into c extensions.
         | Unfortunately I think development has stalled, but as more
         | people start using type hints I think there will be more
         | motivation for similar projects.
        
         | KRAKRISMOTT wrote:
         | I think the issue with Python is that it is relatively
         | underfunded compared to other languages of its size. The entire
         | Python ecosystem lacks leadership. Packaging is a clusterfuck,
         | Pypa today still doesn't contain package metadata (which
         | massively slows down downstream resolvers like poetry and
         | wastes terabytes of bandwidth every year). Non-security issues
         | take forever to resolve. Nothing encourages parties to
         | contribute, unlike Go or Rust. You end up with companies having
         | their own subtly-imcompatible internal forks. The benevolent
         | dictator never cared about performance until recently. Most of
         | Python's changes have been simple syntactic sugar. Python as a
         | compiler engineering project is an exercise in mediocrity
         | compared to V8 or LuaJIT.
        
         | abdullahkhalids wrote:
         | > the whole thing seems bolted on, with worse semantics than
         | most modern typed languages
         | 
         | One of the biggest sources of ugliness is the "None". The
         | standard way of declaring variables ahead of time is setting
         | them to None. But then, the type hints just become these ugly
         | unreadable Optional[ActualTypeofVar] everywhere.
        
           | mjr00 wrote:
           | That's because your type _is_ Optional[TypeOfVar] though; if
           | you try using that variable in a place that expects just
           | TypeOfVar before it 's set, you _should_ get an error.
        
             | abdullahkhalids wrote:
             | Let me restate. To prevent ugliness in typing, either
             | 
             | * Python should have a way of declaring variables without
             | setting them to None, so we can type hint them to their
             | actual types. Pre-declaration is very important for a
             | prototyping language, and needs to be done in a way that
             | the variable is visible to dir().
             | 
             | * Come up with a cleaner syntax than the wordy Optional[].
             | Thankfully, they have recently moved on from the ugly
             | Union[a,b] to the more readable a | b. Something more
             | readable could be done for Optional.
        
               | thatfunkymunki wrote:
               | but Optional[foo] is literally a union of foo | None
               | already!
        
               | travisjungroth wrote:
               | a: int              b: str | None = None
        
             | joshuamorton wrote:
             | Right, in langs with c-style scoping, this is an issue, but
             | in python                   if foo:             x = a
             | else:             x = b
             | 
             | Works, so there's no need to predeclare.
        
               | abdullahkhalids wrote:
               | A very common pattern in python is to declare all
               | instance variables of a class in the __init__ method by
               | setting them to None. This is done for
               | 
               | * code readability; all relevant variables are in one
               | place
               | 
               | * Python is a prototyping language, and a very common
               | usage pattern is doing dir(object) to determine the names
               | of all variables that could be set to something.
        
           | VygmraMGVl wrote:
           | You can declare a type-hint beforehand without setting the
           | value of the variable. See:
           | https://peps.python.org/pep-0526/#global-and-local-
           | variable-...
        
             | abdullahkhalids wrote:
             | Yes, but then those variables are not visible when we
             | dir(object), which makes it harder for the user to
             | prototype. Certainly, type hinting should not get in the
             | way of the users.
        
           | 9dev wrote:
           | Im used to just doing                 x: list[str]
           | if foo:         x = []
           | 
           | And if a variable is nullable, I use a union:
           | x: list[str] | None = None
           | 
           | That's much more readable to me!
        
           | pdonis wrote:
           | _> The standard way of declaring variables ahead of time is
           | setting them to None._
           | 
           | I'm not sure this method is actually "standard". For many use
           | cases there is an obvious "null" value of the desired type
           | (for example, just set an int variable to 0), so there's no
           | need to use None.
           | 
           | For use cases where you can't just initialize the variable to
           | the "null" value of its type (because that value has some
           | other meaning for your program), then the true type of the
           | variable _isn 't_ just the type you're thinking (e.g., not
           | just an int), _because_ you need to be able to distinguish
           | the variable having the  "null" value from it not being set
           | at all (the None case). And for that kind of use case,
           | Python's type hints are correctly forcing you to declare that
           | variable's type the way that reflects the actual situation.
        
         | SAI_Peregrinus wrote:
         | The problem with separate prototyping languages is that the
         | most permanent fix is always a temporary one. The prototype
         | usually becomes the final product. If your language isn't
         | suitable for use as a final product, then you're going to have
         | a problem. If it's not suitable for writing a prototype, then
         | you already have a problem.
        
           | dunefox wrote:
           | That's why I love the idea of a language like Common Lisp.
           | Performance, 'debugability', and flexibility in one package.
        
         | lostmsu wrote:
         | > Python remains a fantastic prototyping and scripting language
         | 
         | I think it sucks for prototyping too if your prototype is
         | constantly evolving. I have a WIP with about 100 files in it
         | that I've been aggressively evolving over the past year, and I
         | already want to rewrite everything in something statically
         | typed, because any kind of change became pain in the ass. Too
         | bad the project requires Python-first libraries.
        
         | yummypaint wrote:
         | I routinely use cython to compile python for heavy workloads. A
         | big part of the ~10x speedup i usually see comes from
         | strategically assigning true static types to certain variables
         | that get frequently iterated or compared. Most variables are
         | left as standard python as it isn't necessary to change them
         | for performance.
         | 
         | My experience has been that cython "just works" even with lots
         | of external libraries etc, and the code ends up performing as
         | well as any c++ code i could realistically write while being
         | much more understandable.
        
           | nextaccountic wrote:
           | > I routinely use cython to compile python for heavy
           | workloads.
           | 
           | an alternative is rust + pyo3 https://pyo3.rs
           | 
           | here's a web framework written with it, https://robyn.tech
           | 
           | the other poster child for pyo3 is polars,
           | https://www.pola.rs
           | 
           | it's simply, amazing.
        
             | samstave wrote:
             | which of these links should I start with with zero xp?
        
             | dereg wrote:
             | I'm so glad I found Polars. I replaced the most time-
             | consuming parts of my Pandas code with Polars and it has
             | reduced data manipulation times by literally 90-95%.
             | 
             | Amazing is not an overstatement.
        
         | wefarrell wrote:
         | That's also true of Typescript, which has been wildly
         | successful and taken over the javascript ecosystem. The main
         | advantage of types is that it makes your code more maintainable
         | by adding guardrails. You'll still possible run into issues at
         | runtime and they're not perfect, but they're better than not
         | having types at all.
        
           | scrollaway wrote:
           | Typescript really rarely feels bolted on to JavaScript. That
           | also has to do with typescript introducing new syntax to JS.
        
             | goodoldneon wrote:
             | There's very little new syntax added by TS
        
       | KurtMueller wrote:
       | Python the language doesn't give you super powers and I would say
       | that its clunkier and less elegant than Ruby and obviously not as
       | powerful as languages like F#. Python's ecosystem and
       | contributors are its biggest benefits and they help you succeed
       | in spite of the language itself.
        
         | [deleted]
        
         | jgeada wrote:
         | The ecosystem exists because Python does make it possible. That
         | was one of the main thrusts of the article!
        
           | pdimitar wrote:
           | > _The ecosystem exists because Python does make it
           | possible._
           | 
           | Only to a certain point, after which the network effects
           | override everything else.
        
       | wheelerof4te wrote:
       | Either embrace dynamic typing and provide good error guards...or
       | try to use type hints and still make good error guards.
       | 
       | We had an entire history of Python 2 without type hints. Why use
       | them now?
        
         | ok123456 wrote:
         | And most of that python2 code is completely rotted.
        
           | markrages wrote:
           | By definition, since it won't run on a supported runtime.
        
         | 9dev wrote:
         | How come everyone realised the benefits of typing by now,
         | except the Python community?
        
           | scrollaway wrote:
           | Because python got a half baked, overall poor quality type
           | hinting system so devs that haven't been exposed to the
           | benefits of eg. Typescript don't understand why this is
           | better.
           | 
           | Many of us in the python community know the benefits, and
           | we're simply changing our stack so python is as contained as
           | possible, and dropping lower quality libraries for higher
           | quality typed ones.
        
           | pdonis wrote:
           | The benefits of typing _for certain kinds of applications_.
           | 
           | Many people in the Python community simply aren't writing
           | those kinds of applications. They're writing applications
           | where typing is not a benefit, it's a hindrance, so they
           | don't use it, and Python makes that easy.
        
             | arcturus17 wrote:
             | I'm also part of the Python community and I use typing
             | extensively. I find them useful for app development but
             | also in scripting. There must be at least be a good dozen
             | of us seeing the popularity of mypy, pyright and the fact
             | that the language designers saw fit to add them, too.
        
             | zerodensity wrote:
             | Could you give an example of a type of application where
             | typing is a hindrance?
        
               | randomluck040 wrote:
               | Not a hindrance but I work with image data a lot. Usually
               | what comes in is any kind of Numpy array and what comes
               | out at the end is either statistics or a Numpy array. I
               | try to type hint everywhere I can but I feel stupid doing
               | so because all I do is work with arrays. Maybe I'm not
               | proficient/knowledgeable enough though so take it with a
               | grain of salt.
        
               | zerodensity wrote:
               | If it's truly "any" kind of Numpy array typing won't help
               | much there I agree.
               | 
               | But often it can be helpful to know the shape of the
               | input and the shape of the output. Eg are we working with
               | a 2D,3D or ND array.
               | 
               | Before 3.11 it was not simple (possible?) To type this.
               | But https://peps.python.org/pep-0646/ makes it possible.
               | If somewhat clunky on the definition side.
        
               | spookylukey wrote:
               | I did a fairly detailed breakdown regarding the Python
               | library Parsy: https://lukeplant.me.uk/blog/posts/python-
               | type-hints-parsy-c...
               | 
               | This is not to make the general claim "Typing is a
               | hindrance in parsing applications", or anything close.
               | It's saying "the current static type system(s) available
               | in Python would have made this Python library much
               | worse".
        
           | ReflectedImage wrote:
           | Developing with static typing reduces development speed by
           | 2.5x and increases bugs by 2.5x per the emperical studies on
           | the topic.
           | 
           | There isn't a benefit to static typing in Python, it's a
           | massive drawback.
        
             | Jtsummers wrote:
             | > Developing with static typing reduces development speed
             | by 2.5x and increases bugs by 2.5x per the emperical
             | studies on the topic.
             | 
             | I hate "Citation needed" comments, but this is a very
             | strong claim and so deserves it:
             | 
             | Citation needed
        
             | anhner wrote:
             | Any source for those made-up-sounding numbers?
        
           | llanowarelves wrote:
           | Not to be rude, but scientific/ai/data scientists are
           | typically not the best "programmers" (best practices and code
           | hygiene) , and their stuff is the main reason to be on Python
           | these days (other than for small CLI and scripts), which
           | pulls everything around into it like a black hole ("oh let's
           | make the api in Python too, to keep it one language").
           | 
           | And Python has a ton of newbies, college kids etc. Though
           | this is also true of JavaScript.
           | 
           | As an industrial language/environment with best practices for
           | very large codebases, it's really weak and I much prefer
           | TypeScript despite the occasional tooling fatigue (has slowed
           | down).
           | 
           | But a ton of money has been poured into JavaScript (v8) which
           | really set that into motion.
        
       | fasttriggerfish wrote:
       | I think type hints have mostly changed Python for the better but
       | I still get frustrated by the number of half baked features and
       | inconsistencies in the language. You end up fighting quirks (
       | like isinstance not working properly with generics ) all the time
       | and it can get pretty tedious.
        
         | packetlost wrote:
         | ... what? You're not supposed to use isinstance with
         | generics??? It's a type-hinting only feature afaik
        
       | Spivak wrote:
       | > But typing.Callable has zero support for them, meaning they
       | can't be typed in a higher-order context.
       | 
       | https://peps.python.org/pep-0612/                   from typing
       | import Awaitable, Callable, ParamSpec, TypeVar              P =
       | ParamSpec("P")         R = TypeVar("R")              def
       | add_logging(f: Callable[P, R]) -> Callable[P, Awaitable[R]]:
       | async def inner(*args: P.args, **kwargs: P.kwargs) -> R:
       | await log_to_database()                 return f(*args, **kwargs)
       | return inner              @add_logging         def
       | takes_int_str(x: int, y: str) -> int:             return x + 7
       | await takes_int_str(1, "A") # Accepted         await
       | takes_int_str("B", 2) # Correctly rejected by the type checker
       | 
       | I think the author and the people working on Python's type
       | annotations actually agree here. The goal is to have type
       | annotations powerful enough to statically describe all behavior
       | _generically_ without library specific extensions. There hasn 't
       | been much push for it but I expect a lot of the author's concerns
       | would be alleviated by a type annotation for types themselves.
       | Being able to say, "alright I'm gonna so some dynamic
       | metaprogramming magic bullshit, but at the end will pop out a
       | class of this shape" probably gets you 80% of the way where.
        
       | ImprobableTruth wrote:
       | Metaprogramming does not require dynamic types, but this post
       | seems to equate them. As far as I can see all this could be done
       | in e.g. Java (and probably is).
       | 
       | IME this kind of "magic" very quickly loses its appeal when you
       | have to debug it. The author's idea of libraries wrapping this
       | stuff up so users don't have to care about it just doesn't pan
       | out at all in my experience.
        
         | ajuc wrote:
         | LISPs are the quintessential metaprogramming languages, and
         | they learnt the lesson of "use macros sparingly and only as the
         | last resort" very early on.
        
           | taeric wrote:
           | I mean, you aren't wrong. But most of what they learned was
           | "step debugging is hard in the presence of macros." And step
           | debugging has largely been tossed out of the window in many
           | modern setups. Just look at Java's "stream" apis. I swear
           | they did what they could to replicate the LOOP macro.
        
             | vkou wrote:
             | I am very rarely concerned about debugging my usage of Java
             | streams, and step debugging works fine in the context
             | surrounding them.
        
               | taeric wrote:
               | That is also the case for macros in lisp, at large.
               | 
               | Similarly, any heavy use of lambdas in java will make
               | step debugging confusing. As will any annotations you may
               | use. Which is largely why many people grow to hate
               | annotations.
               | 
               | Which is all a fancy way of saying we learn the same
               | lessons again and again. Used smartly, all of these are
               | great tools. Defining what is "smartly" is a place of
               | dragons.
        
         | jchw wrote:
         | I also strongly dislike the idea that static type systems are
         | only being added to Python because spoilsports from other
         | languages are forced to use Python and don't want to. Not true.
         | That's especially strange considering Python is one of the only
         | traditionally dynamic languages that has mostly led it's own
         | static typing system, joined mainly by just PHP in that regard.
         | Why does it not support features like kwargs? Dunno. TypeScript
         | has no trouble supporting _tons_ of JavaScript patterns you
         | could _never_ do in other languages, even C# from which it is
         | heavily influenced due to its heritage, and TypeScript is a
         | fully separate effort from JS.
         | 
         | On the contrary, static typing in Python is still extremely
         | nice to have. When I was at the peak of my Python career, I had
         | a bug where I changed the return type of a function to be a
         | tuple, and somehow unit tests missed one of the worst possible
         | invocations, leading to an awful failure that occurred after a
         | payment was processed but before actually completing the task,
         | causing it to be retried repeatedly. To be clear, like any
         | failure of this nature, it is one caused by many different
         | problems, and we employed many different solutions; we started
         | paying attention to test coverage, we began using MyPy (it was
         | still quite new; this was also in Python 2 so it needed type
         | erasure compilation among other things) and we made our payment
         | processing logic more robust to prevent processing the same
         | payment twice even in the case of everything else (like retry
         | logic) failing to stop it again. But the thing that sucks is,
         | fairly simple type inference without any additional type
         | annotations could've detected that sort of bug without a
         | potential for false positives.
         | 
         | So I feel like it's silly the way that some dynamic language
         | proponents feel like static typing systems on top of dynamic
         | languages is all from outsiders. On the contrary, the relative
         | weakness of MyPy is actually what ultimately made me quit using
         | Python, and if I had to use it today, then yes, of course I
         | would opt for the highest degree of type safety, as a primary
         | concern above being "pythonic." I like pretty code, but I like
         | correct code more.
         | 
         | Sometimes this does prevent "better" solutions from working,
         | but in my opinion nearly 100% of the time that this is the
         | case, it's because:
         | 
         | - The type system in question is not sufficiently advanced to
         | express the types elegantly.
         | 
         | OR
         | 
         | - The approach is inherently not safe and probably not a good
         | idea. Like patching the request object inside of middleware in
         | Django, for example.
         | 
         | I think TypeScript proves that with a sufficiently advanced
         | type system, even arguably bad ideas can be type safe. For
         | example, the ability to express dotted object paths safely in
         | modern TypeScript is pretty impressive, and lets you map out
         | older JS that does this accurately, but in general that seems
         | like an unnecessary trick that will just make your code slower
         | at runtime for the slightest terseness improvement over
         | alternatives, lacking a language with sufficiently advanced
         | metaprogramming.
         | 
         | The thing is though, eventually this thought process comes
         | true. If a given programming language community winds up
         | bleeding members who are moving on due to the lack of better
         | static type checking systems, then the people left will
         | invariably be much more likely to be against static type
         | systems.
        
           | ReflectedImage wrote:
           | You quit Python because you tried to use static typing in a
           | dynamic language and for obvious reasons that doesn't work.
           | 
           | You could have introduced an UAT environment and done basic
           | QA.
        
             | jchw wrote:
             | We had dedicated QA testing. QA testing failed to create
             | the requisite conditions.
             | 
             | Type checking is not a replacement for QA testing. However,
             | it is much cheaper and also finds bugs that might be
             | _incredibly_ hard to find through random chance or through
             | structured smoke testing, because it does not depend on how
             | common a given code path is. QA testing is even less likely
             | to find issues than automated test suites, since at least
             | you can qualify branch coverage with test suites (which
             | _still_ will not enumerate all of the possible _code paths_
             | , and thus... Type checking is incredibly useful.)
             | 
             | So while type checking really is _not_ a replacement for
             | QA, QA is also not a replacement for type checking.
             | 
             | I ultimately quit Python for many reasons, but the desire
             | to write more correct code was the big one. Not just me,
             | but my entire team was burned out on Python. Investing so
             | much into unit testing and increasing coverage, upgrading
             | Python versions, and adding type checking as much as
             | possible was still not yielding the benefits we'd hoped for
             | despite how much effort it took. We eventually found much
             | better success with the then-still-new Go programming
             | language, which we used on most new projects going forward.
             | There was still the occasional head scratcher in
             | production, but deployments were as quiet as a church
             | mouse. YMMV of course; there's plenty of success and
             | failure stories with any programming language. I think we
             | were all ready and willing to put a lot of investment into
             | improving our robustness situation and just felt that we
             | got more out of that effort with Go than Python for our
             | programs. Python still has plenty of advantages too, so we
             | didn't completely quit it; we wound up using Django and
             | SQLalchemy here and there, but definitely most stuff moved
             | to Go over time. (And personally, I stopped using Python
             | for those things too, since moving on.)
        
               | ReflectedImage wrote:
               | Are you aware that code written in the statically typed
               | code style has on average 2.5x the number of bugs as the
               | equivalent code in the dynamically typed code style per
               | software feature?
               | 
               | I'm sorry to burst your bubble, but static typing is
               | REALLY REALLY bad from a code correctness standpoint.
               | 
               | "write more correct code was the big one" Well you have
               | completely failed on that account.
               | 
               | Static typing has nothing to do with code correctness,
               | it's purely about code performance.
        
         | posix86 wrote:
         | Yeah thought so too... in particular the example where you pass
         | a a generator to a db, the generator isn't actually executed,
         | and instead the expression is parsed & transformed to SQL.
         | 
         | This is cool if it works. Good luck when it doesn't due to user
         | error, and more luck if it doesn't due to a bug.
         | 
         | You need to develop a whole strategy to tell the user what went
         | wrong and how, and why, basically from scratch; admitting that
         | you didn't, in fact, execute the generator, and that they have
         | to change it. because of that.
         | 
         | It's pretty awesome that it's possible. And it would be pretty
         | amazing to write something like that. But... idk if it's a good
         | idea from a developer stand point. I like being able to
         | understand what's happening in a library with a single click.
        
         | RobotToaster wrote:
         | Isn't the C preprocessor a type of metaprogramming?
        
           | Jtsummers wrote:
           | Yes since metaprogramming is just programming that generates,
           | modifies, or extends other programs.
        
           | agumonkey wrote:
           | it's probably discard as being string-based, you could do the
           | same with sed
        
           | [deleted]
        
       | teaearlgraycold wrote:
       | TypeScript is the language Python wants to be. If only JS came
       | with a Go-level stdlib there'd be nothing to complain about.
        
         | [deleted]
        
         | revskill wrote:
         | Seems valid, most modern Python code is almost the same as
         | Typescript without {}
        
       | TeeWEE wrote:
       | All these features are nice and stuff... But they are often
       | runtime features... At compile time Python doesnt tell you wether
       | a program is correct. Which is fine for small programs or small
       | services. But any big system is written in python is really hard
       | to maintain without LOTS of unit tests...
       | 
       | Static typing, compile time checks just win in the long run. And
       | with languages like kotlin you still have all the advantages, and
       | you have nice tools like python has which execute at COMPILE time
       | using DSL, which are type safe themselve..
       | 
       | Python has become mostly a toy language for me to write scripts
       | in.
        
         | ReflectedImage wrote:
         | No programming language tells you if a program is correct at
         | compile time. Type errors aren't a very common type of bug
         | either.
        
         | chatmasta wrote:
         | What does "compile time" even mean for Python?
        
           | RedTachyon wrote:
           | The moment you run the script, before it actually gets
           | executed.
        
         | CoastalCoder wrote:
         | > At compile time Python doesnt tell you wether a program is
         | correct.
         | 
         | This is a general limitation of type systems, IIUC. If you want
         | a type system to guarantee 100% program correctness, I think it
         | can't handle an arbitrary Turing-complete program.
        
       | bayesian_horse wrote:
       | When I did most of my work in Python, typehints weren't a thing.
       | I still feel like static typechecking is less useful in Python
       | since its datamodel is overally less of a hot mess compared to
       | Javascript for example.
       | 
       | And Python modules/frameworks can be a lot more "typed" than
       | you'd expect. Django models, forms etc offer more runtime
       | validation than typesystems can easily achieve. Yes, at runtime.
       | But between not having a build process and in general being more
       | readable and concise, I feel like Python lets you run into the
       | runtime error long before you get the same thing done "error
       | free" in C#. Not that C# doesn't have runtime errors...
        
         | phailhaus wrote:
         | > its datamodel is overally less of a hot mess compared to
         | Javascript for example.
         | 
         | I don't understand this, what do you mean? TypeScript is such a
         | success partly because everything is an object in Javascript.
         | There's no need to distinguish between classes and "dicts", as
         | you have to with Python. Another example: Python functions have
         | args and kwargs, which make typing significantly more complex
         | (as the article points out, Callable doesn't even support
         | kwargs). Javascript doesn't, so typing functions is trivial.
         | 
         | Part of the point of static typechecking is documentation that
         | can be verified by tooling. If you have no types in your
         | codebase, and you decide to change something from a dict to a
         | class, good luck! You're going to have to manually trace all
         | the data flows through your entire application to figure out
         | what's affected.
        
           | pdonis wrote:
           | _> everything is an object in Javascript_
           | 
           | Everything is an object in Python too.
           | 
           |  _> There 's no need to distinguish between classes and
           | "dicts", as you have to with Python._
           | 
           | "dict" in Python (or at least Python 3, but Python 2 is EOL
           | now so Python 3 is the only active Python there is) _is_ a
           | class. You can even subclass it, which if you want a
           | customized dict for some reason in your particular
           | application is often the best way to do it. Or you can
           | subclass MutableMapping, which dict itself is a subclass of,
           | and which is what is supposed to be used for isinstance
           | checks now that Python has established abstract base classes
           | for all of its standard  "built-in type" interfaces.
        
           | KyeRussell wrote:
           | OP is not saying that type checking is useful. They're saying
           | that it's not as useful.
        
       | paganel wrote:
       | > I'm worried that a de-facto move away from dynamic stuff in the
       | Python ecosystem, possibly motivated by those who use Python only
       | because they have to, and just want to make it more like the C#
       | or Java they are comfortable with, could leave us with the very
       | worst of all worlds.
       | 
       | It is certainly happening, and I'm not sure Python the language
       | is all the better for it. I say that as a guy who explicitly
       | mentioned this "Python Is Not Java" blog-post during my first job
       | interview as a professional programmer, more than 15 years ago.
       | 
       | [1] https://dirtsimple.org/2004/12/python-is-not-java.html
        
         | bayesian_horse wrote:
         | Over the years C# (and probably Java, but I'm not so well
         | versed in that) gained quite a few features to improve "Meta-
         | Programming", one could argue in an attempt to compete with
         | dynamic languages. In C# that is mainly possible through
         | introspection, generics and maybe dependency injection. Entity
         | Framework Core can mostly figure out an SQL Table and its
         | queries by looking at a simple class. It's not as good as the
         | Django ORM or SQLAlchemy, but it tries to achieve similar
         | things...
         | 
         | So maybe some stuff in the Dotnet ecosystem got started because
         | Python programmers were forced to use C# and tried to make that
         | more dynamic.
        
           | acedTrex wrote:
           | How is SQLAlchemy or django better at any of that? in my
           | experience EF is far far superior
        
           | pjmlp wrote:
           | Check the history of IronPython and IronRuby and how that
           | spun the Dynamic Language Runtime, likewise do the same for
           | jython, jTcl, jRuby and invokedynamic bytecode.
        
         | simplicio wrote:
         | My theory is that Python and C++ are slowly evolving towards
         | eachother, and in 20 years will merge into the same (very
         | confusing) language.
        
           | rich_sasha wrote:
           | C++ consuming whatever popular paradigm is around and growing
           | into a jumbled mess? Surely you're joking...
        
         | ok123456 wrote:
         | eval() makes it harder to reason able your code and opens you
         | up to injection attacks. Steering the boat toward C# or Java is
         | better than crashing into TCL.
        
       | thereisnospork wrote:
       | While this might be about my most unpopular opinion, it feels
       | like it is time to start putting together a Python 4.0. I don't
       | particularly have skin in the game but there is(?) enough meat on
       | the bone around things like improving the GIL status quo, JIT
       | compiling, static typing, and presumably etc. to be worth a
       | breaking change.
        
         | JonChesterfield wrote:
         | That's definitely an unpopular opinion. The 2 to 3 change
         | caused a lot of pain. I can't see the python community
         | attempting that again.
        
       ___________________________________________________________________
       (page generated 2023-02-01 23:01 UTC)