CCNA Oop Questions

63 of 138 questions · Page 2/2 · Oop topic · Answers revealed

76
MCQmedium

A programmer writes a class with a static method using @staticmethod. What is the primary purpose of using a static method instead of a class method or instance method?

A.To access class variables without creating an instance
B.To define a method that does not depend on class or instance state and behaves like a regular function but is namespaced inside the class
C.To allow the method to be overridden in subclasses
D.To enforce that the method cannot be called from an instance
AnswerB

Static methods are utility functions that belong to the class logically.

Why this answer

Option B is correct because a static method in Python, decorated with @staticmethod, does not receive an implicit first argument (neither self nor cls). This means it cannot access or modify class or instance state; it behaves exactly like a regular function but is organized within the class's namespace for logical grouping. The primary purpose is to encapsulate utility functions that are related to the class but do not depend on its data.

Exam trap

Python Institute often tests the distinction between static and class methods by making candidates think that @staticmethod is used to access class variables, when in fact that is the role of @classmethod, and the trap is that both decorators avoid the need for an instance, but only @classmethod receives the class reference.

How to eliminate wrong answers

Option A is wrong because accessing class variables without an instance is the purpose of a class method (decorated with @classmethod), which receives the class as the first argument (cls) and can read or write class-level attributes; a static method has no access to cls and cannot directly access class variables unless they are passed explicitly. Option C is wrong because static methods are not overridden in subclasses in the same way as instance or class methods; they are resolved at compile time (early binding) and do not participate in the normal method resolution order (MRO) for inheritance, so overriding them has no effect when called on the subclass. Option D is wrong because static methods can be called from an instance just fine; Python allows calling any method from an instance, and @staticmethod does not restrict this — the decorator only removes the implicit self parameter, not the ability to invoke it on an object.

77
MCQhard

A developer is working on a class hierarchy for geometric shapes. They have a base class Shape with an abstract method area(). They also have a mixin class Drawable that provides a method draw(). They want to create a class Rectangle that inherits from both Shape and Drawable. However, they encounter a TypeError when trying to instantiate Rectangle because the abstract method area() is not implemented. Which action should they take to resolve this?

A.Change the inheritance order to Drawable first, then Shape.
B.Implement the area() method in Rectangle.
C.Use a class decorator @abstractmethod for Rectangle.
D.Remove the abstract method from Shape by removing the @abstractmethod decorator.
AnswerB

All abstract methods must be implemented in a concrete subclass.

Why this answer

Option B is correct because the abstract method area() declared in the Shape base class must be implemented in any concrete subclass. In Python, a class that inherits from an ABC (Abstract Base Class) with an abstract method cannot be instantiated until that method is overridden. By providing an implementation of area() in Rectangle, the class becomes concrete and can be instantiated without raising a TypeError.

Exam trap

Python Institute often tests the misconception that changing inheritance order or using decorators can bypass the abstract method requirement, when in fact the only valid fix is to implement the abstract method in the concrete subclass.

How to eliminate wrong answers

Option A is wrong because changing the inheritance order does not affect the requirement to implement abstract methods; the TypeError arises from the missing implementation, not from the MRO. Option C is wrong because @abstractmethod is a decorator used to declare abstract methods, not a class decorator; applying it to Rectangle would make Rectangle itself abstract, not resolve the missing implementation. Option D is wrong because removing the @abstractmethod decorator from Shape would break the design contract, but more importantly, the question asks how to resolve the error while preserving the abstraction; removing the decorator eliminates the requirement but is not the intended solution for a proper class hierarchy.

78
Multi-Selectmedium

Which TWO of the following are true about the `__init__` method in Python?

Select 2 answers
A.It can be called manually.
B.It must return a value.
C.It can accept arguments.
D.It is not inherited.
E.It is called automatically when an instance is created.
AnswersC, E

Yes, arguments passed to the class are forwarded to `__init__` (except `self`).

Why this answer

Option C is correct because the `__init__` method can accept arguments, which are passed when creating an instance (e.g., `obj = MyClass(arg1, arg2)`). These arguments are forwarded to `__init__` by Python's instance creation machinery, allowing the method to initialize instance attributes with user-supplied values. This is a fundamental feature for parameterized object construction.

Exam trap

Python Institute often tests the misconception that `__init__` is the constructor or that it must return a value, when in fact `__new__` is the true constructor and `__init__` must return `None`.

79
MCQhard

A developer defines a class 'A' with a method 'm' that uses 'self.a'. Class 'B' inherits from 'A' and defines __init__ that sets 'self.a = 10'. An instance of B is created and method m is called. What is the output?

A.None
B.AttributeError
C.10
D.0
AnswerC

B's __init__ sets a to 10.

Why this answer

Option C is correct because when an instance of class B is created, its __init__ method sets self.a = 10. When method m (inherited from A) is called on that instance, self refers to the B instance, so self.a resolves to 10. Python's attribute lookup follows the instance's __dict__ first, finding the attribute set by B's __init__.

Exam trap

Python Institute often tests the misconception that inherited methods use the parent class's attribute values rather than the instance's own attributes, leading candidates to incorrectly expect an AttributeError or None.

How to eliminate wrong answers

Option A is wrong because self.a is not None; it is explicitly set to 10 in B.__init__, so the output is not None. Option B is wrong because there is no AttributeError; the attribute a exists on the instance due to B.__init__, so the lookup succeeds. Option D is wrong because self.a is not 0; it is assigned the integer 10, not a default or zero value.

80
MCQhard

When a class defines both __getattr__ and __getattribute__, which one is called when accessing an attribute that exists in the instance?

A.__getattr__ always overrides __getattribute__.
B.Both __getattr__ and __getattribute__ are called, in that order.
C.Only __getattr__ is called.
D.__getattribute__ is called, and __getattr__ is not called.
AnswerD

For existing attributes, __getattribute__ returns the value directly.

Why this answer

In Python, when both __getattr__ and __getattribute__ are defined in a class, __getattribute__ is always called first for every attribute access. If the attribute exists in the instance (e.g., in the instance dictionary or via a descriptor), __getattribute__ returns it directly, and __getattr__ is never invoked. __getattr__ is only called as a fallback when __getattribute__ raises an AttributeError. Therefore, for an existing attribute, only __getattribute__ runs, making option D correct.

Exam trap

Python Institute often tests the misconception that __getattr__ is the primary hook for attribute access, when in fact __getattribute__ is always called first and __getattr__ is only a fallback for missing attributes.

How to eliminate wrong answers

Option A is wrong because __getattr__ does not override __getattribute__; rather, __getattribute__ takes precedence for all accesses, and __getattr__ is only a fallback for missing attributes. Option B is wrong because both methods are not called in order for an existing attribute; __getattribute__ returns the value immediately, so __getattr__ is not invoked at all. Option C is wrong because __getattr__ is not called when the attribute exists; it is only triggered when __getattribute__ raises an AttributeError.

81
MCQeasy

A class MyClass defines __str__ and __repr__ methods. What is the purpose of __repr__?

A.To return a human-readable string for end users
B.To compare object equality
C.To return a hash value of the object
D.To return an unambiguous representation of the object, ideally for debugging
AnswerD

__repr__ should be unambiguous and, if possible, a valid Python expression.

Why this answer

The `__repr__` method is designed to return an unambiguous string representation of an object, ideally one that can be used to recreate the object or that clearly shows its internal state for debugging purposes. This is distinct from `__str__`, which targets end-user readability. The Python documentation explicitly states that `__repr__` should be unambiguous, while `__str__` should be readable.

Exam trap

The trap here is that candidates confuse `__repr__` with `__str__`, assuming both serve the same purpose, but Cisco specifically tests that `__repr__` is for unambiguous debugging output, not user-friendly display.

How to eliminate wrong answers

Option A is wrong because returning a human-readable string for end users is the purpose of `__str__`, not `__repr__`. Option B is wrong because comparing object equality is handled by the `__eq__` method, not `__repr__`. Option C is wrong because returning a hash value is the job of the `__hash__` method, which is used for dictionary keys and set membership, not `__repr__`.

82
MCQeasy

A developer wants to implement a read-only property for a class 'Temperature' that returns the temperature in Celsius but prevents external modification. Which code snippet correctly defines such a property?

A.class Temperature: @property def celsius(self): return self._celsius @celsius.setter def celsius(self, val): self._celsius = val
B.class Temperature: def __setattr__(self, name, val): if name == 'celsius': raise AttributeError
C.class Temperature: @property def celsius(self): return self._celsius
D.class Temperature: def __init__(self, c): self.celsius = c
AnswerC

This defines a getter only, making the property read-only.

Why this answer

Option C is correct because it defines a read-only property using the `@property` decorator with only a getter method. Without a setter, any attempt to assign a value to `celsius` will raise an `AttributeError`, making the property read-only. This is the standard Pythonic way to implement a read-only attribute.

Exam trap

Python Institute often tests the misconception that a property without a setter is still writable by default, or that overriding `__setattr__` is a valid alternative to `@property` for creating a read-only attribute, but the correct approach is to omit the setter decorator entirely.

How to eliminate wrong answers

Option A is wrong because it includes a setter method (`@celsius.setter`), which allows external modification of the property, contradicting the requirement for a read-only property. Option B is wrong because overriding `__setattr__` to raise an `AttributeError` for the name 'celsius' would prevent setting the attribute even inside the class (e.g., in `__init__`), breaking normal initialization and not providing a proper property interface. Option D is wrong because it simply assigns `celsius` as a regular instance attribute in `__init__`, which is fully writable and does not use the `@property` decorator, so it is not a read-only property.

83
MCQmedium

A team is developing a system that must handle different types of documents (PDF, Word, etc.). Each document type has a unique parsing method. To avoid massive conditional logic, which OOP concept should be applied?

A.Polymorphism
B.Encapsulation
C.Inheritance
D.Abstraction
AnswerA

Polymorphism enables each subclass to provide its own implementation of a common interface.

Why this answer

Polymorphism allows different document types (PDF, Word, etc.) to be treated uniformly through a common interface (e.g., a `parse()` method) while each class implements its own parsing logic. This eliminates the need for conditional statements (like `if type == 'PDF'`) because the correct method is resolved at runtime via dynamic dispatch, which is exactly what the team needs to avoid massive conditional logic.

Exam trap

Python Institute often tests the distinction between inheritance and polymorphism: candidates mistakenly think inheritance alone solves the problem, but without polymorphic method dispatch, you still need conditional logic to handle different types.

How to eliminate wrong answers

Option B (Encapsulation) is wrong because encapsulation focuses on bundling data and methods together and restricting direct access to internal state (e.g., via private attributes), not on avoiding conditional logic for different types. Option C (Inheritance) is wrong because while inheritance can share common code among document types, it does not by itself eliminate the need for conditionals; you would still need to check the object's type to call the correct parsing method without polymorphism. Option D (Abstraction) is wrong because abstraction hides implementation details behind an interface or abstract class, but without polymorphism you would still need conditional logic to decide which concrete implementation to invoke.

84
MCQmedium

Refer to the exhibit. Which of the following correctly shows the MRO of class D?

A.[D, B, C, A, object]
B.[D, A, B, C, object]
C.[D, B, A, C, object]
D.[D, C, B, A, object]
AnswerA

Correct MRO.

Why this answer

Option A is correct because Python's Method Resolution Order (MRO) for class D, which inherits from B and C (where B inherits from A and C inherits from A), follows the C3 linearization algorithm. The MRO is computed as D -> B -> C -> A -> object, ensuring that each class appears before its parents and that the order respects the local precedence order of D's bases (B before C).

Exam trap

Python Institute often tests the C3 linearization rule that the local precedence order (the order of bases in the class definition) must be preserved, so candidates mistakenly reorder bases based on inheritance depth rather than the explicit left-to-right order in the class statement.

How to eliminate wrong answers

Option B is wrong because it places A before B and C, violating the local precedence order of D's bases (B, C) and the C3 algorithm's requirement that a parent class appears after all its subclasses. Option C is wrong because it places A before C, which breaks the monotonicity of the C3 linearization; since C inherits from A, A must come after C. Option D is wrong because it places C before B, ignoring the explicit order of bases in class D's definition (B then C), which the C3 algorithm respects as the local precedence order.

85
Multi-Selecthard

Which TWO statements about Python's name mangling are correct?

Select 2 answers
A.Name mangling applies to all method names that start with a single underscore.
B.The mangled name format is _ClassName__attribute.
C.Name mangling prevents external code from accessing the attribute entirely.
D.Name mangling is applied to attributes that start with two underscores but do not end with two underscores.
E.Name mangling occurs at runtime.
AnswersB, D

Correct.

Why this answer

Option B is correct because Python's name mangling transforms an attribute name like `__attribute` defined in a class `MyClass` into `_MyClass__attribute`. This mechanism is specifically designed to avoid name clashes in subclasses, not to enforce privacy. The transformation is done by the compiler at definition time, not at runtime.

Exam trap

Python Institute often tests the misconception that name mangling provides true access control (like private in Java), when in fact it is only a name transformation that can be bypassed by using the mangled name directly.

86
MCQhard

A Python class 'Shape' defines an abstract method 'area'. Subclasses 'Circle' and 'Square' implement 'area'. A function 'calculate_area(shape)' expects a 'Shape' instance. Which principle ensures that the function works correctly without knowing the specific subclass?

A.Interface Segregation Principle
B.Liskov Substitution Principle
C.Single Responsibility Principle
D.Dependency Inversion Principle
AnswerB

LSP ensures that any subclass can replace the base class without breaking the function.

Why this answer

The Liskov Substitution Principle (LSP) states that objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program. In this scenario, 'calculate_area(shape)' accepts a 'Shape' instance, and because both 'Circle' and 'Square' are proper subtypes that honor the contract of the 'area' method, the function works correctly regardless of which subclass is passed. This is the core of LSP: substitutability without side effects.

Exam trap

Python Institute often tests LSP by presenting a scenario where a subclass overrides a method in a way that changes the expected behavior (e.g., raising an exception or returning a different type), and candidates mistakenly choose Interface Segregation or Dependency Inversion because they confuse 'substitutability' with 'abstraction' or 'interface design'.

How to eliminate wrong answers

Option A is wrong because the Interface Segregation Principle (ISP) focuses on splitting large interfaces into smaller, specific ones so that clients only depend on methods they use; it does not address the substitutability of subclasses in a function parameter. Option C is wrong because the Single Responsibility Principle (SRP) dictates that a class should have only one reason to change, which is unrelated to polymorphic behavior across subclasses. Option D is wrong because the Dependency Inversion Principle (DIP) deals with depending on abstractions rather than concretions, but it does not specifically ensure that a subclass can be used in place of its parent class without breaking functionality—that is LSP's role.

87
MCQeasy

A developer defines a class with a private attribute `_value` and wants to provide controlled access. Which approach is the most Pythonic?

A.Use `__slots__` to restrict attribute creation.
B.Make `_value` public and rely on documentation.
C.Use @property to define getter and setter methods.
D.Define `get_value()` and `set_value()` methods.
AnswerC

Property decorators provide controlled access in a Pythonic way.

Why this answer

Option C is correct because using the `@property` decorator is the most Pythonic way to implement controlled access to a private attribute. It allows you to define getter and setter methods that can be called like regular attribute access (e.g., `obj.value`), preserving encapsulation while maintaining a clean, non-method-call interface. This approach aligns with Python's philosophy of 'we are all consenting adults' and avoids the verbosity of explicit getter/setter methods.

Exam trap

Python Institute often tests the distinction between Pythonic idioms and patterns borrowed from other languages (like Java), so the trap here is that candidates familiar with Java or C++ may choose Option D (explicit getter/setter methods) because it looks familiar, missing that Python's `@property` is the preferred, more concise approach.

How to eliminate wrong answers

Option A is wrong because `__slots__` is used to restrict the attributes that can be assigned to an instance, not to provide controlled access to a specific attribute; it does not define getters or setters. Option B is wrong because making `_value` public and relying on documentation violates encapsulation principles and provides no runtime enforcement or validation, which is not Pythonic for controlled access. Option D is wrong because defining `get_value()` and `set_value()` methods is a Java-style approach that is considered non-Pythonic; Python prefers the `@property` decorator for a more natural attribute-like syntax.

88
MCQmedium

Refer to the exhibit. What is the output?

A.12.56 0
B.Error
C.0 0
D.0 12.56
AnswerD

Correct.

Why this answer

First object is Shape, area returns 0. Second is Circle, area returns 3.14*4=12.56.

89
Multi-Selecthard

Which THREE of the following are characteristics of Python's special methods (dunder methods)? (Select exactly three.)

Select 3 answers
A.They enable operator overloading for user-defined classes.
B.They can be defined in a class to customize behavior.
C.Every class automatically has all special methods predefined.
D.They must be defined inside the class definition and cannot be added later.
E.They are automatically invoked by Python in certain contexts.
AnswersA, B, E

E.g., __add__ for +.

Why this answer

Option A is correct because special methods like `__add__` and `__eq__` allow user-defined classes to redefine the behavior of operators such as `+` and `==`. When Python encounters an operator expression, it looks up the corresponding dunder method on the object's class, enabling operator overloading in a clean, syntactic way.

Exam trap

Python Institute often tests the misconception that all dunder methods are automatically inherited or that they cannot be added dynamically, so candidates mistakenly select option C or D without realizing that Python's data model only provides defaults for a minimal set and allows runtime assignment to classes.

90
Matchingmedium

Match each list method to its effect.

Drag a concept onto its matching description — or click a concept then click the description.

Concepts
Matches

Adds x to end

Appends elements from iterable

Inserts x at index i

Removes first occurrence of x

Removes and returns last item

Why these pairings

Common list methods.

91
MCQmedium

Consider the following class hierarchy: class A: def method(self): return 'A'; class B(A): pass; class C(A): def method(self): return 'C'; class D(B, C): pass. What is the output of D().method() according to Python's MRO?

A.'B'
B.TypeError
C.'A'
D.'C'
AnswerD

C's method() is found first in the MRO.

Why this answer

Python's MRO (Method Resolution Order) for class D(B, C) is computed using the C3 linearization algorithm, which respects the local precedence order and monotonicity. The MRO for D is D -> B -> C -> A, so D().method() resolves to C.method(), returning 'C'. Option D is correct because C is the first class in the MRO that defines method().

Exam trap

Python Institute often tests the C3 linearization rule that the MRO respects the order of base classes in the class definition, so candidates mistakenly think B's inheritance from A takes precedence over C's override, leading them to pick 'A' or 'B' instead of 'C'.

How to eliminate wrong answers

Option A is wrong because 'B' is not returned; class B does not override method(), so the MRO proceeds to C before reaching A. Option B is wrong because no TypeError occurs; the MRO is well-defined and method() is found in class C. Option C is wrong because 'A' is not returned; although A defines method(), the MRO finds C's override first, so A's version is never called.

92
MCQhard

Consider the following code snippet: 'class A: pass; class B(A): pass; class C(A): pass; class D(B, C): pass'. What is the Method Resolution Order (MRO) for class D according to the C3 linearization algorithm used by Python?

A.D, B, A, C, object
B.D, B, C, A
C.D, B, A, object, C
D.D, B, C, A, object
AnswerD

Correct linearization based on C3.

Why this answer

The C3 linearization algorithm merges the linearizations of D's parents (B and C) with their parent list, respecting the local precedence order and monotonicity. For class D(B, C), the MRO is computed as D + merge(L(B), L(C), [B, C]), where L(B) = B, A, object and L(C) = C, A, object. The merge yields D, B, C, A, object, which is the correct MRO.

Exam trap

Python Institute often tests the misconception that Python uses depth-first left-to-right resolution (like in old-style classes), leading candidates to pick Option A (D, B, A, C, object) instead of the correct C3 linearization result.

How to eliminate wrong answers

Option A is wrong because it incorrectly places A before C, violating the local precedence order where C should appear before A (since D inherits from B then C, and C is a direct parent). Option B is wrong because it omits 'object', which is always the final class in the MRO for new-style classes in Python. Option C is wrong because it places 'object' before C, which breaks monotonicity and the rule that a parent's MRO must be preserved; C must appear before object.

93
MCQmedium

A developer needs to create a class that cannot be instantiated directly but serves as a base for other classes. Which approach should be used?

A.Define __init__ that raises NotImplementedError
B.Define the class using the ABCMeta metaclass and decorate methods with @abstractmethod
C.Use a naming convention like _BaseClass
D.Define __new__ to return None
AnswerA

This prevents direct instantiation; subclasses must override __init__.

Why this answer

Option A is correct because raising `NotImplementedError` in the `__init__` method prevents direct instantiation of the class while still allowing subclasses to override `__init__` and be instantiated. This is a common Python pattern for creating abstract base classes without using the `abc` module, though it does not enforce abstraction at the method level.

Exam trap

Python Institute often tests the distinction between runtime enforcement (raising `NotImplementedError`) and compile-time enforcement (using `abc.ABC`), and the trap here is that candidates may choose option B because it is the more 'proper' abstract base class approach, but the question explicitly asks for a class that 'cannot be instantiated directly' and serves as a base — the `NotImplementedError` pattern is the specific technique they want, not the full `abc` module.

How to eliminate wrong answers

Option B is wrong because using `ABCMeta` and `@abstractmethod` creates a true abstract base class that cannot be instantiated, but the question asks for a class that 'cannot be instantiated directly' — this is also a valid approach, but the question specifically expects the pattern of raising `NotImplementedError` in `__init__`, making A the intended answer. Option C is wrong because a naming convention like `_BaseClass` is just a convention and does not prevent instantiation; Python does not enforce private naming. Option D is wrong because defining `__new__` to return `None` would prevent instantiation entirely, but it would also break subclass instantiation (since `__new__` is called before `__init__`), and returning `None` from `__new__` causes `__init__` not to be called, which is not the intended behavior for a base class that should be subclassed.

94
MCQhard

A class has a class attribute that is a list. A developer modifies this list via one instance, and the change is reflected in all other instances. What is the best practice to avoid this unintended sharing?

A.Use a tuple instead of a list.
B.Initialize the list in `__init__` rather than as a class attribute.
C.Use a class method to modify the list.
D.Use `deepcopy` when accessing the list.
AnswerB

By creating the list in `__init__`, each instance gets its own independent list.

Why this answer

Option B is correct because class attributes are shared across all instances. By initializing the list inside `__init__`, each instance gets its own independent list object, preventing unintended mutation from affecting other instances. This is the standard Python pattern for instance-specific mutable data.

Exam trap

Python Institute often tests the distinction between class-level and instance-level attributes, and the trap here is that candidates mistakenly think using a tuple (immutable) or a class method solves the sharing problem, when the real issue is the location of the mutable object's definition.

How to eliminate wrong answers

Option A is wrong because using a tuple prevents mutation entirely, which is not a solution for the requirement to modify the list; it changes the data structure's semantics and would cause an AttributeError on attempted modification. Option C is wrong because a class method still operates on the class-level list, so modifying it via one instance would still affect all instances; the sharing issue is not about the method type but about where the list is stored. Option D is wrong because `deepcopy` only creates a copy at the time of access, but the underlying class attribute remains shared; repeated accesses would require manual copying each time, which is inefficient and does not solve the fundamental design problem.

95
Multi-Selecteasy

Which TWO of the following are valid ways to define a class attribute (as opposed to an instance attribute) in Python?

Select 2 answers
A.obj.attr = 5 on an instance
B.class MyClass: def method(self): pass
C.class MyClass: def __init__(self): self.attr = 5
D.class MyClass: attr = 5
E.MyClass.attr = 5 outside the class definition
AnswersD, E

Class variable assignment inside the class body.

Why this answer

Option D is correct because defining `attr = 5` directly inside the class body, but outside any method, creates a class attribute that is shared by all instances. This is the standard Python syntax for class-level data.

Exam trap

Python Institute often tests the distinction between class attributes and instance attributes by presenting options that look similar (e.g., `self.attr` vs. `ClassName.attr`), and the trap is that candidates confuse assignment inside `__init__` (instance) with assignment in the class body (class).

96
MCQhard

Which of these is NOT a characteristic of Python's descriptor protocol?

A.A descriptor can be used to create properties with custom behavior
B.Descriptors are only used for attributes that are read-only
C.Class variables assigned to a descriptor are automatically intercepted
D.A descriptor must implement __get__
AnswerB

Descriptors can also handle writes and deletes.

Why this answer

Option B is correct because descriptors are not limited to read-only attributes; they can control get, set, and delete operations. A descriptor that only implements `__get__` is a non-data descriptor, which can be overridden by instance attributes, while a data descriptor implements both `__get__` and `__set__` (and optionally `__delete__`), allowing full read-write control. The statement that descriptors are only for read-only attributes is false, as they are commonly used for computed properties, validation, and lazy evaluation.

Exam trap

Python Institute often tests the misconception that descriptors are only for read-only attributes, but the trap here is that descriptors can be read-write (data descriptors) or read-only (non-data descriptors), and the protocol requires at least `__get__`, not that attributes are immutable.

How to eliminate wrong answers

Option A is wrong because descriptors can indeed be used to create properties with custom behavior, such as validation or computed values, via the `__get__`, `__set__`, and `__delete__` methods. Option C is wrong because class variables assigned to a descriptor are automatically intercepted when accessed on an instance, due to Python's attribute lookup precedence (data descriptors override instance attributes). Option D is wrong because a descriptor must implement `__get__` to be considered a descriptor at all; the protocol requires at least `__get__`, while `__set__` and `__delete__` are optional.

97
MCQeasy

Refer to the exhibit. What happens when the last line is executed?

A.The attribute 'city' is added dynamically.
B.The __slots__ is ignored because __init__ is defined.
C.A syntax error occurs.
D.An AttributeError is raised.
AnswerD

Only attributes in __slots__ can be assigned.

Why this answer

When a class defines `__slots__`, it restricts attribute assignment to only those names listed in `__slots__`. Attempting to assign an attribute not in that list (like `city`) raises an `AttributeError` because the instance has no `__dict__` to store dynamic attributes. The `__init__` method does not override this restriction; it simply initializes the allowed slots.

Exam trap

Python Institute often tests the misconception that `__init__` can override `__slots__` or that `__slots__` only applies to class-level attributes, leading candidates to incorrectly choose option B or A.

How to eliminate wrong answers

Option A is wrong because `__slots__` explicitly prevents dynamic addition of attributes not listed in it, so `city` cannot be added dynamically. Option B is wrong because `__slots__` is not ignored when `__init__` is defined; `__init__` only initializes existing slots, it does not bypass the slot restriction. Option C is wrong because no syntax error occurs; the code is syntactically valid, and the error is raised at runtime when the assignment is executed.

98
MCQhard

Refer to the exhibit. What is the output?

A.1 1
B.0 1
C.1 2
D.2 2
AnswerC

Correct.

Why this answer

Class variable count increments each time a new object is created. First object gets id=1, second gets id=2.

99
MCQmedium

A Python class 'BankAccount' has a method 'withdraw(amount)' that deducts 'amount' from 'self.balance'. A developer writes a subclass 'SavingsAccount' that overrides 'withdraw' to add a penalty if balance drops below minimum. Which design pattern is being used?

A.Composition
B.Aggregation
C.Method overriding
D.Inheritance
AnswerC

The subclass provides a specific implementation of the inherited method.

Why this answer

Option C is correct because method overriding is the mechanism where a subclass provides a specific implementation of a method that is already defined in its superclass. In this scenario, SavingsAccount overrides the withdraw method from BankAccount to add penalty logic, which is the defining characteristic of method overriding in Python.

Exam trap

The trap here is that candidates often confuse inheritance (the relationship) with method overriding (the specific technique), leading them to select 'Inheritance' instead of 'Method overriding' when the question explicitly describes a subclass redefining a parent method.

How to eliminate wrong answers

Option A is wrong because composition is a design pattern where a class contains instances of other classes as members to achieve code reuse, not where a subclass redefines a parent method. Option B is wrong because aggregation is a special form of composition representing a 'has-a' relationship with a weaker ownership lifecycle, not the act of overriding a method. Option D is wrong because inheritance is the broader mechanism that allows SavingsAccount to derive from BankAccount, but the specific pattern described—redefining withdraw in the subclass—is method overriding, not inheritance itself.

100
MCQhard

A developer implements a descriptor class with `__get__` and `__set__` methods. When an instance attribute is accessed, what determines whether the descriptor is used?

A.The descriptor's `__get__` is called only if `__getattr__` is not defined.
B.If the attribute exists in the instance's __dict__, the descriptor is ignored.
C.The descriptor must be defined in the class's metaclass.
D.The descriptor is used only if the attribute is a class variable and the descriptor protocol is implemented.
AnswerD

Correct: descriptors are class variables that override access.

Why this answer

Option D is correct because in Python, the descriptor protocol (__get__, __set__, __delete__) is only invoked when the attribute is accessed on the class (i.e., it is a class variable) and the descriptor object is defined in the class dictionary. Instance-level attributes stored in __dict__ take precedence over descriptors, so the descriptor is ignored if the instance has its own attribute with the same name. This behavior is defined by the Python data model: data descriptors (with __set__ or __delete__) override instance __dict__, but non-data descriptors (only __get__) are shadowed by instance attributes.

Exam trap

Python Institute often tests the distinction between data and non-data descriptors, and the trap here is that candidates assume instance __dict__ always wins, forgetting that data descriptors (with __set__) override instance attributes.

How to eliminate wrong answers

Option A is wrong because __getattr__ is a fallback method called only when normal attribute lookup fails; it does not affect whether a descriptor is used. Option B is wrong because for data descriptors (those defining __set__ or __delete__), the descriptor takes precedence over the instance's __dict__, so the descriptor is not ignored. Option C is wrong because the descriptor must be defined in the class's __dict__ (the class that owns the attribute), not in the metaclass; metaclass descriptors affect class-level attribute access, not instance attribute access.

101
MCQhard

Which of the following best describes the use of the @abstractmethod decorator in Python?

A.It automatically provides a default implementation for a method.
B.It indicates that a method must be overridden in any non-abstract subclass.
C.It creates a method that can be called without an instance.
D.It raises AttributeError if the method is called.
AnswerB

Abstract methods are placeholders that require overriding.

Why this answer

The @abstractmethod decorator is used in abstract base classes to declare methods that must be implemented by concrete subclasses. It cannot be instantiated directly if any abstract methods are present.

102
MCQeasy

A company needs to model different types of employees. They have a base class `Employee` with a method `calculate_pay()`. For hourly employees, pay = hours * rate; for salaried employees, pay = salary. Which design approach is most appropriate?

A.Use a `@staticmethod` inside `Employee` to compute pay based on a type parameter.
B.Define a module-level function that takes an employee object and computes pay.
C.Create subclasses `HourlyEmployee` and `SalariedEmployee` that override `calculate_pay()`.
D.Use a single `Employee` class with conditional statements to differentiate pay types.
AnswerC

This uses inheritance and polymorphism, the standard OOP approach for such scenarios.

Why this answer

Option C is correct because it applies polymorphism through method overriding: each subclass (`HourlyEmployee`, `SalariedEmployee`) provides its own implementation of `calculate_pay()`, allowing the calling code to treat all employees uniformly via the base class interface. This adheres to the Open/Closed Principle and keeps the design extensible without modifying existing code when new employee types are added.

Exam trap

Python Institute often tests the distinction between using inheritance with method overriding versus using conditionals or static methods, and the trap here is that candidates may think a single class with `if` statements is simpler and therefore better, missing the long-term maintenance and extensibility advantages of polymorphism.

How to eliminate wrong answers

Option A is wrong because a `@staticmethod` cannot access instance attributes (`hours`, `rate`, `salary`) without passing them explicitly, and using a type parameter violates polymorphism by requiring conditional logic inside the static method. Option B is wrong because a module-level function breaks encapsulation and does not leverage the class hierarchy, making it harder to extend and maintain as employee types grow. Option D is wrong because using conditional statements inside a single `Employee` class violates the Open/Closed Principle and leads to fragile code that must be modified every time a new pay type is introduced.

103
MCQmedium

A class 'Point' is defined with __slots__ = ['x', 'y']. A developer creates an instance p = Point() and tries to set p.z = 10. What happens?

A.The assignment is silently ignored
B.Python issues a warning and adds the attribute
C.The attribute 'z' is added dynamically
D.AttributeError is raised
AnswerD

Slots disallow adding new attributes.

Why this answer

When a class defines `__slots__`, it restricts attribute assignment to only those names listed in the tuple. Attempting to assign an attribute not in `__slots__` raises an `AttributeError`. This is a deliberate memory optimization that prevents the creation of a per-instance `__dict__`, so dynamic attributes are disallowed.

Exam trap

Python Institute often tests the misconception that `__slots__` only provides a hint or that attributes can still be added dynamically, when in fact it strictly forbids any attribute not listed in `__slots__`.

How to eliminate wrong answers

Option A is wrong because the assignment is not silently ignored; Python actively raises an exception. Option B is wrong because Python does not issue a warning and add the attribute; it strictly enforces the slot restriction with an error. Option C is wrong because `__slots__` prevents dynamic attribute addition; the attribute 'z' is not added under any circumstances.

104
MCQhard

Refer to the exhibit. What is the output and why?

A.AttributeError
B.1
C.2
D.3
AnswerC

B's __init__ runs last among the chain, setting x=2.

Why this answer

Option C is correct because the code defines a class `A` with a class attribute `counter` set to 0, and an `__init__` method that increments `A.counter` (the class attribute) by 1 each time an instance is created. Creating two instances (`a1` and `a2`) increments the class attribute twice, so `A.counter` becomes 2. The `print(A.counter)` statement outputs the class attribute value, which is 2.

Exam trap

The trap here is that candidates may mistakenly think `self.counter` is being incremented (creating an instance attribute) rather than `A.counter` (the class attribute), leading them to expect the output to be 1 or to overlook that the class attribute is shared and incremented by each instantiation.

How to eliminate wrong answers

Option A is wrong because there is no AttributeError; the class attribute `counter` is defined and accessed correctly via `A.counter`. Option B is wrong because the output is not 1; creating two instances increments the counter twice, not once. Option D is wrong because the output is not 3; only two instances are created, so the counter is incremented exactly twice, not three times.

105
MCQeasy

A developer defines a class 'Car' with an attribute 'wheels = 4'. They create two instances: car1 = Car() and car2 = Car(). Then they set car1.wheels = 3. What is the value of car2.wheels?

A.4
B.3
C.AttributeError
D.None
AnswerA

car2 still references the class attribute value 4.

Why this answer

Option A is correct because in Python, setting an attribute directly on an instance (car1.wheels = 3) creates an instance attribute that shadows the class attribute for that specific instance only. The class attribute 'wheels = 4' remains unchanged and is still accessible via car2.wheels, which has not been overridden. Therefore, car2.wheels retains the class-level value of 4.

Exam trap

Python Institute often tests the distinction between class attributes and instance attributes, trapping candidates who mistakenly think that modifying an instance attribute propagates to other instances or that it raises an error.

How to eliminate wrong answers

Option B is wrong because it assumes that modifying an instance attribute on one object affects all instances of the class, which is not true in Python; instance attribute assignments are local to that instance. Option C is wrong because no AttributeError occurs: car2.wheels successfully resolves to the class attribute 'wheels' defined in the Car class. Option D is wrong because car2.wheels is not None; it is explicitly set to 4 at the class level and never reassigned.

106
MCQeasy

A junior developer wrote a class representing a bank account with a private attribute balance. They used double underscore prefix (__balance) to make it private. However, in a test script, they are still able to access the attribute using the mangled name _Account__balance. The developer is confused about why encapsulation is not enforced. Which statement best explains this behavior?

A.The double underscore prefix actually makes the attribute completely inaccessible from outside the class.
B.Python's name mangling is only a convention and does not prevent access.
C.The developer forgot to use the @property decorator.
D.The test script must have used a different class attribute name.
AnswerB

Name mangling transforms the attribute name but does not restrict access; it's a naming convention.

Why this answer

Option B is correct because Python's name mangling (triggered by a double underscore prefix) is not a security mechanism but a syntactic transformation that renames the attribute to _ClassName__attribute. This prevents accidental name clashes in subclasses but does not enforce true encapsulation; the attribute can still be accessed via the mangled name from outside the class. The developer's confusion stems from mistaking name mangling for a privacy guarantee, which Python intentionally does not provide.

Exam trap

The trap here is that Python Institute often tests the misconception that double underscore prefix enforces true privacy like in languages such as Java or C++, when in reality Python's name mangling is merely a renaming convention that does not prevent access from outside the class.

How to eliminate wrong answers

Option A is wrong because the double underscore prefix does not make the attribute completely inaccessible; it only triggers name mangling, and the attribute remains accessible via the mangled name (e.g., _Account__balance). Option C is wrong because the @property decorator is used to define getter/setter methods for controlled access, but its absence does not affect the ability to access the attribute directly via the mangled name; the core issue is about privacy enforcement, not property decorators. Option D is wrong because the test script correctly uses the mangled name _Account__balance, which is the actual attribute name after mangling; there is no different class attribute name involved.

107
MCQmedium

Consider the following code: class A: x = 1; class B(A): pass; class C(A): x = 2; class D(B, C): pass. What is D.x?

A.AttributeError
B.1
C.2
D.(1, 2) tuple
AnswerC

C's x is found first in MRO.

Why this answer

Option C is correct because Python's method resolution order (MRO) for class D, which uses multiple inheritance, follows the C3 linearization algorithm. The MRO for D is D, B, C, A, and since C defines x = 2, that attribute overrides the x = 1 from A in the inheritance chain, so D.x resolves to 2.

Exam trap

Python Institute often tests the misconception that Python's multiple inheritance simply merges attributes from all parent classes, leading candidates to expect a tuple or an error, rather than applying the C3 linearization to determine a single overriding value.

How to eliminate wrong answers

Option A is wrong because D inherits from B and C, which both ultimately inherit from A, so x is defined in the hierarchy and no AttributeError occurs. Option B is wrong because although A defines x = 1, the MRO prioritizes C's definition of x = 2 over A's, so D.x is not 1. Option D is wrong because attribute lookup in Python does not return a tuple of all inherited values; it returns a single value from the first class in the MRO that defines the attribute.

108
Multi-Selecteasy

Which TWO of the following are valid ways to define a class attribute that is shared by all instances?

Select 2 answers
A.class MyClass: attr: int = 0
B.class MyClass: def set_attr(self): MyClass.attr = 0
C.class MyClass: pass MyClass.attr = 0
D.class MyClass: attr = 0
E.class MyClass: def __init__(self): self.attr = 0
AnswersC, D

Assigns a class attribute after definition.

Why this answer

Option C is correct because assigning an attribute directly to the class after its definition (MyClass.attr = 0) creates a class-level attribute that is shared by all instances. Option D is correct because defining an attribute directly inside the class body (attr = 0) also creates a class-level attribute, accessible to all instances unless shadowed by an instance attribute.

Exam trap

Python Institute often tests the distinction between class attributes and instance attributes, and the trap here is that candidates confuse type annotations (which do not create attributes) with actual assignments, or think that assigning inside a method (like __init__) creates a class-level attribute when it actually creates an instance attribute.

109
MCQmedium

A developer defines a class 'MathUtils' with a method that performs a calculation either on the class or on instances. Which method type should be used for a method that does not depend on instance state but can be called on the class?

A.@classmethod def add(cls, a, b): return a + b
B.def add(self, a, b): return a + b
C.@property def add(self): return lambda a,b: a+b
D.@staticmethod def add(a, b): return a + b
AnswerA

Class methods receive the class as first argument and can be called on the class or instance.

Why this answer

Option B correctly uses @classmethod, which receives the class as first argument and can be called on the class or instance. Option A uses @staticmethod, which does not receive cls. Option C is a regular instance method requiring self.

Option D uses @property, which is for attribute-like access.

110
MCQhard

Refer to the exhibit. What is the output?

A.DBACA
B.DCBA
C.DBCA
D.DBAC
E.Error
AnswerC

Correct sequence: D, then B, then C, then A.

Why this answer

The MRO for class D using C3 linearization is D -> B -> C -> A. Therefore, D calls super() to B, B calls super() to C, C calls super() to A. Output: D B C A (as a concatenated string).

111
Drag & Dropmedium

Drag and drop the steps to create a Python package with subpackages into the correct order.

Drag steps to the numbered slots on the right, or tap a step then tap a slot.

Steps
Order

Why this order

A package is a directory with __init__.py. Subpackages are subdirectories with their own __init__.py. Modules are placed inside, and imports use dot notation.

112
MCQhard

Refer to the exhibit. What is the root cause of the error?

A.The attribute 'age' is not defined in the class or instance.
B.The __init__ method was not called.
C.The attribute 'age' is private.
D.The attribute 'age' is a class attribute but not initialized.
AnswerA

The instance only has 'name', not 'age'.

Why this answer

Option B is correct because the attribute 'age' is not defined anywhere in the class or instance. Option A is incorrect because there is no private attribute involved. Option C is incorrect because __init__ was called.

Option D is incorrect because 'age' is not a class attribute.

113
MCQmedium

A programmer wants to create a class that cannot be instantiated directly, only through a factory method. Which approach should be used?

A.Raise an exception in __init__ if called directly.
B.Define the class as abstract using ABC and @abstractmethod.
C.Override __new__ to raise an exception unless called from a classmethod factory.
D.Use a metaclass to prevent instantiation.
AnswerC

__new__ controls instance creation; raising an exception prevents direct instantiation.

Why this answer

Option C is correct because overriding `__new__` allows the programmer to control instance creation at the lowest level. By checking the call stack or a flag set by a classmethod factory, `__new__` can raise an exception when instantiation is attempted directly, while still allowing the factory method to create instances. This ensures the class cannot be instantiated directly, only through the designated factory.

Exam trap

Python Institute often tests the distinction between `__new__` and `__init__`, and the trap here is that candidates think raising an exception in `__init__` (Option A) is sufficient, not realizing that `__new__` has already created the object and the exception only prevents full initialization, not allocation.

How to eliminate wrong answers

Option A is wrong because raising an exception in `__init__` still allows the object to be partially created (memory allocated by `__new__`), and the exception can be caught, leaving a half-initialized object or causing confusion; it does not prevent instantiation at the allocation stage. Option B is wrong because defining a class as abstract with ABC and @abstractmethod prevents instantiation only if the class has unimplemented abstract methods; if all abstract methods are implemented, the class can be instantiated directly, which does not enforce the factory-only requirement. Option D is wrong because using a metaclass to prevent instantiation is overly complex and not a standard Python pattern for this specific need; it would require overriding `__call__` in the metaclass, which is less direct and more error-prone than overriding `__new__` in the class itself.

114
MCQhard

A class `ServerConfig` has a class attribute `port = 8080`. After deployment, a developer runs `ServerConfig.port = 9090` in one module, and unexpectedly all existing instances now use port 9090. What concept explains this behavior?

A.Instance attributes always override class attributes.
B.The attribute is immutable.
C.Class attributes are shared among all instances of a class.
D.Python uses copy-on-write for attribute access.
AnswerC

Changing a class attribute via the class affects all instances, as they all reference the same attribute.

Why this answer

Option C is correct because class attributes in Python are shared across all instances of a class. When you modify `ServerConfig.port` on the class itself, every instance that accesses `port` via the class (or via an instance that hasn't overridden it) sees the new value. This is fundamental to Python's attribute lookup mechanism: instance attributes shadow class attributes, but if no instance attribute exists, the class attribute is used.

Exam trap

Python Institute often tests the distinction between modifying a class attribute via the class vs. modifying it via an instance; the trap is that candidates think assigning to `instance.port` changes the class attribute, but it actually creates a new instance attribute that shadows the class attribute.

How to eliminate wrong answers

Option A is wrong because instance attributes only override class attributes when they are explicitly set on the instance; they do not cause class-level changes to propagate. Option B is wrong because the attribute `port` is an integer, which is immutable, but immutability does not affect sharing or rebinding of the attribute on the class. Option D is wrong because Python does not use copy-on-write for attribute access; it uses a dynamic lookup chain (instance → class → parent classes) and assignment always modifies the target directly.

115
MCQeasy

A class has a method that does not access any instance or class data. What decorator should be used to define it as a utility method that can be called on the class itself without requiring an instance?

A.@property
B.@staticmethod
C.@abstractmethod
D.@classmethod
AnswerB

Static methods don't take self or cls.

Why this answer

The @staticmethod decorator is used for methods that do not depend on the class or instance state. They can be called on both instances and the class.

116
MCQhard

Refer to the exhibit. What is the output?

A.7
B.10
C.Error
D.14
AnswerB

Correct.

Why this answer

Base.method returns 3*2=6, Derived.method adds 4, so 10.

117
MCQhard

Refer to the exhibit. What is the output?

A.3
B.Error
C.A object
D.4
AnswerD

Correct; 1+2+1=4.

Why this answer

The __add__ method adds the two values and adds 1, so 1+2+1=4.

118
Multi-Selectmedium

Which TWO statements about method overriding in Python are correct?

Select 2 answers
A.The overriding method can call the parent method using super()
B.The overriding method must have the same name
C.The overriding method requires explicit use of the @override decorator
D.The overriding method must have the exact same parameter list
E.Overriding is resolved at compile time
AnswersA, B

super() allows access to the overridden method.

Why this answer

Option A is correct because the overriding method can call the parent class's version of the method using the built-in `super()` function, which returns a proxy object that delegates method calls to the parent class. This is a fundamental feature of Python's inheritance mechanism, allowing the child method to extend or modify the parent's behavior while still invoking it.

Exam trap

Python Institute often tests the misconception that Python enforces strict method signatures or requires an `@override` decorator, leading candidates to select options D or C, when in fact Python's dynamic nature allows flexible overriding without compile-time checks.

119
MCQhard

A developer wants to ensure that the 'radius' attribute of a Circle class is always non-negative. Which implementation using @property is correct?

A.class Circle:\n def __init__(self, radius):\n self._radius = radius\n def radius(self):\n return self._radius
B.class Circle:\n def __init__(self, radius):\n self._radius = radius\n @property\n def radius(self):\n return self._radius\n @radius.setter\n def radius(self, value):\n if value < 0:\n raise ValueError\n self._radius = value
C.class Circle:\n def __init__(self, radius):\n self.radius = radius\n @property\n def radius(self):\n return self._radius\n @radius.setter\n def radius(self, value):\n if value < 0:\n raise ValueError\n self._radius = value
D.class Circle:\n def __init__(self, radius):\n self.radius = radius\n @property\n def radius(self):\n return self._radius\n def set_radius(self, value):\n self._radius = value
AnswerC

Uses setter in init, validates always.

Why this answer

Option C is correct because it uses the @property decorator to define a getter and @radius.setter to define a setter that validates the radius value before assignment. The __init__ method correctly assigns to self.radius, which triggers the setter, ensuring the initial value is also validated. This pattern enforces the invariant that radius is always non-negative.

Exam trap

Python Institute often tests the subtlety that __init__ must use the property setter (self.radius = radius) rather than directly assigning to the backing attribute (self._radius = radius) to ensure validation applies to the initial value as well.

How to eliminate wrong answers

Option A is wrong because it lacks the @property decorator, so radius is a plain method, not a property; accessing circle.radius would return a bound method, not the stored value. Option B is wrong because __init__ assigns to self._radius directly, bypassing the setter validation, so an initial negative radius would be accepted. Option D is wrong because it defines a set_radius method instead of using @radius.setter, so the property is read-only and assignment to circle.radius would raise an AttributeError.

120
MCQhard

A Python developer is implementing a class that should behave like a sequence and support indexing. Which pair of special methods must be defined to achieve this?

A.__getitem__ and __contains__
B.__setitem__ and __delitem__
C.__iter__ and __next__
D.__getitem__ and __len__
AnswerD

These are the minimum to support indexing and length.

Why this answer

To make a class behave like a sequence and support indexing (e.g., obj[0]), Python requires the __getitem__ method to retrieve items by key. Additionally, the __len__ method is needed to define the length of the sequence, which is used by built-in functions like len() and is part of the sequence protocol. Together, these two methods satisfy the minimal requirements for a sequence-like object that supports indexing.

Exam trap

Python Institute often tests the distinction between the sequence protocol (__getitem__ + __len__) and the iterator protocol (__iter__ + __next__), trapping candidates who think iteration alone enables indexing.

How to eliminate wrong answers

Option A is wrong because __contains__ is used for the 'in' operator (membership testing), not for indexing or sequence behavior. Option B is wrong because __setitem__ and __delitem__ are for mutable sequences that support item assignment and deletion, but indexing (read access) only requires __getitem__; __len__ is still needed for sequence protocol. Option C is wrong because __iter__ and __next__ implement the iterator protocol, which allows iteration but does not provide indexing (e.g., obj[0] would fail without __getitem__).

121
MCQmedium

A class named Counter has a class variable count and an instance method increment. The method is defined as def increment(self): Counter.count += 1. What will be the output after executing the following code? c1 = Counter(); c2 = Counter(); c1.increment(); c2.increment(); print(Counter.count, c1.count, c2.count)

A.2 2 2
B.2 1 1
C.1 1 1
D.0 0 0
AnswerA

Both c1 and c2 refer to the same class variable count.

Why this answer

Option A is correct because the class variable `count` is shared across all instances of the `Counter` class. The `increment` method modifies `Counter.count` directly, so after two calls, `Counter.count` becomes 2. Since `c1.count` and `c2.count` refer to the same class variable (they do not have instance attributes shadowing it), both instances reflect the same value of 2.

Exam trap

Python Institute often tests the distinction between class variables and instance variables, trapping candidates who mistakenly think each instance gets its own copy of the class variable or that `self.count` would create an instance attribute instead of modifying the class variable.

How to eliminate wrong answers

Option B is wrong because it assumes each instance has its own `count` attribute that increments independently, but the code modifies the class variable, not instance attributes. Option C is wrong because it suggests only one increment occurred, but two calls to `increment()` were made. Option D is wrong because it implies no increment happened at all, ignoring the two calls to `increment()`.

122
Multi-Selecthard

Which THREE of the following are true about method overriding in Python?

Select 3 answers
A.The subclass method must have the same name.
B.The parent method can be called using `super()`.
C.The `@override` decorator is required.
D.The subclass method can have a different return type.
E.The subclass method can have a different number of parameters.
AnswersA, B, D

Method overriding is based on the same method name as in the parent class.

Why this answer

Option A is correct because method overriding in Python requires the subclass method to have the same name as the parent class method. This is the fundamental rule of overriding — without the same name, the method is not overriding but rather defining a new method. The subclass method replaces the inherited method when called on an instance of the subclass.

Exam trap

Python Institute often tests the misconception that Python requires an `@override` decorator (like Java or C#) or that changing the parameter list is allowed in overriding, when in fact Python uses implicit overriding based solely on method name and expects the same signature for correct polymorphic behavior.

123
Multi-Selecthard

Refer to the exhibit. Which THREE statements about the class hierarchy are correct?

Select 3 answers
A.D does not have a method named 'method'
B.Calling D().method() returns 'B'
C.The super() call in B would call C.method
D.The MRO of D is ['D', 'B', 'C', 'A', 'object']
E.Class C is a subclass of A
AnswersB, D, E

B is first in MRO after D.

Why this answer

Option B is correct because when `D().method()` is called, Python's MRO (Method Resolution Order) for class D is `['D', 'B', 'C', 'A', 'object']`. Since class D does not define `method`, Python looks up the MRO and finds `method` first in class B. The `return 'B'` in B's `method` is executed, so the call returns 'B'.

Exam trap

Python Institute often tests the misconception that `super()` always calls the immediate parent class, when in fact it follows the MRO of the runtime instance, which can skip or reorder classes in multiple inheritance scenarios.

124
MCQmedium

A class inherits from two parent classes that both have a method with the same name. When calling the method on the child, only one parent's version is executed. What Python mechanism determines which one?

A.Method overloading by signature.
B.Explicit super() call in the child class.
C.Inheritance depth (closest parent wins).
D.Method Resolution Order (MRO).
AnswerD

MRO determines the order of method lookup in multiple inheritance.

Why this answer

Python uses the C3 linearization algorithm to compute the Method Resolution Order (MRO) for a class. When a method is called on an instance, Python searches the MRO from left to right and executes the first implementation it finds. This ensures a consistent and predictable order of inheritance, even in diamond or multiple-inheritance scenarios.

Exam trap

Python Institute often tests the misconception that Python uses 'closest parent wins' or depth-first search, but the actual mechanism is the C3 linearization MRO, which respects base class order and the diamond inheritance pattern.

How to eliminate wrong answers

Option A is wrong because Python does not support method overloading by signature; the last definition of a method in a class overwrites previous ones, and dispatch is based on the object's type, not argument types. Option B is wrong because an explicit super() call is a way to invoke a parent's method from within the child, but it is not the mechanism that determines which parent's method is executed when calling the method directly on the child. Option C is wrong because inheritance depth does not determine which parent's method is called; Python's MRO follows the C3 linearization order, which respects the order of base classes and the diamond pattern, not simply the closest parent.

125
Multi-Selectmedium

Which TWO of the following are valid ways to define a class method in Python? (Select exactly two.)

Select 2 answers
A.def my_method(cls): pass my_method = classmethod(my_method)
B.class MyClass: def my_method(cls): pass
C.def my_method(self): pass
D.@staticmethod def my_method(cls): pass
E.@classmethod def my_method(cls): pass
AnswersA, E

Alternative way to apply classmethod decorator.

Why this answer

Option A is correct because it manually applies the `classmethod()` built-in function to a regular function, converting it into a class method. This is a valid, though less common, way to define a class method, as the `classmethod` descriptor wraps the function so that the first argument passed is the class (`cls`), not an instance.

Exam trap

Python Institute often tests the distinction between the explicit `classmethod()` call and the decorator syntax, and the trap here is that candidates may think only the `@classmethod` decorator is valid, overlooking the manual `classmethod()` function call as an equally valid alternative.

126
MCQhard

Refer to the exhibit. What is the output?

A.2 0 0
B.2 2 2
C.2 1 1
D.0 2 2
AnswerB

All calls refer to the same class variable.

Why this answer

Option B is correct because the code defines a class `A` with a class variable `x = 2`, and a class `B` that inherits from `A`. The `display` method prints `self.x`, which first looks up the instance attribute `x`; since no instance attribute is set, it falls back to the class variable `x = 2` from class `A`. The loop creates three instances of `B` and calls `display` on each, so each prints `2` on a separate line, resulting in the output 2, 2, 2.

Exam trap

Python Institute often tests the distinction between class variables and instance attributes, and the trap here is that candidates mistakenly think each instance gets its own copy of `x` or that the loop modifies `x` per iteration, when in fact all instances share the same class variable unless explicitly overridden.

How to eliminate wrong answers

Option A is wrong because it suggests the output is 2, 0, 0, which would require the first instance to access the class variable and subsequent instances to have instance attribute `x` set to 0, but no such assignment occurs. Option C is wrong because it shows 2, 1, 1, which would imply that `x` is being modified or that a different value is assigned per instance, but the class variable remains 2 and no instance attribute is created. Option D is wrong because it shows 0, 2, 2, which would require the first instance to have `x = 0` and the rest to have `x = 2`, but no instance-level assignment or override happens in the code.

127
MCQmedium

Refer to the exhibit. What will happen when the code is executed?

A.It prints None
B.It raises a TypeError
C.It raises an AttributeError
D.It prints 10
AnswerC

obj.__x does not exist due to name mangling.

Why this answer

The code attempts to call a method or access an attribute that does not exist on the object. In Python, when you try to access an attribute or method that is not defined on an object, an AttributeError is raised. Option C is correct because the exhibit shows an attempt to call a non-existent method or attribute on an instance, which triggers AttributeError.

Exam trap

Python Institute often tests the distinction between AttributeError and TypeError, trapping candidates who confuse missing methods with type mismatches.

How to eliminate wrong answers

Option A is wrong because the code does not contain a return statement that would produce None; instead, it raises an exception. Option B is wrong because a TypeError occurs when an operation or function is applied to an object of inappropriate type, not when a missing attribute is accessed. Option D is wrong because the code does not print 10; it raises an exception before any print statement could execute.

128
MCQeasy

A class has an attribute that should be computed on access and cached for subsequent accesses. Which pattern is most appropriate?

A.Use __slots__ to define the attribute.
B.Use a custom descriptor that caches the value in the instance's __dict__.
C.Use a @classmethod to compute the value.
D.Use a @staticmethod to compute the value.
AnswerB

A descriptor can compute on first access and store the result for subsequent calls.

Why this answer

Option B is correct because a custom descriptor with a __get__ method can compute the attribute value on first access and store it in the instance's __dict__ for subsequent accesses. This pattern, often called a cached property, ensures the computation happens only once per instance, which is exactly what the question requires.

Exam trap

Python Institute often tests the distinction between descriptors that compute on every access versus those that cache, and the trap here is that candidates confuse __slots__ (memory optimization) with caching, or think that class-level methods like @classmethod can somehow provide per-instance caching.

How to eliminate wrong answers

Option A is wrong because __slots__ is used to restrict the attributes an instance can have and to save memory by preventing the creation of a __dict__; it does not provide any caching or lazy computation mechanism. Option C is wrong because a @classmethod operates on the class itself, not on an instance, and cannot cache per-instance computed values. Option D is wrong because a @staticmethod is essentially a regular function inside the class namespace, with no access to the instance or class, and thus cannot compute or cache instance-specific attributes.

129
MCQmedium

Refer to the exhibit. What will be the output?

A.None
B.0
C.AttributeError
D.10
AnswerC

AttributeError because `__private` is mangled to `_MyClass__private` and cannot be accessed directly from outside.

Why this answer

Option C is correct because the code attempts to call `obj.get_value()` on an instance of `MyClass`, but `MyClass` does not define a `get_value` method. In Python, this raises an `AttributeError` since the attribute is not found on the object or its class. The error occurs at runtime, not during compilation, because Python dynamically looks up attributes.

Exam trap

Python Institute often tests the misconception that a missing method will silently return `None` or a default value, but in Python, accessing an undefined attribute on an object always raises an `AttributeError` unless a `__getattr__` method is defined to handle it.

How to eliminate wrong answers

Option A is wrong because the code does produce output—specifically, an exception is raised, so the program does not silently produce 'None'. Option B is wrong because the code does not return or print the integer 0; there is no default value mechanism that would yield 0 for a missing method. Option D is wrong because the code does not execute a method that returns 10; the `get_value` method is never defined, so no value of 10 is ever produced.

130
MCQeasy

A developer defines a subclass 'Dog' that overrides the '__init__' method of the parent class 'Animal'. The parent class __init__ sets a 'species' attribute. Which code ensures the parent __init__ is called correctly in Python 3?

A.class Dog(Animal): def __init__(self, name): super().__init__(); self.name = name
B.class Dog(Animal): def __init__(self, name): self.name = name
C.class Dog(Animal): def __init__(self, name): super().__init__(name); self.name = name
D.class Dog(Animal): def __init__(self, name): Animal.__init__(self); self.name = name
AnswerA

super().__init__() calls the parent __init__ without arguments if parent doesn't require any.

Why this answer

Option A is correct because it uses `super().__init__()` without arguments, which calls the parent `Animal.__init__` method as per Python 3's cooperative multiple inheritance model. Since the parent `__init__` sets `species` without requiring any parameters, this ensures the `species` attribute is initialized before `self.name` is set in the subclass.

Exam trap

Python Institute often tests the misconception that `super().__init__()` must always pass the subclass's arguments to the parent, leading candidates to choose Option C, but the correct behavior depends on the parent's signature, not a blanket rule.

How to eliminate wrong answers

Option B is wrong because it completely omits a call to the parent `__init__`, so the `species` attribute is never set, leaving the object without that inherited attribute. Option C is wrong because it passes `name` to `super().__init__(name)`, but the parent `__init__` does not accept a `name` parameter, causing a `TypeError`. Option D is wrong because while `Animal.__init__(self)` works technically, it bypasses Python's MRO and is not the recommended Python 3 idiom; more critically, it still correctly calls the parent init, but the question asks for the 'correct' Python 3 approach, which is `super()`, not direct parent class referencing.

131
MCQmedium

A developer defines a class hierarchy with multiple inheritance: class A, class B(A), class C(A), class D(B,C). The method 'm' is defined only in A. What is the method resolution order for D according to the C3 linearization algorithm?

A.D -> B -> A -> object
B.D -> B -> C -> A -> object
C.D -> B -> C -> A
D.D -> B -> A -> C
AnswerC

C3 linearization for D(B,C) yields D, B, C, A.

Why this answer

C is correct because the C3 linearization algorithm merges the linearizations of parent classes while preserving local precedence order and monotonicity. For class D(B, C), the linearization is D + merge(L(B), L(C), [B, C]). L(B) = B, A, object; L(C) = C, A, object.

Merging yields D, B, C, A, object (object is often omitted in option lists). This respects that B precedes C in D's bases and that A appears after both B and C.

Exam trap

Python Institute often tests the misconception that the MRO follows a simple depth-first left-to-right order, causing candidates to pick option A (D, B, A, C) or D (D, B, A, C) instead of the correct C3 merge result that respects the order of parent classes and their linearizations.

How to eliminate wrong answers

Option A is wrong because it omits class C entirely, violating the local precedence order of D's bases (B, C) and the C3 merge rule that includes all parent classes. Option B is wrong because it places object at the end, which is technically correct but the given option list omits 'object' — however the core error is that it includes object while the correct answer (C) does not; more importantly, option B's order (D, B, C, A, object) is actually the full correct MRO, but the question's answer choices treat 'object' as optional, so option C is the intended correct answer without object. Option D is wrong because it places A before C, violating the C3 rule that C must appear before A since C inherits from A and the merge must preserve the order from C's linearization (C, A).

132
Multi-Selecthard

Which TWO of the following are valid ways to define a class attribute that is shared among all instances?

Select 2 answers
A.Assign the attribute inside a classmethod using cls.
B.Assign the attribute inside a staticmethod.
C.Use the @property decorator.
D.Assign the attribute inside __init__ using self.
E.Assign the attribute in the class body, outside any methods.
AnswersA, E

Classmethods can modify class attributes via the cls parameter.

Why this answer

Option A is correct because a classmethod receives the class (cls) as its first argument, allowing you to assign or modify a class attribute via `cls.attribute = value`. This assignment affects the class itself, making the attribute shared among all instances, as the attribute is stored on the class object, not on instance dictionaries.

Exam trap

Python Institute often tests the distinction between class-level and instance-level attributes, and the trap here is that candidates confuse the @property decorator (which defines a computed instance property) with a class attribute, or think that a staticmethod can modify class state because it is defined inside the class body.

133
Multi-Selectmedium

Which THREE statements about inheritance in Python are correct?

Select 3 answers
A.A child class inherits all attributes and methods from its parent class.
B.Private attributes (with __) are inherited unchanged.
C.Python supports multiple inheritance.
D.Python supports method overloading based on parameters.
E.The super() function can be used to call a method from a parent class.
AnswersA, C, E

Correct, except for name-mangled ones.

Why this answer

Option A is correct because in Python, a child class inherits all non-private attributes and methods from its parent class by default. This includes both data attributes and methods, allowing the child to reuse and extend the parent's behavior without redefinition. Private attributes (with double underscore prefix) are name-mangled to _Classname__attribute, but they are still inherited in the sense that they exist in the child's namespace under the mangled name, though direct access by the original name is restricted.

Exam trap

Python Institute often tests the misconception that private attributes (__name) are completely hidden or not inherited, when in fact they are inherited but name-mangled, and that Python supports method overloading like Java or C++, when it actually relies on default arguments and single method definitions.

134
MCQhard

A developer creates a metaclass 'Meta' that modifies class creation by adding a class attribute 'created_by' set to 'Meta'. Which code snippet correctly defines and uses this metaclass?

A.class Meta(type): def __new__(cls, name, bases, dct): dct['created_by']='Meta'
B.class Meta(type): def __init__(cls, name, bases, dct): dct['created_by']='Meta'
C.def Meta(name, bases, dct): dct['created_by']='Meta'; return type(name, bases, dct)
D.class Meta(type): def __new__(cls, name, bases, dct): dct['created_by']='Meta'; return super().__new__(cls, name, bases, dct)
AnswerD

Correctly overrides __new__ and calls super to create the class.

Why this answer

Option D is correct because it defines a proper metaclass by subclassing `type` and overriding `__new__`, which is the correct method for modifying the class dictionary before the class is created. The `__new__` method must return the result of `super().__new__(cls, name, bases, dct)` to actually create the class object. Adding `dct['created_by']='Meta'` inside `__new__` ensures the attribute is set during class creation.

Exam trap

Python Institute often tests the distinction between `__new__` and `__init__` in metaclasses, and the trap here is that candidates mistakenly think `__init__` can modify the class dictionary before class creation, or forget that `__new__` must explicitly return the class object.

How to eliminate wrong answers

Option A is wrong because the `__new__` method does not return the newly created class object; without `return super().__new__(...)`, the metaclass returns `None`, causing a `TypeError` when trying to create a class. Option B is wrong because `__init__` is called after the class is already created, so modifying `dct` inside `__init__` does not affect the class's attributes (the dictionary is already used); the correct place to modify the class dictionary is in `__new__`. Option C is wrong because it defines a regular function, not a metaclass; although it can create a class dynamically, it does not define a metaclass that can be used with the `metaclass=Meta` keyword argument in a class statement.

135
MCQhard

An application uses a heavy-weight class DatabaseConnection that establishes a network connection upon instantiation. The class is used in multiple places, and the developer wants to ensure that only one instance of DatabaseConnection exists throughout the application. They implement a Singleton pattern using a class attribute _instance and a class method get_instance(). However, they notice that the network connection is being established multiple times. After debugging, they find that the singleton is not being enforced because the __init__ method is called every time the class is instantiated, even if the same instance is returned. They want to fix this so that the connection is established only once. Which modification should they make?

A.Override __new__ in DatabaseConnection to control instance creation and return the singleton from there, bypassing __init__ on subsequent calls.
B.Use the @staticmethod decorator on get_instance.
C.Use a global variable instead of a class attribute to store the singleton.
D.Move the connection initialization code out of __init__ and into a separate method that is called only once.
AnswerA

Overriding __new__ allows you to return the existing instance before __init__ is called, preventing repeated initialization.

Why this answer

Option A is correct because overriding __new__ allows the developer to control instance creation at the lowest level. By checking if the singleton already exists in __new__, they can return the existing instance without calling __init__ again, thus preventing the network connection from being established multiple times. This is the standard Pythonic way to implement a singleton that avoids reinitialization.

Exam trap

Python Institute often tests the distinction between instance creation (__new__) and instance initialization (__init__), trapping candidates who think that simply returning the same instance from a class method is enough to prevent reinitialization.

How to eliminate wrong answers

Option B is wrong because using @staticmethod on get_instance does not prevent __init__ from being called each time the class is instantiated; it only changes how the method is invoked. Option C is wrong because using a global variable instead of a class attribute does not solve the core issue: __init__ will still be called on every instantiation attempt, re-establishing the connection. Option D is wrong because moving the initialization code to a separate method does not prevent that method from being called multiple times if the singleton pattern is not properly enforced at the instance creation level.

136
MCQeasy

A developer wants to ensure that a class attribute is shared across all instances. Which approach should be used?

A.Use the @property decorator.
B.Define the attribute inside a method without using self.
C.Define the attribute in the class body, outside any methods.
D.Define the attribute inside __init__ using self.
AnswerC

Class attributes are defined in the class body and shared by all instances.

Why this answer

Option C is correct because defining an attribute in the class body, outside any methods, creates a class attribute that is shared across all instances. Class attributes are stored in the class's __dict__ and are accessible via the class or any instance, unless shadowed by an instance attribute.

Exam trap

Python Institute often tests the distinction between class attributes and instance attributes, and the trap here is that candidates may confuse defining an attribute inside __init__ with creating a shared attribute, not realizing that __init__ always creates instance-specific attributes.

How to eliminate wrong answers

Option A is wrong because the @property decorator is used to define a method that can be accessed like an attribute, typically for computed or controlled access, not for creating a shared class attribute. Option B is wrong because defining an attribute inside a method without using self creates a local variable that is not accessible outside that method and does not become a class or instance attribute. Option D is wrong because defining the attribute inside __init__ using self creates an instance attribute, which is unique to each instance and not shared across all instances.

137
MCQhard

Which of the following is true regarding Python's method resolution order (MRO) in multiple inheritance?

A.The MRO is computed using the C3 linearization algorithm, ensuring that each class appears before its parents and that monotonicity is preserved.
B.The MRO is always the same as the order of base classes specified in the class statement.
C.The MRO can be changed at runtime by modifying the __bases__ attribute of a class.
D.The MRO is determined by the order of base classes in the class definition, using a depth-first, left-to-right search without consideration of diamond inheritance.
AnswerA

C3 is correct.

Why this answer

Option A is correct because Python's method resolution order (MRO) is computed using the C3 linearization algorithm. This algorithm ensures that each class appears before its parents and that monotonicity is preserved, meaning the order of class precedence does not change when new subclasses are introduced. This is essential for resolving method calls in multiple inheritance scenarios, particularly with diamond inheritance.

Exam trap

The trap here is that candidates often assume the MRO follows a simple depth-first, left-to-right order (as in older Python versions or other languages), but Python's C3 algorithm can produce a different order to handle diamond inheritance correctly.

How to eliminate wrong answers

Option B is wrong because the MRO is not always the same as the order of base classes specified in the class statement; the C3 algorithm may reorder classes to satisfy monotonicity and local precedence order, especially in diamond inheritance. Option C is wrong because the MRO cannot be changed at runtime by modifying the __bases__ attribute; while __bases__ can be reassigned, the MRO is recalculated based on the new base classes using the C3 algorithm, but it is not directly mutable. Option D is wrong because the MRO is not determined by a simple depth-first, left-to-right search; Python explicitly abandoned that approach due to issues with diamond inheritance, and instead uses the C3 linearization algorithm to avoid inconsistent ordering.

138
MCQmedium

A team is using inheritance but wants to prevent a method from being overridden in subclasses. What Python feature can enforce this?

A.Use a private method with double underscore prefix (__method).
B.Use a @final decorator.
C.Use @staticmethod.
D.Use @abstractmethod.
AnswerA

Name mangling makes the method harder to override accidentally, though it can still be overridden with the mangled name.

Why this answer

Option A is correct because in Python, prefixing a method name with double underscores (e.g., `__method`) triggers name mangling, which renames the method to `_ClassName__method` at compile time. This prevents subclasses from accidentally overriding the method, as the mangled name is unique to the class where it is defined, effectively making it private and non-overridable in subclasses.

Exam trap

Python Institute often tests the misconception that `@final` is a built-in Python decorator for preventing method overriding, but Python does not enforce `@final` at runtime, making the double underscore prefix the correct answer for runtime prevention.

How to eliminate wrong answers

Option B is wrong because Python does not have a built-in `@final` decorator; it is not a standard Python feature (though it exists in some third-party libraries or type checkers like `typing.final` in Python 3.8+, but it is not enforced at runtime by the interpreter). Option C is wrong because `@staticmethod` defines a method that does not receive an implicit first argument (self or cls), but it does not prevent overriding in subclasses; a subclass can still define a method with the same name. Option D is wrong because `@abstractmethod` is used to declare a method as abstract, requiring subclasses to override it, which is the opposite of preventing overriding.

← PreviousPage 2 of 2 · 138 questions total

Ready to test yourself?

Try a timed practice session using only Oop questions.