Why Is Python Growing So Quickly?
stackoverflow.blog
stackoverflow.blog
Really easy to answer: It is stupid fun to program with Python. There are libraries for everything you can imagine and they are generally very easy to use. Once you grok the virtual environment thing, writing apps/programs/scripts is just a matter of creating a new env and installing the libs you need. Testing ideas with Jupyter notebook is fun, fast and rewarding. Pycharm is awesome. VSCode with Python just works. You can automate tons of boring stuff (Thanks Al!)... and the list goes on... and on...
My take on the matter is that Python is gaining traction due to its market share of the Data Science/Machine Learning field, which is what's really gaining traction and growing quickly. Had Perl or Ruby been the premier language to use for DS/ML, they would be growing instead of Python.
Also many things about python that I don't like such as `len` being a function rather than a method on a list are very trivial when coming from a language like C which has hordes of tiny inconsistencies.
The whitespace thing in python is pretty gimmicky but does also hold a certain amount of pedantic appeal.
Take a look at the design rationale for the new __matmul__ magic method. It's not for the standard library, it's for the community.
But you can also see that Guido has been into types lately. He's been pushing the development of mypy and the new optional type system.
Rails is amazing and I personally love it. But it's not the only thing Ruby is good for.
I dislike the many inconsistencies in Python. You mentioned one. Others: sort vs sorted (destructive vs non destructive). Also: not being able to chain methods because many don't return a value. (Scheme, Elixir or even Ruby are imho much more elegant.)
But all in all Python is a very useful programming language with a rich eco system.
https://docs.python.org/2/faq/design.html#why-doesn-t-list-s...
Nevertheless I find this here much more elegant:
data.sort.tail.first # or this data.append(7).append(3)
More elegant than this:
sorted(data)[1:][0]
data.append(7) # and then
data.append(3)
I love method chaining in Elixir or Javascript. In Python I have to create temp variables here and there to capture / further process intermediate results.
Having said that: Python has it's strengths. I use it more than any other programming language.
if (x=42) {}
Has burned many people. Append having a useful return is comparable, though probably not as much of a trap.> sorted(data)[1:][0]
I don't want to get into the weeds, but shouldn't that just be
sorted(data)[1]
Or if you like unpacking for clarity first, second = sorted(data)[:2]
?Well Perl was the premiere data science language for a while. Python made inroads and eventually took over. I think you're mostly right through, it's just a matter of other factors affecting the communities at the time causing Perl to not grow nearly as quick as Python, and Python getting a good numeric library. Had Perl not lost a lot of community in the early 2000's, it might have retained this area.
Well, Python is the scripting language of a ton of useful libraries which are relevant to a lot of very interesting fields.
R sits in a similar spot, but Python is a better, friendlier language, which means actual programmers are more apt to recommend it as an offhand solution to a simple problem someone who isn't seen as a programmer is having: "Oh, that's easy. Just copy and paste this Python code, and maybe hack at it until it does something." You can get scientists programming with recommendations like that.
https://www.scipy.org/scipylib/building/linux.html
Of course, the people who just install and run SciPy don't need to know that, but the fact Python has a nice C FFI means it can run literally decades' worth of software across a fair number of languages.
There are so many lovely and easy to use libraries in Python. I took a couple and tried to be inspired by them to write a C++ library, maybe for addition to boost.
However, if you are writing C++, people expect your library to be fast and memory efficient -- you can't go around sticking the entirety of a parsed file in a std::string. Also, people then start saying your code better interoperate with their templated classes well, and they want to replace the memory management entirely, and it goes on...
Of course, the resulting libraries are very fast and very clever, but they have lost the joy. They also take much longer to write, maintain and use.
Painting with broader brushstrokes with less concern for micro-efficiencies lets you block out a solution faster. Another part of the problem with C++ is that the components come with so many rough edges that need to be filed down that you can't help getting swamped in a certain level of detail, unless you start with a large toolbox or framework that lets you work back at a higher level again.
You ought to have the equivalent of Java's file stream, buffer and text decoder as three separate bits that you can compose, so that putting a whole file in a string is never even a temptation. But if you start out with a sparse toolbox, it's a slog.
Performance grants you some freedom.
Python encourages readable code, which enables smarter algorithms, which ultimately swamps all those little memory optimizations. Oh, and PyPy/Numba/Cython let you get those little optimizations, too.
I think the readable code thing is really really important, too. I can understand other peoples code quicker and learn more about the actual algorithm unlike in C++ where I wonder half of the time about syntactical non-sense and optimizations for certain compiler targets.
Then again, Python and C++ target very different groups and I like both languages for certain things.
I'd really like to know what they were doing and how they could do it so wrong that the C++ version took hours while the Python version was faster than a blink of the eye.
Similarly, naybe the C++ code was using an inefficient data structure for a large dataset compared to using something like Numpy.
The rewrite realized an approximation was reasonable in place of a more "correct" algorithm.
Note that I'm not saying Python was the cause, but the ease of reading and writing code may have helped the programmer come to this algorithm. Instead of stressing about bugs and deadlines. Algorithm choice seems correlated with language choice, in my experience.
Code rewrites are often more than a literal translation. They often eliminate old code, and allow to rethink the architecture. So it's really not a surprise that Python code would be faster here. A rewrite to C++ would probably be much faster still.
C++ libraries should allow people to squeeze every bit of performance juice out of them (e.g. custom allocator).
Python libraries should be intuitive to use.
---
Naturally, there are exceptions, like numpy.
You might use it to make a rope bridge across that performance gap, but how good your bridge is depends a lot on you - and if you just manage to hang yourself with it, well, that's on you as well.
With Python it may take longer to get across because you detour a mile over to a more solidly constructed bridge, but you still get there and for most cases you get there fast enough.
Sure you can. C++ is at best programmed like python. Just throw the working first version together - and once you hit a performance gap, you can optimize it.
Using a profiler.
Premature optimization is mostly pointless because for most non-trivial performance critical apps the bottleneck wont be where you expect it.
The faster you find the actual problematic hotspots with production content the better. The way to get there fast is to treat C++ like filthy python.
Don't trust anyone trying to goad you into premature optimization unlesa they understand the specific problem you are trying to solve, and only then with skepticism.
Why would anyone want to write code that would go into either of those? In the general sense, I mean.
Good production code is simple and is implemented preferably verbosely and understandably than cleverly.
Speaking of good software patterns, I'm not sure boost nor STL are great examples of good software architecture. Boost especially is very templatey-bloatey. The biggest merit of STL is that is exists.
"installing libraries can be fiddly."
Does anyone really need to do that? Install C++ specific libraries I mean. In 10+ years I've never developed C++ software that would not store all of it's dependencies part of the project hierarchy or sub-structure, except for the standard library.
The worst part of C++ is that is has these warts that subtly guide developers into copying all sorts of patterns for their own sake because they are seen "as the standard way to do it". Object orientation and templates should not be considered the basic building blocks of the archictecture of a C++ program, but rather escape valves when some usage pattern would end up more complex without them.
For example, when someone spends long production time creating an elegant template based solution for whatever, generally it is an indication that something is wrong somewhere. There are of course exceptions to this rule, but just saving some boilerplate is never a good reason to do it.
The STL is a library of common algorithms and data structures that are decoupled from one another, and the complexity of operations in the STL has been enshrined in to the C++ standard. These two achievements alone warrant granting it huge respect. Imho, it's the essence of great design and it should be the very first thing taught to programmers new to C++.
> copying all sorts of patterns for their own sake because they are seen "as the standard way to do it".
Yeah, Python programmers would never do anything like that. If they did they might all run around calling it being 'Pythonic' or something.
> Object orientation and templates should not be considered the basic building blocks of the archictecture of a C++ program
Just tools in the toolbox, and the amount of mileage you can get out of just these two features, along with other staples like RAII and function overloading is pretty astounding.
C++ pushes you to conflate optimization with the higher level meaning of what you're trying to implement. In Python you can write the higher level meaning in a more 'pure' way, which is fun of course. The really interesting question is if you can program at the higher level while still running fast, perhaps by specifying optimizations separately?
(BTW, for Python code that can be as fast at C++ see https://kratzert.github.io/2017/09/12/introduction-to-the-nu... - it doesn't sacrifice clarity, but is limited to a subset, for now).
Around 2009 I started questioning if I even enjoyed coding anymore. I was primarily using PHP and Java. Rather than quit the profession I tried Python and suddenly it was fun again. 8 years later, it still is. Python just spoke my language.
My career is based around using Python because it's the way I enjoy the work. Everything else, like the actual properties of Python relative to other languages, is irrelevant to me if using another language would make the work unenjoyable again. (Though if Python didn't measure up very well compared to other languages it wouldn't have become my go-to in the first place.)
Nowadays the panorama for good languages, thankfully, is much better. PHP is no longer that much of a dumpster fire with modern frameworks, and Java has decided to adopt better defaults and drop the XML madness. Not to mention all the good languages that have come up (Elixir, Clojure, Rust, etc).
That said, it seems foolish to ignore the clear data science use case. But that's also been a theme for at least five years now.
In some sense - there are no large projects. Only projects that have failed at being modular.
Maintainability involves keeping clear boundaries between functional units so that you can keep enough code in your head at any one time to reason about it.
If we assume that Python is capable of handling more code than you can keep in your head at any given time, then surely the problem is simply one of making sure your modules are nicely self-contained from each other.
Write function in module A that expects some complex data structure that comes in. In a static typed language, you put a type on the argument and thus guarantee, to some degree, the data in the object can be safely manipulated.
Over in module B we call that function. Because Python doesn't enforce types, I can pass in some type of data structure that might behave well in many situations, but in some that function is going to fail because I didn't properly construct the data structure.
How do other Python projects avoid this? Do they avoid large data structures of multiple fields?
Let's question some of the assumptions. Do you NEED the entire thing to be passed around? If your functions are small and only do one thing, can't they be fed the portion of the data they need and only manipulate that? If they are getting unnecessary data, soon someone will like the convenience and that piece of data will now become necessary.
I have seen Java projects with humongous "DAO" objects being passed across all apps. Even if Java had Haskell's type system, at some point it breaks down.
So, you do not enforce that on Python itself. Rather, you have to apply due diligence and ensure your data structures are clean, and functions do what they are supposed to do and no more.
> I can pass in some type of data structure that might behave well in many situations, but in some that function is going to fail because I didn't properly construct the data structure.
Then you construct the structure in a single place, and that should have some sanity checks and sane defaults.
Even if you are using a static typed language, there's no guarantee that what's inside the data structure even makes sense, only that the right type of structure is being passed on. That's helpful, but not as much as people would think.
And you write tests. Lots of tests. It is amazing the amount of Python code that gets written without proper testing. And Java, for that matter. Only Python programmers have less excuses, it's easier to replace what you need for testing.
You should always put validation in constructor so you are 100% sure that the object created is valid.
I guess I'm arguing both sides now. My point is that one needs to root out the weird cases somehow and that it's often hard to have "100%" validation of inputs. One's initial understanding of what is the valid and invalid state space is often incorrect.
Also, even without actual type checking (mypy), IDE support + type hinting (PEP 484 or reST et al) means you can find most issues before the interpreter/compiler is involved. PyCharm is fantastic at this.
https://github.com/jonathanslenders/pymux/blob/master/pymux/...
Here's one way. Those asserts will typically pick up on errors during spikes, development and tests and turn a head scratching problem into a straightforward issue.
A couple of times on a disastrously tech debt ridden project I used it to pick up obscure configuration errors in prod, too (shouldn't see it in prod on a relatively well written project tho).
Never been much of a fan of duck typing. It only really makes sense when you have objects that approximate built in types.
Take a random object with a .run() method, for example, and you don't have a fucking clue what it might be doing so there's no point interpreting that as a quack.
Divide code into modules.
If you are worried about types, use object oriented programming to define the classes you want and then use the assert() instruction to check variables to comply with said classes/types.
A good IDE like PyCharm will take advantage of such assert() statements.
* Realistic integration tests that cover as many user stories as possible.
* Raise exceptions ASAP for any kind of invalid data or state (could be checking types, but could also be checking for file/directory existence). Could also be pip installing and using 'schema'.
* Do not build on poor quality modules and strive to decouple and uninvent poorly reinvented wheels.
* Just in general: loosely couple everything.
I don't see this as a static typing issue at all. Static typing only helps with a small part of the problem and it usually does that at some expense (usually more verbose & less flexible code).
I'm a little skeptical that super-strong type systems like haskell necessarily help all that much either. They clearly help eliminate classes of bugs, but the overhead is very high (the amount of everyday software written in haskell is seemingly small relative to its apparent popularity).
This is certainly a potential explanation. But I don't think it is self-evident that the trend of recent growth is entirely due to this.
Edit: The article supports the claim - I should have read it before commenting.
it's incredible how hard it is to get some people on board with this. I've gotten used to good project-local package management in other langauges, I can't imaging working with anything that depended on stuff happening to be available in a global namespace ever again.
E.g. is there something like 'cargo run' that just checks that the required python version is installed (I got the impression that this can be specified somewhere), installs deps if they're not installed yet and then runs the main module? Or something like 'npm install --save' that adds the latest version of a package you already know the name of as a dependency and installs it?
https://github.com/kennethreitz/pipenv
While virtualenv management isn't that difficult, Pipenv is VERY intuitive.
All in all, I found it neither much more or less fun to program with than e.g. Java, C# or TS. It might be a better fit for small projects than others, though.
Which parts did you find confusing? Was it the lack of a block-level scope, such as within for loops and if statements? I personally find the LEGB (Local, Enclosing, Global, Builtin) system to be pretty intuitive.
Python is not perfect but the final code is simple to write and understand years later.
I wish this would die, it just scares off newbies. In my twenty years of Python I encountered conflicting reqs once or twice. It's easy to direct folks to the documentation in those circumstances rather than cramming it down every newbie's throat---YAGNI.
Now that pip can install with --user and containers are popular, the problem isn't even possible in production in many circumstances.
This discussion is a lot like version control. How many people made daily (hourly) duplicates of project folders before learning the benefits of version control?
You normally won't get a version control lecture during every programming language tutorial either.
However, some things can't be as easy as in Python, such as sympy, which does symbolic processing of in-python expressions (differentiation, integration etc).
I actually don't find python easy to use - every time I use it, I have to look up how to do for loops (what? range? zero-based? does it include the last one?), and the docs don't have links for arguments (even though they require specific types), because no static types.
But the libraries absolutely are easy to use. And because many are written in C (unlike most of Java's librries), you're arguably running C.
Then there is the GIL. I still don't know if multithreaded python apps are really MT or just faking it. And yes, I know you can do event driven stuff and that does look very interesting.
You can activate two different environments in two different terminals. Why wouldn't you be able to?
You can automatically activate venvs when you cd into a directory with virtualenvwrapper.
Rule of thumb: if a thread goes into C it's releasing the GIL. Not always, but often. Like reading a file, or a library like like numpy or Pillow.
One particularly big thing, that it doesn't have much of a distinct compilation phase. You'll write some script you want to run to do some one-off task that will take the next hour, only to find it crashed after 20 minutes when it hits some boneheaded syntax error you made.
only to find it crashed after 20 minutes when it hits
some boneheaded syntax error you made
I find mypy to be pretty useful for this.They usually don't know better
They'd make a mess with every language...
A beautiful mess, don't get me wrong
There are better languages but there isn't enough "science cargo cult" around them
And honestly there aren't as many code snippets to copy from
My hopes are in luna[1]
p.s. distributing load or using multi cores is still shitty in python, the more dataset will grow in size, the more python will struggle
Once upon a time it was all about cloud, SaaS and building a webapp. Hence the growth of JS.
We also know that ML and AI are new macro trends in the tech industry. Python's elegant syntax isn't really evidence for why Python is trending now as opposed to any other time in the last decade.
These are all libraries heavily used in any technical computing field. The cost of MATLAB, the simplicity of Jupyter, and the community around Python have caused Python to slowly be a language used for general technical computing, not just data science.
All scientists need numerical simulations or evaluations, plotting, and statistics. That's what these libraries do. Not "Data Science", but "Science".
The correlation with TensorFlow/Keras suggests Data Science, maybe. But I bet there is a similar correlation with scikit-learn, Scipy, scikit-image, basemap, and heck, Matlab, Julia and R--and those each suggest different scientific endevours.
TL;DR: In my opinion, Python is becoming the language of Science, which includes, but is not limited to, Data Science.
"Data science" to me seems like a buzzword that has connotations of a field or industry starting to use science where they previously didn't. Over here in academia it's just "science", or possibly "data analysis" if you want to emphasise that that's the part of your project you're working on right now as opposed to data collection.
One of things that makes Python a killer language (apart from its readable syntax and straightforward programming model) is how it enables you to jump in at any skill level and be immediately productive, without hampering your ability to get things done quickly and elegantly as your skills grow.
There are faster, trendier languages out there, but I suspect Python will still be thriving when many of them have become footnotes.
Python is a great beginner language, but it isn't a language that is only for beginners.
It enables people that normally would not program to do things that they otherwise could not be done with traditional software with a GUI, that being web based, apps or desktop applications.
It is a stepping stone into computing that otherwise would have been inaccessible for many. Unlike BASIC, the design of the language is good enough that it can be used in professional applications, and not only being a stepping stone.
In languages where white space is insignificant, it is pretty much universal that we use syntactic elements to communicate block structure to the compiler, and white space to communicate block structure to humans. Having two different ways of communicating block structure is: a) redundant and wasteful, and b) a source of bugs.
So, if you buy into the idea that having two different ways of communicating block structure is somewhere between an annoyance and a language design defect, and also buy into the idea that computers should serve the needs of humans, then it follows that the compiler should extract block structure from source the same way that humans do. That being: significant white space.
The {} languages seem very primitive to me any more.
{} languages have the advantage of allowing you an immediate restyling of the code when the original author (who can be of varying skill level) wrote something you don't like looking at, or when you want to change the style of your own code for various reasons.
I find that Python-style blocks generally cause me more mild annoyances than {} blocks. A frequent thing that happens is copy-pasting/moving a line from some place to another with a different depth: In C, I paste and run my automatic indentation, while in python I have to specify manually by how much I want to indent my new code so that it can know within which block I want it. ... And it's not like you could do so automatically: if I want to paste something after the code of an "if ...:" block, the editor cannot know if I want it inside or outside the block.
On a more abstract level, I personally prefer a language where the end of a block is explicitly specified by the presence of a visible character rather than by the absence of an (arguably) invisible one, and where the form of the code does not affect its function in any way...
I'm not trying to argue that much against the python logic though, because the potential for disastrous style is indeed limited, it has its specific advantages, but I don't think delimiter-based languages can be qualified as more primitive just because of this.
And, yes, it is hard to argue that presence of {} makes a language objectively more primitive, which is why I used the word "feel"... the syntactic sugar necessary to keep the block structure straight just looks like noise to me any more. But as with many things, it comes down to personal preferences.
My code has whitespace that reasonably closely matches Python's rules regardless of the language. I only say "reasonably closely" because I don't spend enough time in Python to really be sure about any potential gotchas.
But like PEP 20 says:
> Explicit is better than implicit.
Brackets are explicit. Whitespace is implicit.
And the end of a block, the lack of indentation that denotes that, is absolutely implicit.
Personally I prefer {} blocks so I don't have to know what sort of white space is creating the indentation, even though I do miss using python sometimes and may come back to it for the right project.
This is trivially solved. You can find and replace with sed[0] if you want to be fancy, or just use your favorite text editor/IDE. The teams I've worked on have never had a problem with this. There is always an established convention in a project, and if you're breaking the convention -- e.g. because you prefer tabs -- you're doing it wrong, just by virtue of breaking the convention. If your project is new and you need to set a convention, do that. (also, PEP8 recommends spaces, so there is an authority to reference as a tie-breaker)
[0]: something like: find ./ -type f -exec sed -i -e 's/ / . /g' {} \;
While you're at it, please also s/\s+$//g on save. Those unintentional trailing spaces really clutter up Git history, and that comprehensive, clean history is what enables the team leads to do their job without bugging you on Slack. It also signals carelessness, or at least a lack of care for personal tools, and has your name attached to it.
I just tried with three different editors, and literally could not manage to get code in a file indented with a mix of tabs and spaces despite actively attempting to. Who are your co-workers who actually personally have had this happen to them in, say, this decade (not nebulous stories from the internet of "I heard once about this"), and how did they do it?
Though I do know in Visual Studio (what I do my day to day coding in these days) I've had situations at work where tabs and spaces got mixed together and at some point it finally started complaining but not right away.
sub (@) { return map { "@{[ $_[0] . $_ ]}" } @$_ };
Disclaimer: The majority of the programmers that I have known in real life that have a significant (and very vocal) dislike of Python's whitespace requirements have all written code like that above (this is my from-memory reproduction of actual code that one of them wrote). Python sucks because it's "restricting" them from being "expressive" with their code.Sadly, you can write code just like that in Python. I don't know what that perl snippet does, my caches have long since flushed ;) -- but here's a Python snippet that's relatively dense:
def foo(y): return lambda x: {str(i) : '_{}'.format(i**y) for i in range(x)}Was just reviewing colleague's code with them the other day. Hit some blocks like this (not quite as offensive, but tackling a bit in one line), and hell if they knew what was going on in their own code.
Not because I want to write everything on one line, but because it's an extra step when trying to understand what code does.
For instance, a piece of code is misbehaving, not being called as part of the block it visually appears part of. In a bracket/paren language I can highlight one bracket and my editor shows which one matches. In Python I have to figure out what the indentation is built from, spaces or tabs, and make sure there's no ambiguity there.
We have developers here that are claiming they wrote things in Python for their PHD, and yet when I look at their code in any language there are tabs and spaces mixed in the same line, with inconsistent indentation. Multiple people have tried to express the issue or teach ways to deal with it, to no avail.
The fact of the matter is that whitespace is by definition invisible, and that makes it hard for people to grasp its importance. Basing control flow on invisible characters is asking for trouble.
To quote PEP 20:
> Explicit is better than implicit.
Brackets are explicit, whitespace is implicit. You only can see whitespace by the gaps between visible characters, and then you have to guess. Is it an actual U+0020 like you see 99% of the time? Is it an nbsp? It it a tab that happens to stop after the width of a space? You don't know until you encounter an error or turn on whitespace rendering.
Was it copied and pasted from www.python-help-7575.com, which uses a platform that favors punctuation spaces? Was it copied from a site that didn't wrap their code in <code> or <pre>? (I see this all the time in comment systems on programming blogs) Should we claim that copying and pasting code in a beginner targeted language is something you do at your own risk?
The following program throws a TabError in Python 3:
def demo():
print("1 tab")
print("8 spaces")
It does work in Python 2, but I'm pretty sure the majority of developers have 4 space wide tabs by now, meaning they won't be able to mix tabs and spaces in Python 2 code either.EDIT: So Hacker News has code blocks, but doesn't strip the indentation that is required to introduce them. So you'll have to lead the 2 leading spaces in each line if you want to try this out for yourself.
Your example is good, but the technical issues experienced in posting your example are perfect.
That function is easy to parse if you take 20 min learning the syntax. Object oriented monstrosities aren't.
sub
It's an anonymous sub (@)
It has a prototype that says it accepts a list of arguments (this is the default in perl though).Prototypes are mostly for giving hints to the compiler on how to unambiguously parse calls to your function later. For an anonymous sub, it's pointless because you assign its value to a variable, and then brackets are required when calling it.
return
It returns the result of the map (this default in perl is to return the result of the last expression & everything is an expression though) map
same as python map(code, list) { "@{[ <some stuff> ]}" }
This is a particular perl goof for interpolating array lookups into a string. Usually, perl's sigils let variables be interpolated without any issue, but since we're using $_[0] to use the first element of the @_ array, it's ambiguous with $_ . '[0]'.The @{} dereferences the contents of the braces as an array, and [] creates a new arrayref. The arrayref has one element, and perl's default stringification of an array (join them all with no separator) means that it… iterpolates the thing inside the @{[]} into the surrounding string.
This is pointless though, since it's the only thing in the string. The author might have been trying to give a string context to force stringification of the thing, but the dot operator already provides that context.
$_[0] . $_
This is a string of the first element of … hmm. Not of the currently-mapped element (that's $_). $_[0] refers to the first element of @_. This makes a new value which is the concatenation of the first element with the current element. @$_
This is a short way of writing @{ $_ }: dereference the arrayref that's stored in $_. But $_ is not set anywhere, so I assume this is a typo of @_I would have written this as:
my $prefixer = sub { my($prefix , @rest) = @_; return map { $prefix.$_ } @_ };
And it would work like this: say $prefixer->('Hi_', 1, 'str', 7);
> 'Hi_Hi_Hi_1Hi_strHi_7'
The 'best' way to write it would have been: sub { $_[0].join($_[0], @_) } lambda *lst: ''.join([str(lst[0]), str(lst[0]).join([str(_) for _ in lst])])
Which is uh… begging for an initial line of "lst = map(str, lst)" {,/(*t),/:t:$x}
Flatten (,/) the first element of the list (*t) joined with each element of the list (a,/:b), where t is the input x cast to a list of strings (t:$x). Curly braces make the expression an anonymous function, and since no argument names are specified explicitly the name x is the single input argument. lambda *lst: ''.join(['{}{}'.format(lst[0], _) for _ in lst])(I guess the original code did something useful and looked very similar to this.)
It might just be the code base I'm working with..
But then they have to go and ruin it by making single letter variables a common thing.
Is Python use really growing? Or is this a Stack Overflow thing? I thought it was being displaced by Javascript Everywhere.
Python had a 5-year setback from the Python 3 transition, but we're now mostly past that.
That said; the idea of something like numpy in javascript is years off and laughable.
University undergraduate classes in a variety of courses use it as their default language, so it is a bunch of students trying to complete their homework assignments.
But besides, there still remains the same question as always: Doesn't the posing of Stackoverflow questions tend to reflect more who's starting to use a language, than the sum total of who uses it per se? (Since presumably questions taper off with time.) If you're measuring growth or adoption, as in this case, sure, it might seem like a reasonable approximation, but it doesn't tell you anything about long-term use (by people who become experts and stop visiting Stackoverflow) or about attrition (people who quit using it and move on to something else). Thus any trend Stackoverflow can see, probably overemphasizes short-term phenomena. Which is great if you're doing algorithmic trading on the stock market and make your money by responding to the market's every short-term boom & bust (and other investors' overconfidence & diaper-crappings respectively), but not so great if you're choosing a language to which you'll devote months of study.
So I agree that another revamp would be good now, but I historically the docs have been a plus as much as they've been a minus, relative to Python's alternatives.
Are you referring to Github, Shopify, Basecamp and many other functional businesses scaled and built on the shoulders of ruby "unicorns" and "kittens" ?
Having worked with both languages, I can confirm that they simply have different view points with tradeoffs, and that in itself is a matter of personal opinion.
But claiming one community does not build great tools because you view them as "kittens" is ridiculous.
Also please do not generalize things like "most people" prefer X.
[EDIT] I sincerely hope this comment does not come off as rude. I am just trying to understand OP's point of view
In comparison, big Python projects have a lower profile, a more serious, adult tone, and generally don't brag too much about their capabilities.
In practice I've seen that the Python community's greater skepticism towards new packages means that libraries have evolved more slowly but with more certainty, whereas Ruby libs have been swapped out as fashions come an go. Witness the fact that Rails decided to package Coffeescript at its core, whereas Django has no strong opinions on frontend matters. Also look at Django's mature deprecation policy compared to pretty much everything else.
He also has very good thoughts, and very important for beginners to know, about how there isn't a single right way to learn programming.
> In any case, data science is an exciting and growing field, and there’s plenty of room for multiple languages to thrive. My main conclusion is to encourage developers early in their career to consider building skills in data science. We’ve seen here that it’s among the fastest-growing components of the software development ecosystem, and one that’s become relevant across many industries.
Also, Python is probably the most concise and easy-to-read imperative language that has gained wide acceptance.
Of all major languages is by far the slowest, hardest to extend and by now easily surpassed PHP and JavaScript with its number of design quirks.
I big reason why Pandas is so popular is because its API is so complicated. I probably have 10x more experience using Pandas than Django. And yet, when I'm doing something in Pandas I'm visiting the documentation far more often than Django. Let's compare the top level APIs:
>>> import pandas as pd
>>> len(dir(pd))
177
>>> import django
>>> len(dir(django))
11
Also, I find the data manipulation Pandas provides is far inferior to the R Hadleyverse and is one of the few things that R does better than Python.
Btw, for those of you who dislike the dynamic typing (e.g. myself) of Python, check out Cython, it's really heaven.
Why is it growing so quickly? I speculate:
Lots of people want to learn to program - and Python is easy to learn and teach.
I think it blows other languages out of the water. I'm going to compare it to its closest competitor, Ruby. Ruby is also open-source, high level, popular relative to other languages (which means you can probably get help if you need it), it has lots of libraries (meaning you can do a lot with it), ok tutorials, and a decent package manager. On the downside, Ruby is also a very large language, which makes it much harder to learn to mastery.
I think Python blows Ruby out of the water in terms of how easy Python is to learn relative to Ruby.
I don't encourage people to learn Ruby. I spent a long time (months) trying to learn it. I still don't tell people I know it.
I used to think that Ruby's syntax is twice as much to learn - now I think it might be even more than that.
Ruby's YACC file is ~918 lines long[0], while Python's grammar file is 149 lines long.
~$ wc cpython/Grammar/Grammar
149 879 6472 cpython/Grammar/Grammar
Even if 1/2 of Ruby's grammar output is whitespace, that's more than twice as much grammar to learn as Python's grammar[1].I could compare Python to other languages, but I don't think they come close to matching the upsides of Python.
I still want to learn other languages, like Haskell, lisps, and C, to a level of mastery - but since I can be so productive so fast with Python, the other goals are something I work on in my spare time without a bunch of urgency.
[0] https://stackoverflow.com/a/16629318/541136
[1] https://docs.python.org/3/reference/grammar.html
PS I can see that this comparison to Ruby isn't popular due to the downvoting - but nobody is contradicting my point.
Python's so popular because it maximizes developer productivity.
1) Computational Linguistics libraries
2) Machine Learning libraries
3) Still one of the blessed languages internal to Google? and BFDL was employed for a while there
4) Jupyter Notebooks
5) Coder Dojo approved language
I used to think that all dynamic languages (Ruby/Python/Javascript/Perl/…) were of a par but I have to admit that Python has an awful lot of mindshare and it's beginning to exhibit strong network effects.
Ruby is a wonderful language with a really unfortunate standard implementation. It's easily 5 times slower than Node at practically anything, which is sad because Ruby is infinitely better than Javascript. I really think this is what it comes down to and why Rails has been dying off.
Plus there has been a reaction to Rails size and complexity. I kind of hate that everyone thinks of Rails when Ruby is mentioned. But I thought Sinatra was a really nice microframework.
This has repeated often but so far I haven't found a really convincing argument. All my friends, who know C, C++, C#, Java (and other languages) had no problem in picking up Javascript/ES7 for programming the browser using whatever you need.
I think this argument was exciting for the front-end developers who wanted to try doing things on the server but couldn't be bothered into learning a new language. So now with Node.js they are happy and satisfied, until they realize that the problem is not the language; the problem is that server programming is a different matter altogether, no matter what the language is.
It'll be interesting to see whether Python or Ruby or Ruby get to WebAssembly first – I'm correct in saying that none has of yet, yes?
You can check out the Oracle Labs code and progress of Graal/TruffleRuby here: https://github.com/graalvm/truffleruby
Relevant page: https://labs.oracle.com/pls/apex/f?p=labs:49:::::P49_PROJECT...
And IBM's Ruby+OMR code and progress is here: https://github.com/rubyomr-preview/ruby
Relevant post: https://developer.ibm.com/open/2017/03/01/ruby-omr-jit-compi...
Can Matz somehow in the nicest possible way kidnap Lars Bak and pay him in gummy bears or something?
Scheme, Common Lisp, and Julia all have good metaprogramming facilities (i'd argue, for Scheme & CL, way beyond what Ruby offers), and they are highly performant, indeed much faster than Ruby, Python (even under Jython) and Javascript under V8.
Try Lua, Common Lisp, Julia, and Racket, for a surprise.
My first language was Basic and my second language was C64 Assembly and Pascal. I would have killed for Python as a kid.
Better editors help too.
And this was way back when twisted was the only asynchronous game in town. So I'm not surprised it's growing.
My experience with python has been positive but I don't understand how people who want to create separate libraries for specific functionality tie these codebases together without using deprecated features or containerizing everything.
If you need to keep things on premise, is running your own pypi particularly hard? I've never tried so maybe there's a bunch of hidden complexity but there are some packages to run one and even a docker image: https://hub.docker.com/r/codekoala/pypi/builds/bwe6cdn4swgyi...
Personally I met with python thanks to course assignments. It helped me to finish my projects way faster than any other language. I loved its simplicity and now even in my complex projects, I tend to solve my problems in "python way".
Also modularity, almost non-existent boiler-plate code, etc kind of things attract data scientists without computer science background.
#2 - it's dead simple to do things; the syntax is, to me at least, about as direct and uncomplicated as you can get (and without being overly wordy!)
#3 - so many handy libraries... it's good for full projects, and it's great for integrating and gluing things together
I wouldn't call programming in Python fun, per se, but I do call "getting things done quickly and easily" fun.
I am at a big company, and it seems most new projects are being done in Python. No one asks why, it is just accepted.
Now the question is why. I have no explanation, other than maybe that's because universities have been teaching python more often, and it happens to be practical.
I just wish everyone were using Python 3.
That's a question that bugs me. I can't believe the level of obviousness of the things that are wrong. That is because we write complex code. Things like direct access to data members (which is 'pythonic'!) are cruel blows to software productivity for complex code. Ugh, Ugh, let me count the ways: No compiler to check the code. The other day I dumped 800 extra lines into a file as a typo. Many, many duplicate functions. Of our whole test suite, how many tests failed? One!!! Ugh. This is not even to mention the topics of Black.Holes.In.Your.Code because you can't tell what types the functions receive. I really think python is driven by non-programmers who consume rather than produce complex code and the teachers who teach these people. I believe the problems will increase over time. Does anyone know the story of Hack at Facebook? I heard the lead developer give a talk once. Be afraid.
> Things like direct access to data members
I think you're complaining about (lack-of-) encapsulation. Between methods, functions, and properties, there's ample opportunity for encapsulation. The convention is for internal-use-only members to be prefixed with an underscore.
> No compiler to check the code.
In fact there are many static checkers. pylint, pyflakes, etc.
> This is not even to mention the topics of Black.Holes.In.Your.Code because you can't tell what types the functions receive.
In fact, you can use type hints [1] to do this.
> The other day I dumped 800 extra lines into a file as a typo. Many, many duplicate functions. Of our whole test suite, how many tests failed? One!!! Ugh.
This isn't quite explicit enough for me to understand. You unintentionally redefined a function multiple times in the same file, and your test suite caught the error. You think that instead Python should've refused to execute/import this module w/redefined functions? Hmm, I suppose it's a very uncommon need to redefine functions but it's not uncommon to assign a function to a file-scope name. Also keep in mind that both pylint and pyflakes detect this mistake.
I think this tone is misplaced here.
Use aptly named parameters, always, add assert() statements for type checking whenever you feel mistakes could happen.
I can bet, based on my experience, that it's much "safer" (less error-prone) to use a language that allows calling functions with named parameters (where the order of parameters doesn't matter and you know exactly which parameter are you sending a value into), than a language like C++ or Java which has a static typing system but has no named parameteres, plus depends on argument order to call a function.
You should try using Python in this way.
I totally understand the lack of typing & static compilation making things painful once you reach a scale where you can't put the codebase in your head. Asserts, unit tests and variable names are poor substitutes. As an interm solution have you tried converting your internal python code to be fully typed with 'optional types'?
Go is far from a modern language, being more like a mutant, crippled subset of Algol-68, which, as the name says, dates from 1968...