Release 0.2b: #js-vs-py - Fianlly learning Python!

Hello and welcome back to my #HacktoberFEST series!

The 2nd week of October means the 2nd pull request (PR) has to be done (at least for me and the sake of me following my plan).

Issue #2: Add user authentication to a simple messaging app

This week, I have been working on a new open source project called tmessage of which links are bellow:

Links: Repository | Issue | Pull Request

The project is a simple Python program with the support of the paho-mqtt.py library that supports text communication between users over the lightweight and low-bandwidth MQTT protocol.

The issue is that, currently, a user can start the app under any name and start messaging. This can cause identity-related problems so the owner of the project wants to implement a simple username-and-password-based authentication system.

The reason I want to work on this problem is straightforward that:
  • I think this project can be a good base for me to learn Python and...
  • ...that's it... there's no 2nd reason.
As I accepted to work on the issue, after some productive conversation with the owner...


I decided to adopt a solution where I would need to perform 2 tasks:
  • Building a RESTful API for authentication and registration with JavaScript and Node.js
  • Add functionality to the current app for it to interact with the web API
And accomplish both tasks, I did. The tmessage-api was built and hosted. I also made a Pull Request to build the API... I am still wondering if I should count this as 1 PR for HacktoberFEST...

Links: Repository | Pull Request

As for the client-side code to interact with the newly created API, it was a little bit more challenging since I had to learn Python to do it. With some experience in JavaScript, I find it reasonably easy to achieve.

The work I have done for this contribution is relatively trivial and a lot of detailed instructions can be found online. Therefore, to lengthen my blog post, I would like to discuss my impression and first experience of learning Python through the following topic: "JavaScript vs. Python".

JavaScript vs. Python


JavaScript and Python are 2 programming languages that are very well-known as the "first language" for beginners but also possess differences in many aspects: philosophy, syntax and usage.

While JavaScript is a scripting language used mostly for the web and mostly run in browsers, Python is an object-oriented programming language (which happens to work as a scripting language just fine) and requires installation of its interpreter to run.

Many of the differences between Js and Py derive from the one mentioned above, 3 main ones that I think "immigrants" from JavaScript or, in general, beginners in programming should notice are the followings:

Difference #1: From philosophy to syntax

Philosophy of Python are beautiful, explicit, simple and readable...
$ python
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 19:29:22) [MSC v.1916 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
With this philosophy in mind, the creators of Python have made this language different from "the C-liked" genre.

No semi-colon ";" , no block-enclosing brackets "{ }" and INDENTATION MATTERS !!!

Let me start this topic by saying you can forget about the semi-colon in Python (unless you want to write some ugly codes), A statement ends with a newline character.

Next, code blocks in Python are identified by their level of indentation, not a pair of enclosing brackets. To demonstrate this point, I have code snippet...
# Code snippet A
age = 17
if age >= 19:
    print('You can legally drink in Ontario')
    print("Don't drink before you drive!")
and another...
# Code snippet B
age = 17
if age >= 19:
    print('You can legally drink in Ontario')
print("Don't drink before you drive!")
While Code snippet A produces no output at all, Code snippet B still prints the 2nd line:
Don't drink before you drive!
This is because, in Code snippet A, both of the print statements are under the scope of the if conditional structure, thus, none will be printed when the condition is wrong while in Code snippet B, the 2nd print statement is unindented, therefore, is outside of the block of the if statement which is executed regardless of the result of the condition.

This example emphasizes the importance of white spaces in Python which in cases like above determine the outcome of the program. 

No switch/case structure and shorthand increment/decrement operator (++, --)

In JavaScript, we have a conditional structure called switch/case which essentially evaluates the expression in the switch clause and compares the result to each case clause to select the code block to be executed.

An example of the said structure in a function that returns the current weekday as a string in Js:
// JavaScript
function get_weekday() {
    let today = new Date().getDay();
    switch (today) {
    case 0:
        return "Sunday";
    case 1:
        return "Monday";
    case 2:
        return "Tuesday";
    case 3:
        return "Wednesday";
    case 4:
        return "Thursday";
    case 5:
        return "Friday";
    default:
        return "Saturday";
    }
}
In Py, to adopt the philosophy of simplicity, the switch/case statement is not implemented. To achieve the same behaviour in Py, we can only use the traditional if statement which is if/elif/else in Py:
# Python
import datetime as dt
def get_weekday():
    today = dt.datetime.today().weekday()
    if today == 0:
        return "Monday"
    elif today == 1:
        return "Tuesday"
    elif today == 2:
        return "Wednesday"
    elif today == 3:
        return "Thursday"
    elif today == 4:
        return "Friday"
    elif today == 5:
        return "Saturday"
    else:
        return "Sunday"
Another "missing" element of Python is the shorthand operator for incrementing and decrementing a number. For example, we have a JavaScript class encapsulating the stats of a player in a game:
// JavaScript
class Player {
    constructor() {
        this.health = 100;
    }
    get_attacked() {
        this.health--; // or --this.health;
    }
    heal() {
        ++this.health; // or this.health++;
    }
}
You can see that we decrement the player's health by 1 when they got attacked and increment it by 1 when they heal using the ++ and -- operator. The same class written in Python would be:
# Python
class Player():
    def __init__(self):
        self.health = 100

    def get_attacked(self):
        self.health -= 1  # or self.health = self.health - 1

    def heal(self):
        self.health = self.health + 1  # or self.health += 1
As we can see, the closest we can get to the shorthand ++ and -- in Python would be the += and -= operator. And finally, of course, we can always do...
# Python
self.health = self.health + 1
and...
# JavaScript
this.health = this.health + 1

Difference #2: Object Model

JavaScript and Python have one significant difference that clearly distinguishes them from each other and that is their Object Model. Specifically, while Py uses a classical Class Inheritance model, Js adopts another model called Prototypal Inheritance.

The difference can be seen in the way we create objects in the 2 languages. In Js, there are a million ways to create an object, some examples...
// JavaScript
let player1 =  { health: 100 };  // <-- Object

function PlayerFunc() {
    this.health = 100;
}
let player2 = new PlayerFunc();  // <-- Object

class PlayerClass {
    constructor() {
        this.health =  100;
    }
}
let player3 = new PlayerClass();  // <-- Object
In short,  objects in Js can be created either from nowhere with the enclosing pair of curly brackets, from a function constructor or from a class (which is technically still a function constructor, class is just a syntax sugar). Unlike Js, in Python, an object is and can only be an instance of a class. Python requires a class as a blueprint for an object to be created, an example...
# Python
class Player:
    def __init__(self):
        self.health = 100

player = Player()   # <-- object
player2 = { "health": 100 }  # <-- dictionary
To achieve the same behavior of creating a structure to store data from "nowhere" as in Js, we have to use a data type in Python called a Dictionary.

As you can see in the example above, a Dictionary is declared the same way as a JavaScript Object with key-value pairs. So... what's the difference?

Notation for Accessing Member Data

As JavaScript Objects are actual objects with each field is an object's attribute, we have 2 ways of accessing its data, the Dot Notation and the Bracket Notation:
// JavaScript
player = {
    "health": 100,
    "power": 15,
}

console.log(player.health);  // <-- Output: 100
console.log(player["power"]);  // <-- Output: 15
In Python, this is not the case since fields of a Dictionary are not attributes of the dict object itself. The Bracket Notation is the only way to access the data:
# Python
player = {
    "health": 100,
    "power": 15
}

print(player["health"])  # <-- Output: 100
print(player.power)  # <-- AttributeError: 'dict' object has no attribute 'power'

Objects can contain Methods

An object, regardless of which language, can encapsulate both data and method. This is not an exception in  JavaScript. As a Dictionary in Python is an object of a predefined class named dict, we cannot (naturally) add methods to it.
// JavaScript
player = {
    health: 100,
    
    get_attacked: function() {
        this.health--;
    },

    heal: function() {
        this.health++;
    }
}

player.get_attacked();  
console.log(player.health)  // <-- Output: 99
It is nearly impossible in Python to achieve the same functionality as the code snippet above without creating a class (we can use lambda expression but let's not discuss it here).

Both key and value of a Python Dictionary are evaluated

As you might notice from above, I create JavaScript Object from "nowhere" using 2 different notations interchangeably and they have the same effect.
// JavaScript
player1 = { health: 100 };
player2 = { "health": 90 };
console.log(player1.health);  // Output: 100
console.log(player2.health);  // Output: 90
This is because Js only evaluates the value and keeps the key as a variable (a name) that holds the value. This is not the case in Python Dictionary where both key and value are evaluated. We can see that through the following example:
# Python
he = "health"
player = { 
    he: 100,
    "he": 'the string "he"'
}
print(player)  # Output: {'health': 100, 'he': 'the string "he"'}
You can notice that he (without quotes) is evaluated to its value: "health" which is the actual key while the key "he" (with quotes) is still "he". This Dictionary if written exactly as it is right now in JavaScript will cause overwritten of the "he" attribute with whichever value got assigned later because, in Js, "he" and he is considered to be the same key.
// JavaScript
let he = "health";
player = {
    he: 100,
    "he": 'the string "he"'
};
console.log(player);  // Output: { he: 'the string "he"' }
The general rule for Python Dictionary is that the key must be a hashable expression that can be evaluated a number (int, float...), string or even a tuple.
# Python
myDict = { }
myDict[1] = "one"
myDict["three"] = 3
myDict[(2, 4)] = "tuple of 2 and 4"
print(myDict)  # Output: {1: 'one', 'three': 3, (2, 4): 'tuple of 2 and 4'}

Difference #3: Package Manager (pip vs. npm)

This one is mostly for developers using the 2 languages for web programming.

Programming with JavaScript and Python nowadays involves a lot of dependencies which are packages providing us with well-written modules. These modules help us reuse pre-written codes to serve our programming tasks and save time.

The main 2 Package Managers and Installers for Js and Py are Node Package Manager (npm) and Python Package Index (PyPI or pip). They have certain differences from each other that I think are important to be aware of.

Installing and Saving Dependencies

The command we use in the console to install a certain package in npm is simply...
npm install [package-name] --save  # --save option is automatic for higher version of NPM
What the above command does are:
  • Download and install the said package into the node_modules folder
  • Add an entry of the dependency's name and version into the package.json file
However, the equivalent of pip does not do exactly that. The above task is separated into 2 commands.
The following one will install the package:
pip install [package-name]
and this one will export all the installed dependencies into a file:
pip freeze >> requirements.txt
This may produce more hassle for the users but it is the wai pip works. Do note that the equivalent of package.json in npm would be requirements.txt in pip.

Virtual/Local Environment

In JavaScript, each project has its owned package.json and node_modules folder. This acts as a local environment for that project that any dependencies got installed in a project folder will only exist for the said project (by default). In some case, we might want to avoid this default behavior and install a project globally, then, we need to run the install command with -g option:
npm install -g [package-name]
As for pip, the "-g" behavior above would be the default, thus, a dependency will always be installed globally. Pip itself does not have the mechanism for install a package locally, therefore, it raised the need for a tool called virtualenv. This tool creates a virtual environment for the project and allows the project to have its owned "global" scope. We can install this tool through pip:
pip install virtualenv
After installing virtualenv globally, whenever we are in the folder of a project, we would want to create a virtual environment...
virtualenv myEnv  # 'myEnv' is the name of the virtual environment
and activate it:
source myEnv/Scripts/activate  # 'myEnv' is the name of the virtual environment
At this point, you should see an indicator in your console that you are in a virtual environment:

From this point, any pip install will put the new dependency under the scope of myEnv and available only to this project.

Finally, to exit the virtual environment, we simply do:
deactivate

And there we go! Those are the noticeable differences between JavaScript and Python that I think worth bringing up as I was learning and working on a Python project.

I hope you enjoy reading!

Comments

Popular posts from this blog

Release 0.1b: Contributing a new feature... Why not?

Release 0.1a: My First Contribution

Release 0.2a: #good-first-issue - Make web app work offline!