Top Python 3.x Interview Questions You Must Know

author image Hirely
at 10 Jan, 2025

Question: What is the difference between Python 2.x and Python 3.x?

Answer:

Python 2.x and Python 3.x are two major versions of the Python programming language. Python 3.x was released to fix various design flaws and provide better support for modern programming practices, but this led to backward incompatibility with Python 2.x. Below are the key differences between Python 2.x and Python 3.x:


1. Print Statement vs. Print Function

  • Python 2.x: print is treated as a statement.

    print "Hello, World!"
  • Python 3.x: print is treated as a function and requires parentheses.

    print("Hello, World!")

2. Integer Division

  • Python 2.x: Division of integers results in an integer (floor division) when both operands are integers.

    3 / 2    # Output: 1

    To get a float result, you would need to explicitly convert one of the operands to a float.

    3 / float(2)    # Output: 1.5
  • Python 3.x: Division of integers results in a float by default.

    3 / 2    # Output: 1.5

    If you want integer division (floor division), use the // operator.

    3 // 2    # Output: 1

3. Unicode Handling

  • Python 2.x: Strings are treated as ASCII by default unless specified as Unicode with a u prefix.

    s = "hello"      # ASCII string
    u = u"hello"     # Unicode string
  • Python 3.x: Strings are treated as Unicode by default, and byte data is handled separately with a b prefix for byte strings.

    s = "hello"      # Unicode string
    b = b"hello"     # Byte string

4. Iterators and Generators

  • Python 2.x: Functions like range(), map(), and filter() return lists.

    range(5)    # Output: [0, 1, 2, 3, 4]
  • Python 3.x: These functions return iterators, which are more memory efficient, especially for large datasets.

    range(5)    # Output: range(0, 5) (an iterator object)

    To get a list in Python 3.x, you can explicitly convert the iterator into a list:

    list(range(5))    # Output: [0, 1, 2, 3, 4]

5. Exception Handling Syntax

  • Python 2.x: The except clause uses as or a comma.

    try:
        # some code
    except SomeError, e:
        # handle exception
  • Python 3.x: The except clause always uses as to bind the exception to a variable.

    try:
        # some code
    except SomeError as e:
        # handle exception

6. Input Handling

  • Python 2.x: The input() function evaluates the user input as Python code, and raw_input() is used to get a string input.

    x = raw_input("Enter something: ")  # String input
    x = input("Enter a number: ")  # Evaluates as Python code
  • Python 3.x: The input() function returns string input, and raw_input() has been removed.

    x = input("Enter something: ")  # Always returns a string

7. Standard Library Changes

  • Python 2.x: Many modules and functions in the standard library have different names and may not follow modern practices. For example, urllib and urllib2 were separate in Python 2.x.

  • Python 3.x: The standard library was reorganized and many modules were renamed or consolidated. For example, urllib in Python 3.x is more consistent, and urllib2 was merged into urllib.


8. Function Annotations

  • Python 2.x: Function annotations are not supported (except for some third-party libraries).

  • Python 3.x: Function annotations are supported and can be used to specify the type of parameters and return types.

    def greet(name: str) -> str:
        return "Hello " + name

9. Libraries and Third-Party Support

  • Python 2.x: As Python 2.x reached its end of life (EOL) on January 1, 2020, many third-party libraries have stopped supporting it, and new libraries are often built exclusively for Python 3.

  • Python 3.x: Python 3 is actively maintained and supported by the community. It is the recommended version for all new projects and for those migrating from Python 2.x.


10. Performance Improvements

  • Python 3.x has made numerous performance improvements over Python 2.x, including better memory handling, optimization of various functions, and enhancements to the garbage collection process. For many use cases, Python 3.x is faster than Python 2.x.

11. End of Life (EOL)

  • Python 2.x: Python 2 reached its official end of life (EOL) on January 1, 2020. This means it no longer receives updates, including security fixes, from the Python Software Foundation.
  • Python 3.x: Python 3.x is the future of the language and continues to receive new features, performance improvements, and security updates.

Summary of Key Differences:

FeaturePython 2.xPython 3.x
Printprint statementprint() function
Integer DivisionInteger division results in an integerInteger division results in a float
Unicode StringsASCII by default, use u for UnicodeUnicode by default
String Handlinginput() evaluates inputinput() returns string
IteratorsReturns listReturns iterator
Exception Syntaxexcept Exception, e:except Exception as e:
Standard LibraryDifferent module namesReorganized and renamed modules
Function AnnotationsNot supportedSupported
End of LifeJanuary 1, 2020 (no more support)Actively supported

Conclusion:

Python 3.x introduced many improvements and fixes over Python 2.x, making it the preferred choice for new projects. However, due to the backward incompatibility, migrating from Python 2.x to Python 3.x can require significant changes in code. Python 2.x reached its end of life in 2020, so it is advisable to switch to Python 3 for all new development and maintenance of existing projects.

Question: What are Python decorators?

Answer:

In Python, decorators are a way to modify or extend the behavior of a function or method without changing its source code. A decorator is essentially a function that wraps another function (or method), and allows additional functionality to be added to it before or after its execution.

Decorators are widely used in Python for various purposes, such as logging, authentication, authorization, caching, etc.


How Do Python Decorators Work?

A decorator is a higher-order function that takes a function as input and returns a new function that adds some kind of functionality to the original function.

Basic Syntax of a Decorator:

def decorator_function(original_function):
    def wrapper_function():
        # Code to execute before calling the original function
        print("Wrapper executed this before {}".format(original_function.__name__))
        
        # Call the original function
        return original_function()
    
    return wrapper_function

To apply this decorator to a function, you use the @decorator_name syntax above the function definition.

Example of a Simple Decorator:

def decorator_function(original_function):
    def wrapper_function():
        print("Wrapper executed before {}".format(original_function.__name__))
        return original_function()
    return wrapper_function

# Using the decorator
@decorator_function
def say_hello():
    print("Hello!")

say_hello()

Output:

Wrapper executed before say_hello
Hello!

In this example, @decorator_function is applied to the say_hello function. When say_hello() is called, the wrapper_function is executed first, and then it calls the original say_hello function.


Components of a Decorator:

  1. Outer Function: This is the decorator function that takes a function as input.
  2. Inner Function: This function wraps around the original function and can modify or extend its behavior.
  3. Returning the Inner Function: The decorator returns the inner function, which will be used in place of the original function.

Example with Arguments:

If the decorated function has parameters, the decorator should pass those parameters to the original function as well. This can be done using *args and **kwargs to handle any number of positional and keyword arguments.

def decorator_function(original_function):
    def wrapper_function(*args, **kwargs):
        print("Wrapper executed before {}".format(original_function.__name__))
        return original_function(*args, **kwargs)
    return wrapper_function

@decorator_function
def say_hello(name):
    print("Hello, {}!".format(name))

say_hello("Alice")

Output:

Wrapper executed before say_hello
Hello, Alice!

In this example, the decorator function now accepts any number of arguments (*args and **kwargs) and forwards them to the say_hello function.


Using Built-in Decorators:

Python has several built-in decorators that are commonly used, such as @staticmethod, @classmethod, and @property.

  1. @staticmethod:

    • It is used to define a method that doesn’t depend on class instance data.
    class MyClass:
        @staticmethod
        def say_hello():
            print("Hello from static method!")
  2. @classmethod:

    • It is used to define a method that operates on the class, not the instance. It takes the class as its first argument (cls) instead of the instance (self).
    class MyClass:
        @classmethod
        def greet(cls):
            print("Hello from class method!")
  3. @property:

    • It allows you to define a method as an attribute, so that it can be accessed like an attribute but executed as a method.
    class Circle:
        def __init__(self, radius):
            self._radius = radius
        
        @property
        def radius(self):
            return self._radius
        
        @property
        def area(self):
            return 3.1416 * self._radius * self._radius

Chaining Decorators:

You can apply multiple decorators to a single function by stacking them, with the bottom-most decorator applied first.

def decorator_one(func):
    def wrapper():
        print("Decorator One")
        func()
    return wrapper

def decorator_two(func):
    def wrapper():
        print("Decorator Two")
        func()
    return wrapper

@decorator_one
@decorator_two
def say_hello():
    print("Hello!")

say_hello()

Output:

Decorator One
Decorator Two
Hello!

In this case, say_hello() is first passed through decorator_two, then the result of that is passed to decorator_one.


Practical Use Cases for Decorators:

  1. Logging:

    • You can use decorators to log function calls, execution times, or results.
    def log_function_call(func):
        def wrapper(*args, **kwargs):
            print(f"Calling function {func.__name__} with arguments {args}, {kwargs}")
            result = func(*args, **kwargs)
            print(f"{func.__name__} returned {result}")
            return result
        return wrapper
    
    @log_function_call
    def add(a, b):
        return a + b
  2. Authorization:

    • You can use decorators to check if the user has the proper permissions before running a function.
    def check_permissions(func):
        def wrapper(*args, **kwargs):
            if not has_permission():
                raise PermissionError("You don't have permission to perform this action")
            return func(*args, **kwargs)
        return wrapper
  3. Caching:

    • You can cache results of expensive function calls using decorators, which can help improve performance.
    def cache_results(func):
        cache = {}
        def wrapper(*args):
            if args not in cache:
                cache[args] = func(*args)
            return cache[args]
        return wrapper

Summary:

  • Python decorators are a powerful feature that allows you to add functionality to functions or methods without modifying their actual code.
  • They work by defining a function that takes another function as input and returns a new function (the wrapped function).
  • Decorators are often used for logging, access control, memoization (caching), and modifying or enhancing functions in a modular way.
  • Decorators are a great tool for adhering to the DRY principle (Don’t Repeat Yourself), as they allow you to apply reusable behavior to multiple functions.

Read More

If you can’t get enough from this article, Aihirely has plenty more related information, such as Python 3.x interview questions, Python 3.x interview experiences, and details about various Python 3.x job positions. [Click here](https://www.aihirely.com/tag/Python 3.x) to check it out.

Related Posts

Trace Job opportunities

Hirely, your exclusive interview companion, empowers your competence and facilitates your interviews.

Get Started Now