Python vs Java: Understand Object Oriented Programming

Python vs Java: Understand Object Oriented Programming

This article compares and contrasts object-oriented programming support in Python vs Java. By the end, you’ll be able to apply your knowledge of object-oriented programming to Python, understand how to reinterpret your understanding of Java objects to Python, and use objects in a Pythonic way.

Java programmers making a move to Python often struggle with Python’s approach to object-oriented programming (OOP). The approach to working with objects, variable types, and other language capabilities taken by Python vs Java are quite different. It can make switching between both languages very confusing.

Over the course of this article, you’ll:

  • Build a basic class in both Java and Python
  • Explore how object attributes work in Python vs Java
  • Compare and contrast Java methods and Python functions
  • Discover inheritance and polymorphism mechanisms in both languages
  • Investigate reflection across Python vs Java
  • Apply everything in a complete class implementation in both languages

This article isn’t a primer on object-oriented programming. Rather, it compares object-oriented features and principles of Python vs Java. Readers should have good knowledge of Java, and also be familiar with coding Python.

Table of Contents

  • Sample Classes in Python vs Java
  • Object Attributes
    Declaration and InitializationPublic and PrivateAccess Controlself and this* Methods and Functions
  • Inheritance and Polymorphism
    InheritanceTypes and PolymorphismDefault MethodsOperator Overloading* Reflection
    Examining an Object’s TypeExamining an Object’s AttributesCalling Methods Through Reflection* Conclusion
Sample Classes in Python vs Java

To begin, you’ll implement the same small class in both Python and Java to illustrate the differences between them. You’ll make modifications to them as the article progresses.

First, assume you have the following Car class definition in Java:

public class Car {
    private String color;
    private String model;
    private int year;
    public Car(String color, String model, int year) {
        this.color = color;
        this.model = model;
        this.year = year;
    }
    public String getColor() {
        return color;
    }
    public String getModel() {
        return model;
    }
    public int getYear() {
        return year;
    }
}

Java classes are defined in files with the same name as the class. So, you have to save this class in a file named Car.java. Only one class can be defined in each file.

A similar small Car class is written in Python as follows:

class Car:
    def __init__(self, color, model, year):
        self.color = color
        self.model = model
        self.year = year

In Python you can declare a class anywhere, in any file, at any time. Save this class in the file car.py.

Using these classes as your base, you can explore the basic components of classes and objects.

Object Attributes

All object oriented languages have some way to store data about the object. In **Java **and Python, data is stored in attributes, which are variables associated with specific objects.

One of the most significant differences between Python vs Java is how they define and manage class and object attributes. Some of these differences come from constraints imposed by the languages, while others come from best practices.

Declaration and Initialization

In Java, you declare attributes in the class body, outside of any methods, with a definite type. You must define class attributes before they are used:

public class Car {
    private String color;
    private String model;
    private int year;

In Python, you both declare and define attributes inside the class <strong>init</strong>(), which is the equivalent of Java’s constructor:

def __init__(self, color, model, year):
    self.color = color
    self.model = model
    self.year = year

By prefixing the variable names with self, you tell Python these are attributes. Each instance of the class will have a copy. All variables in Python are loosely typed, and these attributes are no exception.

You can also create instance variables outside of .<strong>init</strong>(), but it’s not a best practice as their scope is often confusing. If not used properly, instance variables created outside of .__init__() can lead to subtle bugs that are hard to find. For example, you can add a new attribute .wheels to a Car object like this:

>>> import car
>>> my_car = car.Car("yellow", "beetle", 1967)
>>> print(f"My car is {my_car.color}")
My car is yellow
>>> my_car.wheels = 5
>>> print(f"Wheels: {my_car.wheels}")
Wheels: 5

However, if you forget the my_car.wheels = 5 on line 6, then Python displays an error:

>>> import car
>>> my_car = car.Car("yellow", "beetle", 1967)
>>> print(f"My car is {my_car.color}")
My car is yellow
>>> print(f"Wheels: {my_car.wheels}")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute 'wheels'

In Python, when you declare a variable outside of a method, it’s treated as a class variable. Update the Car class as follows:

class Car:
    wheels = 0
    def __init__(self, color, model, year):
        self.color = color
        self.model = model
        self.year = year

This changes how you use the variable wheels. Instead of referring to it using an object, you refer to it using the class name:

>>> import car
>>> my_car = car.Car("yellow", "beetle", 1967)
>>> print(f"My car is {my_car.color}")
My car is yellow
>>> print(f"It has {car.Car.wheels} wheels")
It has 0 wheels
>>> print(f"It has {my_car.wheels} wheels")
It has 0 wheels

Note: In Python, you refer to a class variable using the following syntax:

  1. The name of the file containing the class, without the .py extension
  2. A dot
  3. The name of the class
  4. A dot
  5. The name of the variable

Since you saved the Car class in the file car.py, you refer to the class variable wheels on line 6 as car.Car.wheels.

You can refer to my<em>car.wheels or car.Car.wheels, but be careful. Changing the value of the instance variable my</em>car.wheels will not change the value of the class variable car.Car.wheels:

>>> from car import *
>>> my_car = car.Car("yellow", "Beetle", "1966")
>>> my_other_car = car.Car("red", "corvette", "1999")
>>> print(f"My car is {my_car.color}")
My car is yellow
>>> print(f"It has {my_car.wheels} wheels")
It has 0 wheels
>>> print(f"My other car is {my_other_car.color}")
My other car is red
>>> print(f"It has {my_other_car.wheels} wheels")
It has 0 wheels
>>> # Change the class variable value
... car.Car.wheels = 4
>>> print(f"My car has {my_car.wheels} wheels")
My car has 4 wheels
>>> print(f"My other car has {my_other_car.wheels} wheels")
My other car has 4 wheels
>>> # Change the instance variable value for my_car
... my_car.wheels = 5
>>> print(f"My car has {my_car.wheels} wheels")
My car has 5 wheels
>>> print(f"My other car has {my_other_car.wheels} wheels")
My other car has 4 wheels

You define two Car objects on lines 2 and 3:

  1. my_car
  2. my_other_car

At first, both of them have zero wheels. When you set the class variable using car.Car.wheels = 4 on line 16, both objects now have four wheels. However, when you set the instance variable using my_car.wheels = 5 on line 24, only that object is affected.

This means that there are now two different copies of the wheels attribute:

  1. A class variable that applies to all Car objects
  2. A specific instance variable applicable to the my_car object only

It isn’t difficult to accidentally refer to the wrong one and introduce subtle bugs.

Java’s equivalent to a class attribute is a static attribute:

public class Car {
    private String color;
    private String model;
    private int year;
    private static int wheels;

    public Car(String color, String model, int year) {
        this.color = color;
        this.model = model;
        this.year = year;
    }

    public static int getWheels() {
        return wheels;
    }

    public static void setWheels(int count) {
        wheels = count;
    }
}

Normally, you refer to static variables using the Java class name. You can refer to a static variable through a class instance like Python, but it’s not a best practice.

Your Java class is getting long. One of the reasons why Java is more verbose than Python is the notion of public and private methods and attributes.

Public and Private

Java controls access to methods and attributes by differentiating between public data and private data.

In Java, it is expected that attributes are declared as private, or protected if subclasses need direct access to them. This limits access to these attributes from code outside the class. To provide access to private attributes, you declare public methods which set and retrieve data in a controlled manner (more on that later).

Recall from your Java class above that the color variable was declared as private. Therefore, this Java code will show a compilation error at the highlighted line:

Car myCar = new Car("blue", "Ford", 1972);

// Paint the car
myCar.color = "red";

If you don’t specify an access level, then the attribute defaults to package protected, which limits access to classes in the same package. You have to mark the attribute as public if you want this code to work.

However, declaring public attributes is not considered a best practice in Java. You’re expected to declare attributes as private, and use public access methods, such as the .getColor() and .getModel() shown in the code.

Python doesn’t have the same notion of private or protected data that Java does. Everything in Python is public. This code works with your existing Python class just fine:

>>> my_car = car.Car("blue", "Ford", 1972)

>>> # Paint the car
... my_car.color = "red"

Instead of private, Python has a notion of a non-public instance variable. Any variable which starts with an underscore character is defined to be non-public. This naming convention makes it harder to access a variable, but it’s only a naming convention, and you can still access the variable directly.

Add the following line to your Python Car class:

class Car:

    wheels = 0

    def __init__(self, color, model, year):
        self.color = color
        self.model = model
        self.year = year
        self._cupholders = 6

You can access the ._cupholders variable directly:

>>> import car
>>> my_car = car.Car("yellow", "Beetle", "1969")
>>> print(f"It was built in {my_car.year}")
It was built in 1969
>>> my_car.year = 1966
>>> print(f"It was built in {my_car.year}")
It was built in 1966
>>> print(f"It has {my_car._cupholders} cupholders.")
It has 6 cupholders.

Python lets you access ._cupholders, but IDEs such as VS Code may issue a warning through linters that support PEP 8.

Here’s the code in VS Code, with a warning highlighted and displayed:

Python further recognizes using double underscore characters in front of a variable to conceal an attribute in Python. When Python sees a double underscore variable, it changes the variable name internally to make it difficult to access directly. This mechanism avoids accidents but still doesn’t make data impossible to access.

To show this mechanism in action, change the Python Car class again:

class Car:

    wheels = 0

    def __init__(self, color, model, year):
        self.color = color
        self.model = model
        self.year = year
        self.__cupholders = 6

Now, when you try to access the .__cupholders variable, you see the following error:

>>> import car
>>> my_car = car.Car("yellow", "Beetle", "1969")
>>> print(f"It was built in {my_car.year}")
It was built in 1969
>>> my_car.year = 1966
>>> print(f"It was built in {my_car.year}")
It was built in 1966
>>> print(f"It has {my_car.__cupholders} cupholders.")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute '__cupholders'

So why doesn’t the .__cupholders attribute exist?

When Python sees an attribute with double underscores, it changes the attribute by prefixing the original name of the attribute with an underscore, followed by the class name. To use the attribute directly, you need to change the name you use as well:

>>> print(f"It has {my_car._Car__cupholders} cupholders")
It has 6 cupholders

When you use double underscores to conceal an attribute from the user, Python changes the name in a well-documented manner. This means that a determined developer can still access the attribute directly.

So if your Java attributes are declared private, and your Python attributes are prefaced with double underscores, then how do you provide and control access to the data they store?

Access Control

In Java, you access private attributes using setters and getters. To allow users to paint their cars, add the following code to your Java class:

public String getColor() {
    return color;
}

public void setColor(String color) {
    this.color = color;
}

Since .getColor() and .setColor() are public, anyone can call them to change or retrieve the car’s color. Java’s best practices of using private attributes accessed with public getters and setters is one of the reasons why Java code tends to be more verbose than Python.

As you saw above, you access attributes directly in Python. Since everything is public, you can access anything at any time from anywhere. You set and get attribute values directly by referring to their names. You can even delete attributes in Python, which isn’t possible in Java:

>>> my_car = Car("yellow", "beetle", 1969)
>>> print(f"My car was built in {my_car.year}")
My car was built in 1969
>>> my_car.year = 1966
>>> print(f"It was built in {my_car.year}")
It was built in 1966
>>> del my_car.year
>>> print(f"It was built in {my_car.year}")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute 'year'

However, there are times you may want to control access to an attribute. In that case, you can use Python properties.

In Python, properties provide controllable access to class attributes using Python decorator syntax. Properties allow functions to be declared in Python classes that are analogous to Java getter and setter methods, with the added bonus of allowing you to delete attributes as well.

You can see how properties work by adding one to your Car class:

class Car:
    def __init__(self, color, model, year):
        self.color = color
        self.model = model
        self.year = year
        self._voltage = 12
    @property
    def voltage(self):
        return self._voltage

    @voltage.setter
    def voltage(self, volts):
        print("Warning: this can cause problems!")
        self._voltage = volts

    @voltage.deleter
    def voltage(self):
        print("Warning: the radio will stop working!")
        del self._voltage

Here, you expand the notion of the Car to include electric vehicles. You declare the ._voltage attribute to hold the battery voltage on line 6.

To provide controlled access, you define a function called voltage() to return the private value on lines 9 and 10. By using the @property decoration, you mark it as a getter that anyone can access directly.

Similarly, you define a setter function on lines 13 to 15, also called voltage(). However, you decorate this function with @voltage.setter. Lastly, you use @voltage.deleter to decorate a third voltage() on lines 18 to 20, which allows controlled deletion of the attribute.

The names of the decorated functions are all the same, indicating they control access to the same attribute. The function names also become the name of the attribute you use to access the value. Here’s how these properties work in practice:

>>> from car import *
>>> my_car = Car("yellow", "beetle", 1969)
>>> print(f"My car uses {my_car.voltage} volts")
My car uses 12 volts
>>> my_car.voltage = 6
Warning: this can cause problems!
>>> print(f"My car now uses {my_car.voltage} volts")
My car now uses 6 volts
>>> del my_car.voltage
Warning: the radio will stop working!

Note that you use .voltage in the highlighted lines above, not ._voltage. This tells Python to use the property functions you defined:

  • When you print the value of my_car.voltage on line 4, Python calls .voltage() decorated with @property.
  • When you assign a value to my_car.voltage on line 7, Python calls .voltage() decorated with @voltage.setter.
  • When you delete my_car.voltage on line 13, Python calls .voltage() decorated with @voltage.deleter.

The @property, @.setter, and @.deleter decorations make it possible to control access to attributes without requiring users to use different methods. You can even make attributes appear to be read-only properties by omitting the @.setter and @.deleter decorated functions.

self and this

In Java, a class refers to itself with the this reference:

public void setColor(String color) {
    this.color = color;
}

this is implicit in Java code: it doesn’t normally need to be written, unless there may be confusion between two variables with the same name.

You can write the same setter this way:

public void setColor(String newColor) {
    color = newColor;
}

Since Car has an attribute named .color, and there isn’t another variable in scope with the same name, a reference to that name works. We used this in the first example to differentiate between the attribute and parameter both named color.

In Python, the keyword self serves a similar purpose. It’s how you refer to member variables, but unlike Java’s this, it’s required if you want to create or refer to a member attribute:

class Car:
    def __init__(self, color, model, year):
        self.color = color
        self.model = model
        self.year = year
        self._voltage = 12

    @property
    def voltage(self):
        return self._voltage

Python requires each self in the code above. Each one either creates or refers to the attributes. If you omit them, then Python will create a local variable instead of an attribute.

The difference between how you use self and this in Python and Java is due to underlying differences between the two languages and how they name variables and attributes.

Methods and Functions

This difference between Python vs Java is, simply put, that Python has functions, and Java doesn’t.

In Python, the following code is perfectly fine (and very common):

>>> def say_hi():
...     print("Hi!")
... 
>>> say_hi()
Hi!

You can call say_hi() from anywhere it’s visible. This function has no reference to self, which indicates that it’s a global function, not a class function. It can’t alter or store any data in any classes but can use local and global variables.

In contrast, every line of Java code you write belongs to a class. Functions can’t exist outside of a class, and by definition, all Java functions are methods. In Java, the closest you can get to a pure function is by using a static method:

public class Utils {
    static void SayHi() {
        System.out.println("Hi!");
    }
}

Utils.SayHi() is callable from anywhere without first creating an instance of Utils. Since you can call SayHi() without creating an object first, the this reference doesn’t exist. However, this is still not a function in the sense that say_hi() is in Python.

Inheritance and Polymorphism

Inheritance and polymorphism are two fundamental concepts in object-oriented programming.

Inheritance allows objects to derive attributes and functionality from other objects, creating a hierarchy moving from more general objects to more specific. For example, a Car and a Boat are both specific types of Vehicles. Objects can inherit their behavior from a single parent object or multiple parent objects, and are referred to as child objects when they do.

Polymorphism allows two or more objects to behave like one another, which allows them to be used interchangeably. For example, if a method or function knows how to paint a Vehicle object, then it can also paint a Car or Boat object, since they inherit their data and behavior from the Vehicle.

These fundamental OOP concepts are implemented quite differently in Python vs Java.

Inheritance

Python supports multiple inheritance, or creating classes that inherit behavior from more than one parent class.

To see how this works, update the Car class by breaking it into two categories, one for vehicles, and one for devices that use electricity:

class Vehicle:
    def __init__(self, color, model):
        self.color = color
        self.model = model

class Device:
    def __init__(self):
        self._voltage = 12

class Car(Vehicle, Device):
    def __init__(self, color, model, year):
        Vehicle.__init__(self, color, model)
        Device.__init__(self)
        self.year = year

    @property
    def voltage(self):
        return self._voltage

    @voltage.setter
    def voltage(self, volts):
        print("Warning: this can cause problems!")
        self._voltage = volts

    @voltage.deleter
    def voltage(self):
        print("Warning: the radio will stop working!")
        del self._voltage

A Vehicle is defined as having .color and .model attributes. Then, a Device is defined to have a ._voltage attribute. Since the original Car object had these three attributes, it can be redefined to inherit both the Vehicle and Device classes. The color, model, and _voltage attributes will be part of the new Car class.

In the .__init__() for Car, you call the .__init__() methods for both of the parent classes to make sure everything is initialized properly. Once done, you can add any other functionality you want to your Car. In this case, you add a .year attribute specific to Car objects, and getter and setter methods for .voltage.

Functionally, the new Car class behaves as it always has. You create and use Car objects just as before:

>>> from car import *
>>> my_car = Car("yellow", "beetle", 1969)

>>> print(f"My car is {my_car.color}")
My car is yellow

>>> print(f"My car uses {my_car.voltage} volts")
My car uses 12 volts

>>> my_car.voltage = 6
Warning: this can cause problems!

>>> print(f"My car now uses {my_car.voltage} volts")
My car now uses 6 volts

Java, on the other hand, only supports single inheritance, which means classes in Java can inherit data and behavior from only a single parent class. However, Java objects can inherit behavior from many different interfaces. Interfaces provide a group of related methods an object must implement, and allow multiple child classes to behave similarly.

To see this in action, split the Java Car class into a parent class and an interface:

public class Vehicle {

    private String color;
    private String model;

    public Vehicle(String color, String model) {
        this.color = color;
        this.model = model;
    }

    public String getColor() {
        return color;
    }

    public String getModel() {
        return model;
    }
}

public interface Device {
    int getVoltage();
}

public class Car extends Vehicle implements Device {

    private int voltage;
    private int year;

    public Car(String color, String model, int year) {
        super(color, model);
        this.year = year;
        this.voltage = 12;
    }

    @Override
    public int getVoltage() {
        return voltage;
    }

    public int getYear() {
        return year;
    }
}

Remember that each class and interface needs to live in its own file.

As you did with Python, you create a new class called Vehicle to hold the more general vehicle related data and functionality. However, to add the Device functionality, you need to create an interface instead. This interface defines a single method to return the voltage of the Device.

Redefining the Car class requires you to inherit from Vehicle using extend, and implement the Device interface using implements. In the constructor, you call the parent class constructor using the built-in super(). Since there is only one parent class, it can only refer to the Vehicle constructor. To implement the interface, you write getVoltage() using the @Override annotation.

Rather than getting code reuse from Device as Python did, Java requires you to implement the same functionality in every class that implements the interface. Interfaces only define the methods—they cannot define instance data or implementation details.

So why is this the case for Java? It all comes down to types.

Types and Polymorphism

Java’s strict type checking is what drives its interface design.

Every class and interface in Java is a type. Therefore, if two Java objects implement the same interface, then they are considered to be the same type with respect to that interface. This mechanism allows different classes to be used interchangeably, which is the definition of polymorphism.

You can implement device charging for your Java objects by creating a .charge() that takes a Device to charge. Any object that implements the Device interface can be passed to .charge(). This also means that classes that do not implement Device will generate a compilation error.

Create the following class in a file called Rhino.java:

public class Rhino {
}

Now you can create a new Main.java to implement .charge() and explore how Car and Rhino objects differ:

public class Main{
    public static void charge(Device device) {
       device.getVoltage();
    }

    public static void main(String[] args) throws Exception {
        Car car = new Car("yellow", "beetle", 1969);
        Rhino rhino = new Rhino();
        charge(car);
        charge(rhino);
    }
}

Here is what you should see when you try to build this code:

Information:2019-02-02 15:20 - Compilation completed with 
    1 error and 0 warnings in 4 s 395 ms
Main.java
Error:(43, 11) java: incompatible types: Rhino cannot be converted to Device

Since the Rhino class doesn’t implement the Device interface, it can’t be passed into .charge().

In contrast to Java’s strict variable typing, Python uses a concept called duck typing, which in basic terms means that if a variable “walks like a duck and quacks like a duck, then it’s a duck.” Instead of identifying objects by type, Python examines their behavior.

You can explore duck typing by implementing similar device charging capabilities for your Python Device class:

>>> def charge(device):
...     if hasattr(device, '_voltage'):
...         print(f"Charging a {device._voltage} volt device")
...     else:
...         print(f"I can't charge a {device.__class__.__name__}")
... 
>>> class Phone(Device):
...     pass
... 
>>> class Rhino:
...     pass
... 
>>> my_car = Car("yellow", "Beetle", "1966")
>>> my_phone = Phone()
>>> my_rhino = Rhino()

>>> charge(my_car)
Charging a 12 volt device
>>> charge(my_phone)
Charging a 12 volt device
>>> charge(my_rhino)
I can't charge a Rhino

charge() must check for the existence of the ._voltage attribute in the object it’s passed. Since the Device class defines this attribute, any class that inherits from it (such as Car and Phone) will have this attribute, and will therefore show they are charging properly. Classes that do not inherit from Device (like Rhino) may not have this attribute, and will not be able to charge (which is good, since charging rhinos can be dangerous).

Default Methods

All Java classes descend from the Object class, which contains a set of methods every other class inherits. Subclasses can either override them or keep the defaults. The Object class defines the following methods:

class Object {
    boolean equals(Object obj) { ... }    
    int hashCode() { ... }    
    String toString() { ... }    
}

By default, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-" target="_blank">equals()</a> compares the addresses of the current Object with a second Object passed in, and <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--" target="_blank">hashcode()</a> computes a unique identifier that also uses the address of the current Object. These methods are used in many different contexts in Java. For example, utility classes, such as collections that sort objects based on value, need both of them.

<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#toString--" target="_blank">toString()</a> returns a String representation of the Object. By default, this is the name of the class and the address. This method is called automatically when an Object is passed to a method that requires a String argument, such as System.out.println():

Car car = new Car("yellow", "Beetle", 1969);
System.out.println(car);

Running this code will use the default .toString() to show the car object:

[email protected]

Not very useful, right? You can improve this by overriding the default .toString(). Add this method to your Java Car class:

public String toString() {
    return "Car: " + getColor() + " : " + getModel() + " : " + getYear();
}

Now, when you run the same sample code, you’ll see the following:

Car: yellow : Beetle : 1969

Python provides similar functionality with a set of common dunder (short for “double underscore”) methods. Every Python class inherits these methods, and you can override them to modify their behavior.

For string representations of an object, Python provides __repr__() and __str__(), which you can learn about in Pythonic OOP String Conversion: __repr__ vs __str__. The unambiguous representation of an object is returned by __repr__(), while __str__() returns a human readable representation. These are roughly analogous to .hashcode() and .toString() in Java.

Like Java, Python provides default implementations of these dunder methods:

>>> my_car = Car("yellow", "Beetle", "1966")

>>> print(repr(my_car))
<car.Car object at 0x7fe4ca154f98>
>>> print(str(my_car))
<car.Car object at 0x7fe4ca154f98>

You can improve this output by overriding .__str__(), adding this to your Python Car class:

def __str__(self):
    return f'Car {self.color} : {self.model} : {self.year}'

This gives you a much nicer result:

>>> my_car = Car("yellow", "Beetle", "1966")

>>> print(repr(my_car))
<car.Car object at 0x7f09e9a7b630>
>>> print(str(my_car))
Car yellow : Beetle : 1966

Overriding the dunder method gave us a more readable representation of your Car. You may want to override the .__repr__() as well, as it is often useful for debugging.

Python offers a lot more dunder methods. Using dunder methods, you can define your object’s behavior during iteration, comparison, addition, or making an object callable directly, among other things.

Operator Overloading

Operator overloading refers to redefining how Python operators work when operating on user-defined objects. Python’s dunder methods allow you to implement operator overloading, something that Java doesn’t offer at all.

Modify your Python Car class with the following additional dunder methods:

class Car:
    def __init__(self, color, model, year):
        self.color = color
        self.model = model
        self.year = year

    def __str__(self):
        return f'Car {self.color} : {self.model} : {self.year}'

    def __eq__(self, other):
        return self.year == other.year

    def __lt__(self, other):
        return self.year < other.year

    def __add__(self, other):
        return Car(self.color + other.color, 
                   self.model + other.model, 
                   int(self.year) + int(other.year))

The table below shows the relationship between these dunder methods and the Python operators they represent:

When Python sees an expression containing objects, it calls any dunder methods defined that correspond to operators in the expression. The code below uses these new overloaded arithmetic operators on a couple of Car objects:

>>> my_car = Car("yellow", "Beetle", "1966")
>>> your_car = Car("red", "Corvette", "1967")

>>> print (my_car < your_car)
True
>>> print (my_car > your_car)
False
>>> print (my_car == your_car)
False
>>> print (my_car + your_car)
Car yellowred : BeetleCorvette : 3933 

There are many more operators you can overload using dunder methods. They offer a way to enrich your object’s behavior in a way that Java’s common base class default methods don’t.

Reflection

Reflection refers to examining an object or class from within the object or class. Both Java and Python offer ways to explore and examine the attributes and methods in a class.

Examining an Object’s Type

Both languages have ways to test or check an object’s type.

In Python, you use type() to display the type of a variable, and isinstance() to determine if a given variable is an instance or child of a specific class:

>>> my_car = Car("yellow", "Beetle", "1966")

>>> print(type(my_car))
<class 'car.Car'>
>>> print(isinstance(my_car, Car))
True
>>> print(isinstance(my_car, Device))
True

In Java, you query the object for its type using .getClass(), and use the instanceof operator to check for a specific class:

Car car = new Car("yellow", "beetle", 1969);

System.out.println(car.getClass());
System.out.println(car instanceof Car);

This code outputs the following:

class com.realpython.Car
true

Examining an Object’s Attributes

In Python, you can view every attribute and function contained in any object (including all the dunder methods) using dir(). To get the specific details of a given attribute or function, use getattr():

>>> print(dir(my_car))
['_Car__cupholders', '__add__', '__class__', '__delattr__', '__dict__', 
 '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
 '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__',
 '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
 '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
 '_voltage', 'color', 'model', 'voltage', 'wheels', 'year']

>>> print(getattr(my_car, "__format__"))
<built-in method __format__ of Car object at 0x7fb4c10f5438>

Java has similar capabilities, but the language’s access control and type safety make it more complicated to retrieve.

.getFields() retrieves a list of all publicly accessible attributes. However, since none of the attributes of Car are public, this code returns an empty array:

Field[] fields = car.getClass().getFields();

Java treats attributes and methods as separate entities, so public methods are retrieved using .getDeclaredMethods(). Since public attributes will have a corresponding .get method, one way to discover if a class contains a specific property might look like this:

  • Use .getFields() to generate an array of all the methods.
  • Loop through all the methods returned:
  • For each method discovered, return true if the method:
    Begins with the word get OR accepts zero argumentsAND doesn’t return voidAND includes the name of the propertyOtherwise, return false.
    Here’s a quick-and-dirty example:
public static boolean getProperty(String name, Object object) throws Exception {
    Method[] declaredMethods = object.getClass().getDeclaredMethods();
    for (Method method : declaredMethods) {
        if (isGetter(method) && 
            method.getName().toUpperCase().contains(name.toUpperCase())) {
              return true;
        }
    }
    return false;
}
// Helper function to get if the method is a getter method
public static boolean isGetter(Method method) {
    if ((method.getName().startsWith("get") || 
         method.getParameterCount() == 0 ) && 
        !method.getReturnType().equals(void.class)) {
          return true;
    }
    return false;
}

getProperty() is your entry point. Call this with the name of an attribute and an object. It returns true if the property is found, and false if not.

Calling Methods Through Reflection

Both Java and Python provide mechanisms to call methods through reflection.

In the Java example above, instead of simply returning true if the property was found, you could call the method directly. Recall that getDeclaredMethods() returns an array of Method objects. The Method object itself has a method called .invoke(), which will call the Method. Instead of returning true when the correct method is found on line 7 above, you can return method.invoke(object) instead.

This capability exists in Python as well. However, since Python doesn’t differentiate between functions and attributes, you have to look specifically for entries that are callable:

>>> for method_name in dir(my_car):
...     if callable(getattr(my_car, method_name)):
...         print(method_name)
... 
__add__
__class__
__delattr__
__dir__
__eq__
__format__
__ge__
__getattribute__
__gt__
__init__
__init_subclass__
__le__
__lt__
__ne__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__

Python methods are simpler to manage and call than in Java. Adding the () operator (and any required arguments) is all you need to do.

The code below will find an object’s .__str__() and call it through reflection:

>>> for method_name in dir(my_car):
...     attr = getattr(my_car, method_name)
...     if callable(attr):
...         if method_name == '__str__':
...             print(attr())
... 
Car yellow : Beetle : 1966

Here, every attribute returned by dir() is checked. You get the actual attribute object using getattr(), and check if it’s a callable function using callable(). If so, you then check if its name is __str__(), and then call it.

Conclusion

Throughout the course of this article, you learned how object-oriented principles differ in Python vs Java. As you read, you:

  • Built a basic class in both Java and Python
  • Explored how object attributes work in Python vs Java
  • Compared and contrasted Java methods and Python functions
  • Discovered inheritance and polymorphism mechanisms in both languages
  • Investigated reflection across Python vs Java
  • Applied everything in a complete class implementation in both languages

Understanding the differences in Python vs Java when handling objects, and the syntax choices each language makes, will help you apply best practices and make your next project smoother.

Why I use Java? Why not C#, JavaScript, or Python?

Why I use Java? Why not C#, JavaScript, or Python?

In this article, you'll see some reasons to I learn and use Java, why not C#, JavaScript, or Python? and why Java is one of the best programming language

But why Java? Why not C#, JavaScript, or Python?

Well… there were a few well-thought reasons behind this decision.

The top 3 programming languages in the world right now are Python, Java, and JavaScript. Sorry my C# friends, C# is not in the top 3 list. I’ll talk about C# later in this post.

Why not JavaScript?

Yes, we can do object-oriented programming with JavaScript. But let’s be real. Object-oriented programming with JavaScript is a bit messy. JavaScript classes are not real classes. They are syntactic sugar over constructor functions. Also, in JavaScript, we don’t have access modifiers like public and private. Yes, we can achieve them using other ways and I’ve demonstrated that in my Object-oriented Programming with JavaScript course. But still, JavaScript is not the best language for object-oriented programming.

Why not Python?

Python is a great language. I love it! It’s free of clutter and is simple to use. It also has better support for OOP features. So, why didn’t I choose Python? Because based on my research, Python is often used among people in the data science community, rather than professional software engineers.

Yes, you we use Python to build desktop and mobile apps as well as backends. However, Python is not the language of choice for building mobile or desktop apps. These days, the majority of people are building mobile apps using cross-platform solutions such as React Native or Flutter. Others do native development in Java (for Android) or Swift (for iOS). The same applies to building desktop applications with Python. Python is not very well known for that reason.

Why not C#?

C# and Java are very similar in terms of syntax and they both have great support for OOP features. So, why didn’t I choose C# given that I have several C# courses?

Well… I looked at different sources to see the popularity of Java vs C#. Google Trends is a great resource. As you saw earlier in the post, Java is way more popular than C#. Does it mean it’s a better language? Well, it depends on _how _we define “better”.

What is better? A Ferrari or a truck? It depends on what you want to do. Ferrari is a super-fast car but it’s useless if you want to use it to move house. Programming languages are the same. There is no such thing as the best programming language. Every language has pros and cons. C++ is well known for its speed. Python is popular for its simple and clean syntax as well as tons of resources for machine learning.

Just because Java is more popular, it doesn’t mean it’s a better language than C#. In my opinion, C# is a more feature-rich language but Java was marketed better.

C# and Java have been rivals since day one. Many of the features we’ve had in C# for a long time were introduced in Java years later. Some features don’t exist to this day! For example, in Java, we don’t have optional parameters which are very handy. We have to overload a method. Ugly! Jave interfaces are also bad.

I personally prefer C#. But as I said, Java has had better marketing and that’s why it’s always been more popular than C#.

Why Java?

So, I chose Java because it’s used more widely than C# amongst professional software engineers. There are more Java developers out there than C# developers. Most universities and colleges also tend to teach Java, rather than C#.

Now, all that aside, C# and Java are very similar in terms of the syntax. Recently I posted this tweet asking my students if this is Java or C# code?

The reality is I wrote this code in IntelliJ (a popular Java IDE). But the code is valid C# and Java code. Someone argued that this is an over-simplified example and shouldn’t be used as a basis for comparison. That is true. But my whole point is that if you understand this code, you can perfectly take my Data Structures or Design Patterns courses.

What You Should Take Away

In my opinion, Java in the programming world, is like the English language in the world we live in. If Italian or Hindi is the only language you speak, you’re probably not gonna get very far ahead.

If you understand English, you have access to tons of valuable resources. Whether you want to learn programming, or painting, or piano, if you “understand” English, you have tons of resources in front of you. You don’t need to be fluent in speaking English. All you need is to just understand it.

It’s the same story with Java. There are tons of great programming books written and these books use Java. If you simply understand the Java syntax, you can take advantage of these amazing resources. You don’t need to become a Java developer and let go of your favorite language, whether it is C# or JavaScript or Python or PHP.

Python GUI Programming Projects using Tkinter and Python 3

Python GUI Programming Projects using Tkinter and Python 3

Python GUI Programming Projects using Tkinter and Python 3

Description
Learn Hands-On Python Programming By Creating Projects, GUIs and Graphics

Python is a dynamic modern object -oriented programming language
It is easy to learn and can be used to do a lot of things both big and small
Python is what is referred to as a high level language
Python is used in the industry for things like embedded software, web development, desktop applications, and even mobile apps!
SQL-Lite allows your applications to become even more powerful by storing, retrieving, and filtering through large data sets easily
If you want to learn to code, Python GUIs are the best way to start!

I designed this programming course to be easily understood by absolute beginners and young people. We start with basic Python programming concepts. Reinforce the same by developing Project and GUIs.

Why Python?

The Python coding language integrates well with other platforms – and runs on virtually all modern devices. If you’re new to coding, you can easily learn the basics in this fast and powerful coding environment. If you have experience with other computer languages, you’ll find Python simple and straightforward. This OSI-approved open-source language allows free use and distribution – even commercial distribution.

When and how do I start a career as a Python programmer?

In an independent third party survey, it has been revealed that the Python programming language is currently the most popular language for data scientists worldwide. This claim is substantiated by the Institute of Electrical and Electronic Engineers, which tracks programming languages by popularity. According to them, Python is the second most popular programming language this year for development on the web after Java.

Python Job Profiles
Software Engineer
Research Analyst
Data Analyst
Data Scientist
Software Developer
Python Salary

The median total pay for Python jobs in California, United States is $74,410, for a professional with one year of experience
Below are graphs depicting average Python salary by city
The first chart depicts average salary for a Python professional with one year of experience and the second chart depicts the average salaries by years of experience
Who Uses Python?

This course gives you a solid set of skills in one of today’s top programming languages. Today’s biggest companies (and smartest startups) use Python, including Google, Facebook, Instagram, Amazon, IBM, and NASA. Python is increasingly being used for scientific computations and data analysis
Take this course today and learn the skills you need to rub shoulders with today’s tech industry giants. Have fun, create and control intriguing and interactive Python GUIs, and enjoy a bright future! Best of Luck
Who is the target audience?

Anyone who wants to learn to code
For Complete Programming Beginners
For People New to Python
This course was designed for students with little to no programming experience
People interested in building Projects
Anyone looking to start with Python GUI development
Basic knowledge
Access to a computer
Download Python (FREE)
Should have an interest in programming
Interest in learning Python programming
Install Python 3.6 on your computer
What will you learn
Build Python Graphical User Interfaces(GUI) with Tkinter
Be able to use the in-built Python modules for their own projects
Use programming fundamentals to build a calculator
Use advanced Python concepts to code
Build Your GUI in Python programming
Use programming fundamentals to build a Project
Signup Login & Registration Programs
Quizzes
Assignments
Job Interview Preparation Questions
& Much More

Guide to Python Programming Language

Guide to Python Programming Language

Guide to Python Programming Language

Description
The course will lead you from beginning level to advance in Python Programming Language. You do not need any prior knowledge on Python or any programming language or even programming to join the course and become an expert on the topic.

The course is begin continuously developing by adding lectures regularly.

Please see the Promo and free sample video to get to know more.

Hope you will enjoy it.

Basic knowledge
An Enthusiast Mind
A Computer
Basic Knowledge To Use Computer
Internet Connection
What will you learn
Will Be Expert On Python Programming Language
Build Application On Python Programming Language