(Click the blue text above to quickly follow us)
Translation: Open Source China
www.oschina.net/translate/languages-to-improve-your-python
If you have good articles to submit, please click → here for details
27 Programming Languages
-
Procedural Programming Languages: C, Rust, Cython
-
Object-Oriented Data Modeling Languages: Java, C#, Eiffel
-
Object-Oriented Derivatives of C: C++, D
-
Array-Oriented Data Processing: MATLAB/Octave, Julia
-
Statistical Data Analysis: R
-
Computational Pipeline Modeling: Haskell, Scala, Clojure, F#
-
Event-Driven Programming: JavaScript, Go, Erlang, Elixir
-
Gradual Typing: TypeScript
-
Dynamic Metaprogramming: Hy, Ruby
-
Pragmatic Problem Solving: Lua, PHP, Perl
-
Computational Thinking: Scratch, Logo
As one of the co-designers of one of the most popular programming languages in the world, I often encounter a frustrating behavior (present in both the Python community and other fields) where influential figures in the community try to instill a sense of fear about what is “missing” in other open-source communities, driving others to contribute to our community (I occasionally exhibit this inappropriate behavior myself, and I find it easier to notice when others fall into this trap).
While learning from the experiences of other programming language communities is a good thing, using fear-based methods to drive action has significant issues; community members may view members of other communities as competitors rather than potential allies to face challenges together and advance software development technology. This can also lead to the community excluding those who prefer other programming languages, treating them as enemies.
In fact, we hope for a richer selection of cross-platform open-source programming languages. Programming languages are the most important thinking tools, allowing us to translate our ideas into terms that computers can understand. If people find a language that suits their brain and directly solves their problems, that’s great; they shouldn’t have to worry about which language they choose.
Therefore, I want to propose three specific requests and one broader suggestion to the Python community. First, let’s talk about these requests:
1. When we want to motivate tribe members and enhance community attraction, we should not use fear tactics; instead, we should use pride tactics. When using fear tactics to motivate, such as saying, “If we don’t solve problem X, then Python developers will decrease, and they will turn to language Y,” we are deliberately sending negative energy to the world of free code contributors. However, if we use pride tactics, we would say something like, “Problem X in Python is indeed difficult to solve; look at community Y, they solved this problem in an excellent way, and we can try this solution in Python to elegantly resolve the issues.” Emphasizing “pride in our own efforts” positively fosters a culture of continuous learning in the Python community and promotes ongoing relationships with other communities.
2. We should restrain our disdain for other programming language communities, especially those with significant contributors who can solve problems on their own without waiting for commercial software vendors to deign to solve them. Most of the important problems in the world are not profit-driven (those people want to solve problems not for wealth, nor are they funded by institutions), so we should encourage and praise those who are actively trying to solve problems, regardless of the technology they use.
3. If we know someone who is just starting to learn programming, even if the programming language they choose is not one we like, we should support them because they know better what suits their brain. So, a language that is suitable for us may not be suitable for them. If they become frustrated with their initial choice to the point of losing their motivation to learn programming, it makes more sense to recommend programming languages at that point. This advice is even useful for those among us who have worked on improving network security; for inherently insecure languages, our solution is to gradually dismantle this language selection barrier by enhancing the sandboxing features in the operating system, improving the default behavior of programming languages with the native system’s security attributes, and we should not evaluate programming languages based on application security perspectives, which can confuse beginners. (If someone asks a programming novice to write unaudited software that is deployed to handle security-sensitive issues, this is not the programmer’s fault; rather, it should be blamed on the deployer for not doing due diligence on the software’s source and security attributes.)
My further suggestions are aimed at people who begin to encounter the core Python assembly and thus start exploring more of Python’s own “thinking tools.”
Part of what we do in the Python core development process is due to the characteristics we understand that give us an advantage in other languages; can we make Python code easy to read and write? This means that learning other programming languages can clarify specific styles and enhance one’s understanding of software development through programming in Python.
To assist in this effort, I have listed below areas for exploration, along with some languages that may provide additional insights into these areas. I have tried to link to Wikipedia pages rather than directly to the relevant home pages because Wikipedia often provides interesting historical backgrounds, which are worth exploring when choosing a new programming language as an academic exercise rather than for immediate practical use.
However, personally, I am familiar with many programming languages (and have used some of them to develop production systems). All the recommendations include languages I indirectly understand (either through reading some materials and design documents or through discussions with trusted friends about a language’s strengths and weaknesses).
There should be many more languages appearing on the list, but the specific languages listed here are just a random subset, selected based on my own interests (for instance, my primary interest lies in the dominant Linux, Android, and Windows ecosystems, so I have omitted the closed but more profitable Apple-centric Objective-C and Swift programming languages, and I am not very familiar with programming languages focused on artistic environments, such as Processing; I even have to guess how what I learn from them can guide a Python developer). A more comprehensive list of programming languages would need to consider many factors, besides considering how a programming language can guide you to become a developer, the IEEE Spectrum’s annual ranking of programming language popularity and growth is also worth understanding.
Procedural Programming Languages: C, Rust, Cython
The default execution model of Python is procedural: we start from the top of the main module and execute one statement at a time. All of Python’s support for other data and computation models is based on this procedural characteristic.
C language is undoubtedly still the ruler of low-level programming languages. It is the core language for implementing the Python interpreter and also the core language for implementing the Linux operating system kernel. As a software developer, learning C is the best starting point to learn more about the underlying hardware on which software runs – C is often described as a “portable assembly language,” and it is commonly used with C compilers as cross-compilers to compile the first applications for new CPU architectures.
Rust, in contrast, is a relatively new language created by Mozilla. The reason it can enter this list is that Rust learned from the industry’s known lessons about what cannot be done in C, and it was designed to be a language that can interoperate with C libraries. It achieves the same level of precision in hardware control as low-level system programming languages, but it uses different compile-time methods for data modeling and memory management, structurally eliminating many common pitfalls that plague C programs (such as buffer overflows, double-free errors, null pointer access, and thread synchronization issues). As an embedded systems engineer, I have seen that many areas currently dominated by C language and custom assembly code are likely to be replaced by Rust.
Cython is also a lower-level language by default, but unlike general-purpose languages like C and Rust, Cython is mainly used for writing CPython extension modules. Cython is designed as a superset of Python, allowing programmers to choose when to support pure Python syntax; when Cython syntax is supported, it can generate code with speed and memory efficiency comparable to native C code.
Learning one of these languages enhances practical understanding of memory management, algorithm efficiency, binary interface compatibility, software portability, and a profound understanding of how source code is transformed into running systems.
Object-Oriented Data Modeling: Java, C#, Eiffel
One of the primary tasks in programming is to model the states of the real world, and the most common approach is the native syntax support provided by object-oriented languages: combining data structures and methods that operate on these data structures into classes.
Python is natively designed to directly use object-oriented features without needing to first learn how to write one’s own classes. Not every language has this approach – for the languages listed in this section, learning object-oriented design concepts is a prerequisite for using these languages.
Thanks to Sun Microsystems’ marketing of the Java language in the late 1990s, Java became the default language for many college computer science introductory courses. Although it is now being replaced by Python in many educational fields, it remains one of the most popular languages in commercial application development. A series of other languages target implementations for the common JVM (Java Virtual Machine) runtime, including Python’s Jython implementation. The Dalvik and ART environments of the Android system are based on the Java programming API.
C# is similar to Java in many ways; it emerged as a replacement for J++ (Microsoft’s implementation of the Java language) after Sun and Microsoft failed to resolve inconsistencies between J++ and standard JAVA. Like Java, it is also a popular language for commercial application development, and a series of other languages target implementations for the shared .NET CLR (Common Language Runtime), including Python’s IronPython implementation (the core components of the original IronPython 1.0 were extracted to create an intermediate layer for the .NET dynamic language runtime). For a long time, .NET was a proprietary technology that could only be used on Windows systems, but in early 2015, Microsoft announced the .NET open-source initiative.
Unlike most languages on the list, I do not recommend using Eiffel in everyday usage. It is included in the recommendation list because this language has a wealth of excellent object-oriented design concepts, including “correct and reliable” as design goals for programs. (At the same time, Eiffel tells me that for most software development, “correct and reliable” is not the design goal; this is because correct and reliable software cannot properly handle uncertain situations. When many relevant constraints are still unclear and need to be gradually refined through iteration, this design philosophy is entirely inappropriate.)
Learning these types of programming languages requires familiarity with inheritance models, contract design, class invariants, preconditions, postconditions, covariance, contravariance, method lookup paths, generic programming, and various other features supported by Python’s type system. There are also many standard library modules and third-party frameworks that employ “explicit object-oriented” design styles, such as unittest and logging modules, as well as class-based views in the Django framework.
Object-Oriented C: C++, D
One way to use CPython is to treat its core as a programming environment that is a “C language containing objects” – CPython implements object-oriented programming through C language style, that is, using C structs to describe data and passing the instance pointer of the struct as the first argument to those data processing functions (this is the ubiquitous PyObject* pointer in CPython’s C). This design pattern is intentionally replicated in Python, where instance methods and class methods need to explicitly specify self or cls parameters.
C++ aims to be source-compatible with C while adding some advanced features, such as native object-oriented programming support and template-based metaprogramming. C++’s obscurity and complexity are notorious (even though the 2011 language standard update resolved many of the worst issues), but it remains a choice in many scenarios, including 3D modeling graphics engines and cross-platform application development frameworks like Qt.
The D programming language is also interesting because its relationship with C++ is similar to Rust’s relationship with C: the purpose of designing the D language is to retain most of C++’s advantages while avoiding many of the pitfalls present in C++ (such as lack of memory safety). Unlike Rust, D is not a completely new programming language designed from scratch; rather, it is directly derived from C++. Although it is not a strict superset of C, it adheres to a design principle that any code falling within the common subset of C and D must behave the same in both languages.
Learning these languages helps deepen understanding of the complexities of combining high-level language features with the low-level C runtime model. Learning C++ also aids in using Python to operate existing libraries and toolkits written in C++.
Array-Oriented Data Processing: MATLAB/Octave, Julia
Array-oriented programming is used for numerical programming models: based on matrix algebra and related numerical methods.
Although Python’s standard library does not directly support this, it has been designed with a series of syntax and semantic features that help third-party libraries like NumPy and similar array-oriented tools.
In many cases, Python’s scientific computing software suite is regarded as a replacement for the specialized MATLAB programming environment, widely used for modeling, simulation, and numerical analysis in science and engineering. The open-source project GNU Octave aims for syntax compatibility with MATLAB code, allowing for a comparison between these two object-oriented programming approaches.
Julia is another relatively new language, characterized by its support for array-oriented programming and type-based function overloading.
Learning one of these languages helps deepen understanding of the power of Python’s scientific computing toolkit, while studying such languages helps explore how to leverage hardware-level concurrent execution using technologies like OpenCL and Nvidia’s CUDA, as well as how to implement distributed data processing using frameworks like Apache Spark and Blaze.
Statistical Data Analysis Language: R
With the increasing number of large datasets needing processing, there is a need for a free analytical tool capable of handling such datasets, and the R programming language is one such tool, particularly focused on statistical data analysis and visualization.
Learning R language helps deepen understanding of the statistical functionalities of Python’s scientific computing toolkit, especially its data analysis library pandas and statistical visualization library seaborn.
Computational Pipeline Modeling Languages: Haskell, Scala, Clojure, F#
Object-oriented data modeling and array-oriented data modeling are primarily used for static modeling of data; there are two modeling approaches: one is to store data in the various properties of objects, and the other is to save structured data as arrays.
In contrast, functional programming languages emphasize dynamic modeling of data in the form of computational flows. Just by learning the basics of functional programming, one can significantly enhance their ability to model data using data transformation operations, which is also helpful when developing applications using other paradigms (such as procedural, object-oriented, and array-oriented programming languages).
Haskell is a functional programming language that has had a significant influence on Python’s design, the most noticeable being the list comprehensions introduced in Python 2.0.
Scala is undoubtedly a functional programming language based on the JVM and, like Java, Python, and R, is one of the four main programming languages of the Apache Spark data analysis platform. While supporting functional programming, Scala’s syntax, data model, and execution model are designed to avoid imposing too great an obstacle for existing Java programmers (from this perspective, Scala should be more appropriately classified as an object-oriented programming language with strong functional language support).
Clojure is another functional programming language based on the JVM, regarded as a variant of Lisp. It earns its place in our list because it inspired the implementation of Python’s functional programming toolkit toolz.
I am not familiar with F#, but since it is a recommended language for .NET CLR, it is worth noting.
Learning these programming languages helps understand Python’s own computational pipeline modeling tools, including container inference expressions, generators, generator expressions, the functools and itertools standard library modules, and third-party functional Python tools like toolz.
Event-Driven Programming Languages: JavaScript, Go, Erlang, Elixir
Computational pipelines are a great way to handle data transformation and analysis problems, but many problems require programs to run persistently, waiting for events to occur and then processing those events. For such services, multiple events can typically be processed concurrently to provide service to multiple users (or at least multiple actions) simultaneously.
JavaScript was originally developed as an event-handling programming language for browsers, allowing web developers to handle local user behaviors (such as mouse movements and keystrokes) and events (such as page render completion). All modern browsers support JavaScript, which, together with HTML5’s DOM, has become the de facto standard for the appearance and behavior of user interfaces.
Go is designed by Google with the goal of creating highly scalable network services. Go language is very suitable for developing command-line programs. From the perspective of programming language design, the most notable aspect is that Go uses the concept of “Communicating Sequential Processes” in its core concurrency model.
Erlang was designed by Ericsson with the goal of creating highly reliable telephone switches and similar devices. The famous open-source framework RabbitMQ’s message server is implemented in Erlang. Erlang uses the Actor model to implement core concurrency primitives, disallowing different threads from directly sharing data; inter-thread communication can only occur through message passing. Although I have never used Erlang, my first job involved a concurrency framework developed based on the Actor model, created by a former Ericsson engineer in C++. I have also developed such frameworks based on TSK (tasks) and MBX (mailboxes) in Texas Instruments’ lightweight DSP/BIOS runtime (now called TI-TROS).
Elixir earns its place on this list because, although it runs on the Erlang virtual machine and shares the same concurrency semantics as the Erlang programming language, it also includes a series of additional language-level features that provide a more comprehensive development environment, making it easier to attract developers transitioning from other programming languages (such as Python, Java, or Ruby).
Learning one of these languages helps deepen understanding of how Python itself supports concurrency and parallelism, including native coroutines, generator-based coroutines, the concurrent.futures and asyncio standard library modules, third-party network service development frameworks (such as Twisted and Tornado), the channels concept newly introduced in Django, and event handling loops in GUI frameworks.
Dynamic and Static Mixed Types: TypeScript
Among the features introduced in Python 3.5, the most controversial is the new typing module, which adds support for mixed types to the Python system.
For developers familiar with static typed programming languages like C, C++, and Java, this is a daunting idea.
Microsoft’s TypeScript provides dynamic and static mixed type support for JavaScript applications, giving you a better perspective on this concept. TypeScript code compiles into JavaScript code (without any runtime type checks after compilation), and annotations for mainstream JavaScript libraries in TypeScript can be found in the DefinitelyTyped codebase.
As Chris Neugebauer pointed out in a presentation at PyCon Australia, this is akin to the relationship between Python and the typeshed typing library, as well as static analysis tools like mypy.
Essentially, TypeScript and Python’s type hints are both ways to implement specific testing programs, whether they are standalone files (regular testing programs) or embedded within the main code (similar to type declarations in static programming languages). In either case, you can run separate commands to check whether the remaining code adheres to known type constraints (for JavaScript and TypeScript, this is implicitly done at compile time; for Python’s type hints, it is an optional static analysis task).
Dynamic Metaprogramming: Hy, Ruby
One unsettling feature that programming languages like C, C++, C#, and Java bring to Python is “code as data”: functions and classes are runtime objects that can be manipulated by other objects.
Hy is a variant of Lisp that can run on both the CPython and PyPy virtual machines. Lisp takes “code as data” to the extreme; Lisp code itself consists of nested lists that describe the operations to be performed (the name of the language comes from “LISt Processor”). Lisp-style languages are powerful because they can easily implement their own domain-specific languages (DSLs), but this sometimes makes reading other people’s code difficult.
Ruby is similar to Python in many ways, but as a more open community, Ruby is more accepting of dynamic metaprogramming, whereas Python merely “supports but does not encourage” this aspect. This functionality includes redefining classes to add methods and using closures to implement core language structures like iterators.
Learning these languages can help deepen understanding of Python’s own support for dynamic metaprogramming, including function and class decorators, monkey patching (dynamic code modification), the unittest.mock standard library module, and third-party object proxy modules like wrapt (I have yet to find any programming language that helps understand Python’s metaclasses; if anyone has good suggestions, please let me know in the comments. Advanced features of metaclasses include core types, abstract base classes, enumeration types, and mixed type (dynamic and static type mixed) expression runtime execution).
Pragmatists: Lua, PHP, Perl
Popular programming languages are often not isolated – they are part of a vast ecosystem (both commercial and community), along with end users, framework developers, tool developers, educators, and so on.
Lua is a popular programming language primarily embedded as a scripting engine within large programs. Notable examples include plugins written for the Warcraft game client and the RPM tools found in many Linux distributions, which are also built on Ruby. Compared to CPython, Lua’s runtime size is only one-tenth, and its weaker introspection capabilities allow it to be more easily decoupled from other parts of the application and the host operating system. One notable contribution from the Lua community to the Python ecosystem is that CPython and PyPy adopt LuaJIT FFI (Foreign Function Interface) as the basis for their JIT-friendly cffi interface library.
PHP is another popular programming language, widely known for its ability to generate HTML pages and was extensively used by early virtual server hosting providers, hence being well-known as part of the LAMP stack (Linux-Apache-MySQL-PHP). Despite many frustrating conceptual flaws in its design, PHP has become the foundation for many well-known open-source web services, including the Drupal content management system, WordPress blogging engine, and the MediaWiki engine that supports Wikipedia. PHP also supports many important services, such as the distributed event reporting platform Ushahidi used by crowdsourced communities.
Like PHP, Perl is also a popular language on Linux systems. Unlike PHP, Perl is not known as a website development platform; it is more commonly used as a tool for system administrators to manage systems, capable of handling strings with regular expressions and processing the output of text-based Linux operating system commands. Using Perl alone can accomplish all tasks without needing to resort to tools like Whensh, awk, and sed.
Learning one of these languages does not provide any insights into aesthetically pleasing or conceptually simple programming language design. The possible outcome is to gain practical knowledge of the structures and adoptions of various programming languages, as well as understanding the roles of chance, historical accumulation, and lowering barriers to entry (through redistribution to make defaults possible), which are stronger than the inherent abilities of the languages themselves.
In particular, it can provide insights into the significance of projects like CKAN, OpenStack NFV, Blender, SciPy, OpenMDAO, PyGMO, PyCUDA, Raspberry Pi Foundation, and Python, ensuring the institutional investment in the Python ecosystem continues through extensive commercial organizations.
Concepts of Numerical Computing: Scratch, Logo
Finally, I often find myself caught in discussions about the arguments between advocates of structured programming and object-oriented programming. The latter claim that object-oriented programming languages are just as easy to learn as structured programming languages.
When we talk about teaching through concrete numerical experiments (robotics), the models of subjects in simulation software have direct real-world counterparts, such as students interacting with sensors, engines, relays, etc. I believe that supporters of object-oriented programming have a valid point.
However, for others, I encounter a typical challenge: take a cookbook and convert one of the recipes into what you believe is an easy-to-learn object-oriented programming language, then find a student who understands that programming language to continue converting the recipe along my lines. (I look forward to seeing academic researchers genuinely practice such a learning process – I would sincerely feel gratified by such a situation.) Most of the time, companions do not need to follow such a process – merely conducting thought experiments in their minds is sufficient for them to feel how much preparatory knowledge is required to learn this “easy-to-learn” programming language.
However, another solution to this problem is to learn those programming languages used to teach children numerical computing.
One of the most popular is Scratch, which allows students to manipulate a closed graphical environment through dragging, enabling them to see corresponding movements and reactions in the graphical interface. Graphical environments like Scratch provide a programming approach similar to using comic strips to help children gradually learn to read and write.
However, the idea of using a specially designed educational programming language to operate a graphical interface is not new; one of the earliest classic environments was the Logo environment created in the 1960s (similar to Python’s own turtle module), where the main interaction was with a “turtle” that you could command to move and draw lines, thereby changing the graphical environment. In this way, concepts like command lines, iteration, and state (e.g., moving up or down) are introduced based on a natural intuitive thinking process (imagine if you were a turtle, what would happen if you turned 90 degrees to the right?).
Returning to the essence, as an experienced programmer, relearning any of the above programming languages is the most effective way to forget what has been learned (to discard some wheels): the concepts covered by these language tools help us recall those concepts we once took for granted but need to relearn with a beginner’s perspective. When we do this, we are more likely to recall the entire logical chain, including those thought steps we previously considered obvious and omitted, allowing us to work more effectively with students and other beginners.
Did you gain something from this article? Please share it with more people
Follow ‘Python Developers’ to enhance your Python skills