Live data from Hacker News

Problems I Have with Python

darkf.github.io

171–180 of 239 posts

Re: Problems I Have with Python

#171

For flatten, use: flattened = sum(list_of_lists, ())

This only flattens one level. Consider the following snippets: ; CHICKEN Scheme #;1> (flatten '((1 2 3) ((4 5) 6) (7 (8) (((((9)))))))) (1 2 3 4 5 6 7 8 9) #;2> (apply append '((1 2 3) ((4 5) 6) (7 (8) (((((9)))))))) (1 2 3 (4 5) 6 7 (8) (((((9)))))) vs. # Python 3 >>> sum([[1,2,3], [[4,5],6], [7, [8], [[[[[9]]]]]]], []) [1, 2, 3, [4, 5], 6, 7, [8], [[[[[9]]]]]] There's a big difference here. Flattening a list to jus…

See https://bugs.python.org/issue27852 for a discussion as to why there isn't a more general flatten().

Re: Problems I Have with Python

#172
post #115

Earlier quoted context omitted.

Your post quite strongly alludes to it being either due to incompetence, or politics, or both. So I think grandparent has a very valid point, and you might want to change the tone of your post a bit; then it'll produce fewer knee-jerk reactions, and might be taken more seriously.

Nah, just people connecting that sentiment with other statements. It should be cleared up since it's causing some mass confusion. It's funny because I preface it by saying "Remember that it's a matter of opinion" (and, well, the title alone) and people come out of the woodwork completely disregarding this, or outright misinterpreting sections of it. I maintain that a large reader base here does not actually... read.

Stating that something is a matter of opinion does not mean that insults do not hurt. Either you don't want people to listen to you so you don't have to worry about what you say or you do want people to listen in which case how you phrase things matters.

Or put another way: I'm a core developer of Python and I found your post somewhat insulting (I've unfortunately seen worse). You claim I'm possibly incompetent and I did a half-assed job with asyncio. You very "audibly" sigh and call my work "nonsense". You ask me to "come on" and accept your view on things when I have apparently helped make a "gimped language". And you end by saying I need to "fix [my] language". None of that phrasing comes off as understanding of the hard work and immeasurable number of hours I have put into making sure Python continues to function well for you over the past 14 years that I have been a core developer. I know you like Python as you stated in the post and in the comments here, but that doesn't wash away the rest of the unnecessary negativity in your post such that I want to take your opinions seriously enough to spend the time to explain why things are the way they are.

Re: Problems I Have with Python

#174

Though I likely haven't completely understood each of the authors gripes, each problem to me seems to have a notable solution provided by Clojure (with the exception of tail-call optimization). Clojure: is compiled to JVM byte-code and is fast. has a good parallelism story (parallel map, parallel fold, channels) is almost completely backwards compatible. has a sequence abstraction that leverages the same operations o…

All of the above is good except for transducers. They are a necessary hack in Clojure because the data is immutable running a large number of functions across changing data is rife with overhead in Clojure. So the hack is mutate the code many times, so you only have mutate the data once.

I see what you mean and although the definition of a from-scratch transducer looks a bit ugly to me, the idea of composing existing transducers together seems rather elegant.

Re: Problems I Have with Python

#175
post #117
post #76

Earlier quoted context omitted.

Python has made some trade-offs that you dislike. You complain about the negative consequences without comparing those against the benefits. One of the major factors in speed is efficient memory layout. Contrast a Python list with a NumPy array. To achieve speedier loops and vectorized arithmetic [0], the array gives up dynamic typing and dynamic sizing. In most applications, I would gladly give up some compute speed…

>Contrast a Python list with a NumPy array. To achieve speedier loops and vectorized arithmetic [0], the array gives up dynamic typing and dynamic sizing. In most applications, I would gladly give up some compute speed to gain some programming productivity. Except numpy arrays have a much richer interface and can still store dynamic objects (dtype=object). So what's your point? >I love duck-typing So do I. Where does…

If you're storing generic objects rather than numbers in a NumPy array, you're discarding its main benefits. Sure, you've got some extra slicing sugar for selecting columns and subsets, but comprehensions are more readable (and faster!) in many of those situations.

Duck-typing is Python's form of dynamic typing and therefore results in the speed penalty. If you want the extra speed, you'll need to give up some dynamicism. I say this now, but some of the work the core devs are doing to optimize dicts might let us have our cake and eat it too. Until then, it's a choice: flexible or fast, not both.

Re: Problems I Have with Python

#176

Earlier quoted context omitted.

The thing is, tail calls aren't _just_ about emulating iteration via recursion: def foo(): raise ValueError def bar(): return foo() bar() With TCO, the stack trace would contain `main` and `foo`, as `bar`'s frame would be overwritten by `foo`. This example is simple, but `bar` could be a 50 line long if-else chain of tail calls and when debugging you won't necessarily know which condition was evaluated.

> The thing is, tail calls aren't _just_ about emulating iteration via recursion: I completely agree, but there is also no need to perform TCO to make code like this safely runnable. TCO only becomes necessary/useful when implementing an iterative process where we can't statically know that the call stack won't be exhausted. That said, TCO is usually an all or nothing transformation, and it would be difficult to accu…

A decorator that enabled TCO makes sense to me. Kind-of like the Numba project, it'd be a specialized JIT-compiler invoked only on some functions.

What's stopping that from being a 3rd-party library like Numba?

Re: Problems I Have with Python

#177

Earlier quoted context omitted.

Naively compiled C/C++ is fairly easy to reverse engineer (I say this from a lot of experience!). If you want to "protect your source code" you need to apply obfuscation techniques to slow down a reverse engineer - but keep in mind that everything ultimately can be reversed and understood given enough time. Plus, many obfuscation techniques can be made applicable to Python code too (e.g. encrypting, obfuscating or ma…

> Naively compiled C/C++ is fairly easy to reverse engineer (I say this from a lot of experience!). So I assume your position on reverse engineering Python bytecode is that it's trivial.

It can be, since Python is a higher-level language, but it isn't necessarily easier. For one, the state of decompilation technology is much more primitive for Python - the decompilers I've used are more like pattern matchers and break if you even slightly tweak the bytecode or use fancy constructs.

Second, although Python by default outputs plenty of symbolic data to assist a reverse engineer, these can be stripped (just like a C/C++ binary can be stripped), leaving you with a bunch of duck-typed method calls and operations.

Re: Problems I Have with Python

#178
post #115

Earlier quoted context omitted.

Nah, just people connecting that sentiment with other statements. It should be cleared up since it's causing some mass confusion. It's funny because I preface it by saying "Remember that it's a matter of opinion" (and, well, the title alone) and people come out of the woodwork completely disregarding this, or outright misinterpreting sections of it. I maintain that a large reader base here does not actually... read.

Stating that something is a matter of opinion does not mean that insults do not hurt. Either you don't want people to listen to you so you don't have to worry about what you say or you do want people to listen in which case how you phrase things matters. Or put another way: I'm a core developer of Python and I found your post somewhat insulting (I've unfortunately seen worse). You claim I'm possibly incompetent and I…

Hey, Brett. Thanks for your work :-)

Re: Problems I Have with Python

#179

One of the biggest Python issues I see is the inability to hide or protect Python source code. 'Compiling' into byte code is easily reversible using pip packages like uncompyle2. Various pip packages offer code obfuscation but from my tests cause problems when running the code. Encrypted bytecode seems to always be decryptable due to the very nature of having an interpreter. Moving Python code into modules implemente…

There's decompilers and deassemblers.

Code is not hidden or protected by being transformed into a binary executable format. Companies that believe/rely on that are disillusioned, not paranoid.

Re: Problems I Have with Python

#180
post #176

Earlier quoted context omitted.

> The thing is, tail calls aren't _just_ about emulating iteration via recursion: I completely agree, but there is also no need to perform TCO to make code like this safely runnable. TCO only becomes necessary/useful when implementing an iterative process where we can't statically know that the call stack won't be exhausted. That said, TCO is usually an all or nothing transformation, and it would be difficult to accu…

A decorator that enabled TCO makes sense to me. Kind-of like the Numba project, it'd be a specialized JIT-compiler invoked only on some functions. What's stopping that from being a 3rd-party library like Numba?

You can find simple decorators which try to provide space efficient tail recursion. Usually they work by trampolining the function. I've seen one example where a decorator rewrites the bytecodes to perform a goto in the case of self recursion. The problem is that all of these solutions are rather limited, easy to break, or have a pretty high runtime overhead. The general solution would be for a decorator to rewrite all CALL opcodes in tail postion to TAIL_CALL opcodes, but such an opcode currently does not exist. The actual implementation of a TAIL_CALL opcode would be almost idential to the CALL opcode, so adding it would probably be straightforward, but I'm speculating here.
Post reply on HN