0% found this document useful (0 votes)
55 views2 pages

Python Inheritance Exercises Explained

The document contains a series of Python questions with multiple-choice answers and explanations. It covers topics such as class attribute naming conventions, thread management, and the differences between `__repr__()` and `__str__()` methods. Each question is designed to test knowledge of Python programming concepts and best practices.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
55 views2 pages

Python Inheritance Exercises Explained

The document contains a series of Python questions with multiple-choice answers and explanations. It covers topics such as class attribute naming conventions, thread management, and the differences between `__repr__()` and `__str__()` methods. Each question is designed to test knowledge of Python programming concepts and best practices.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

# Python Questions with Answers and Explanations

---

### **Question 1 of 30**


**Problem**:
You need to define a Python class named Widget in your application with an
attribute named `value`, a fairly common name. In which of the scenarios below, is
it better to rename `[Link]` to `self.__value` (with a double underscore)?

**Choices**:
- **A**: Widget is defined as part of a public API, and we do not want any class
methods of Widget to access value.
- **B**: The widget is internal to your application and is the base class of a
diamond-shaped inheritance hierarchy, and we do not want derived class methods to
access value.
- **C**: The widget is internal to your application, and we do not want any class
methods of the Widget class to access value.
- **D**: The widget is internal to your application and is the base class of an
inheritance hierarchy, and we do not want derived class methods to access value.
- **E**: Widget is defined as part of a public API, and the clients of this API are
expected to subclass Widget in their own inheritance hierarchies. We do not want
methods of these subclasses to access value.

**Answer**: **D**
**Explanation**: Using `__value` invokes name mangling, which ensures that the
attribute is harder to access or override accidentally in derived classes. This is
particularly useful in inheritance hierarchies to protect the attribute.

---

### **Question 2 of 30**


**Problem**:
You are working on a Python 3 program that uses threading. The code snippet
schedules five threads every 10 seconds. If you want tighter control over the
number of threads, what would you do?

**Choices**:
- **A**: Use multiple schedulers and make them run serially.
- **B**: Use a thread pool.
- **C**: None is correct.
- **D**: Use only [Link] that will queue relevant threads as and when
added.

**Answer**: **B**
**Explanation**: A thread pool allows you to control the number of threads,
ensuring efficient resource usage while preventing excessive thread creation.

---

### **Question 3 of 30**


**Problem**:
What is the difference between the implementations of the methods `__repr__()` and
`__str__()` in a user-defined class in Python?

**Choices**:
- **A**: If we do not implement the `__str__()` function, then a call to `str()` on
an object invokes `__repr__()`.
- **B**: An invocation of `__str__()` returns a user-friendly printable string that
can also be used by a debugger to reconstruct a representation of the original
object.
- **C**: A call to `repr()` invokes both `__repr__()` and `__str__()`, whereas a
call to `str()` invokes just `__str__()`.
- **D**: An invocation of `__repr__()` returns a developer-friendly printable
string that can be used by a debugger to reconstruct a representation of the
original object.
- **E**: If we do not implement `__repr__()`, then a call to `repr()` on an object
invokes `__str__()`.

**Answer**: **A, B, D**


**Explanation**:
- `__repr__()` is meant for developers and returns an unambiguous string that can
recreate the object.
- `__str__()` is for end-users, providing a readable or printable representation.
- If `__str__()` is missing, Python falls back to `__repr__()`.

---

... (content continues for Questions 4 through 30)

Common questions

Powered by AI

The `__repr__()` and `__str__()` methods serve different purposes in Python classes. The `__repr__()` method is intended for developers; it returns an unambiguous string that is useful for debugging and can ideally recreate the object it represents. In contrast, the `__str__()` method is aimed at end-users, providing a readable or user-friendly string representation of the object. If `__str__()` is not defined, Python defaults to `__repr__()` for `str()` calls, ensuring that there is always some form of string representation for an object .

Python's fallback mechanism between `__str__()` and `__repr__()` ensures that there is always a string representation of an object available. If the `__str__()` method is not implemented, Python automatically falls back to using `__repr__()` for `str()` calls. Meanwhile, the `repr()` function always uses `__repr__()`. This mechanism guarantees that objects have a way to be represented as strings, which is essential for debugging and logging purposes, making it straightforward for developers to view objects' states regardless of the presence of a specific `__str__()` implementation .

Python uses the `__repr__()` method instead of the `__str__()` method when the `__str__()` method is not implemented in a class. In such cases, calls to `str()` on an object will invoke `__repr__()`. Additionally, `repr()` always invokes `__repr__()` to produce an unambiguous string representation of an object that can be used for debugging and potentially for recreating the object. This default behavior ensures that Python always has a way to represent objects as strings for debugging purposes .

A thread pool contributes to efficient resource utilization by limiting the number of active threads at any given time. This prevents the system from being overwhelmed by too many concurrent threads, which can lead to increased context switching and resource contention. By managing a set number of threads, a thread pool ensures that only a predefined number of tasks are processed concurrently, which optimizes CPU usage and system performance while avoiding the creation of unnecessary threads .

Name mangling is advisable when the base class is part of an internal application, forming a diamond-shaped inheritance hierarchy, where you do not want derived class methods to have direct access to certain attributes, specifically to avoid accidental overrides or access. Using a double underscore for an attribute (e.g., `self.__value`) invokes name mangling, making the attribute less accessible from subclasses, thus maintaining encapsulation and integrity of the attribute within inheritance hierarchies .

Allowing subclasses to access a base class's attributes directly in Python can lead to several implications. It may break encapsulation principles by exposing internal state to direct manipulation from subclasses, potentially causing invalid states and unexpected behaviors. This direct access can also make maintenance and debugging more challenging, as changes to a base class's attributes could inadvertently affect subclass behavior. Furthermore, it may introduce tight coupling between classes, reducing reusability and flexibility of the base class to evolve independently without affecting derived classes .

Name mangling provides the advantage of protecting class attributes from being accidentally modified or accessed by subclasses in a Python inheritance hierarchy, especially in a complex diamond-shaped structure. By prefixing an attribute with a double underscore, Python automatically mangles the name with the class name, making it difficult for subclasses to access or override the attribute directly. This helps maintain the integrity of encapsulated data within an inheritance structure, reducing potential conflicts and errors caused by accidental interaction with base class attributes .

Python developers might prefer using thread pools over individual thread creation to effectively manage concurrency due to several reasons. Thread pools allow for reusing threads, which reduces the overhead associated with creating and destroying threads repeatedly. They also help in controlling the number of active threads, preventing resource exhaustion and ensuring system stability. Furthermore, thread pools provide a more scalable and efficient way to handle a large number of concurrent tasks by queuing them and executing within a bounded number of threads, maximizing CPU utilization while avoiding the performance drawbacks of excessive threading .

Name mangling affects the accessibility of class attributes in derived classes by changing the attribute name to include the class name, effectively making it private to its class scope. For example, `self.__value` becomes `_ClassName__value`. This alteration complicates direct access to the attribute from subclasses, reducing the risk of unintentional modification or overriding. Thus, name mangling enhances data hiding and adheres to encapsulation principles, safeguarding critical attributes from interference in complex inheritance structures .

Using a double underscore prefix for a class attribute is considered a form of encapsulation in Python because it invokes name mangling. This technique alters the attribute name in a way that makes it less accessible to other classes, specifically affecting inheritance hierarchies. Name mangling changes the name of the attribute to include the class name, which helps prevent direct access to private attributes from outside the class, thereby enhancing data protection and preserving the encapsulation principle .

You might also like