Python Institute PCPP-32-101 Exam Dumps & Practice Test Questions
Which of the following best defines the concept of composition in object-oriented programming?
A. Composition enhances a class by modifying its existing components and introducing new ones.
B. Composition enables a class to contain other classes as part of its structure.
C. Composition is primarily used for reusability, whereas inheritance focuses on encapsulation.
D. Composition follows a "has-a" relationship and cannot be combined with inheritance.
Correct Answer: B
In object-oriented programming (OOP), composition is a fundamental design approach where one class contains references to objects of other classes to delegate tasks or share behavior. This design pattern promotes modular and reusable code and follows a “has-a” relationship, meaning that a class "has" one or more instances of other classes as part of its state or behavior.
For example, consider a Car class that uses an Engine class. Here, a Car has an Engine, which is a classic demonstration of composition. Rather than inheriting from Engine, the Car class simply contains it and uses its methods and properties. This is in contrast to inheritance, where a subclass inherits the behavior and attributes of a parent class, typically describing an “is-a” relationship (e.g., Dog is an Animal).
Let’s break down the options:
Option A is misleading. While composition does allow adding functionality through additional components, it does not modify existing ones. It simply combines objects in a structured way, each object maintaining its own encapsulated behavior.
Option B is correct. This statement rightly describes that a class using composition acts as a container for other classes. It emphasizes how classes are built by assembling other class instances, making systems more flexible and scalable.
Option C misrepresents both concepts. In fact, inheritance is primarily known for promoting code reuse by enabling subclasses to use code defined in a parent class. Encapsulation, on the other hand, is the principle of hiding internal details and exposing only the necessary interface — and is supported by both composition and inheritance.
Option D is incorrect because composition and inheritance are not mutually exclusive. A class can use both — it might inherit from a superclass and also use composition to include additional behavior from other classes. This mix allows for more adaptable and maintainable code structures.
In summary, composition allows a class to achieve functionality by containing instances of other classes, providing a flexible, modular alternative or complement to inheritance. Therefore, option B best describes the nature of composition in object-oriented programming.
When analyzing the Python code provided below, which statement most accurately reflects what happens when the code is executed?
A. This is a case of implicit exception chaining.
B. The code is invalid because OwnMath does not derive from Python's Exception class.
C. The code executes without raising any exceptions.
D. This demonstrates explicit exception chaining in Python.
Correct Answer: B
This Python snippet defines a class OwnMath and a function calculate_value that attempts to divide two numbers. If a division by zero occurs, a ZeroDivisionError is caught and a new exception OwnMath is raised using the raise ... from e syntax, which is designed for explicit exception chaining.
However, there's a critical error here. In Python, only classes that inherit from BaseException (or typically Exception) can be raised as exceptions. Since OwnMath is a plain class without extending from Exception, trying to raise it will result in a TypeError at runtime:
TypeError: exceptions must derive from BaseException
Let’s analyze each option:
Option A refers to implicit chaining, which occurs when an exception is raised during the handling of another, without explicitly using from. This code explicitly uses from e, so this option is incorrect.
Option B is correct. Python strictly requires that all exceptions be instances of classes derived from BaseException. Since OwnMath is not, attempting to raise it — even with the correct syntax — causes a runtime error. Thus, the code is erroneous and execution is interrupted.
Option C is incorrect. The script does not execute successfully. It triggers a ZeroDivisionError, then tries to raise OwnMath, but fails because OwnMath is not a valid exception class. Hence, the execution ends with a TypeError.
Option D is technically close — the intention is explicit chaining, and the syntax is correct — but since the exception class is invalid, this chaining fails. The concept of explicit chaining applies only when valid exception classes are used.
To correct the code, modify OwnMath to inherit from Exception:
With this fix, the raised OwnMath exception properly chains to the original ZeroDivisionError, and Python can handle the exception chain appropriately.
In conclusion, the original code is invalid due to an improper exception class definition. Therefore, option B is the most accurate answer.
In the following Python class, var1 is set at the class level, and self.name is initialized inside the constructor.
Which statement most accurately describes how the variables behave?
A. self.name is a class variable.
B. var1 is a global variable.
C. 'Excalibur' is assigned to an instance variable.
D. 'weapon' is assigned to an instance variable.
Correct Answer: C
To understand the behavior of the variables in this Python code snippet, let’s analyze what kind of variables are defined and where:
This class defines two different types of variables:
var1 is set directly within the class body, outside any methods.
self.name is initialized inside the __init__ method, which is the constructor for the class.
1. Class Variable — var1 = 'weapon':
This is a class-level variable, meaning it is shared among all instances of the Sword class. Any object created from Sword can access var1, but it is not unique to each instance. It belongs to the class itself. Importantly, this is not a global variable. Global variables are defined outside of any class or function, typically at the module level. Therefore, option B is incorrect.
2. Instance Variable — self.name = 'Excalibur':
This line creates an instance variable called name and assigns it the value 'Excalibur'. It is specific to each object created from the Sword class. Every time a new Sword object is instantiated, self.name will be initialized with 'Excalibur'. This makes option A incorrect because self.name is not a class variable.
3. Analysis of the Remaining Options:
Option C states that 'Excalibur' is the value assigned to an instance variable — this is correct. The assignment self.name = 'Excalibur' sets 'Excalibur' as the value for the instance-specific variable name.
Option D incorrectly claims that 'weapon' is assigned to an instance variable, when in fact it is set as a class variable (var1), accessible to all instances but not stored separately in each.
The key takeaway is the difference between class variables (shared across all instances) and instance variables (unique per object). In this code, var1 is a class variable and self.name is an instance variable. Since 'Excalibur' is directly assigned to self.name, C is the correct choice.
Three classes are defined where two include a run() method, and a loop attempts to call this method on instances of all three. What object-oriented programming principle is primarily demonstrated?
A. Serialization
B. Inheritance
C. Encapsulation
D. Polymorphism
Correct Answer: D
The goal here is to understand which object-oriented programming (OOP) concept is being demonstrated.
1. Behavior Overview:
Class A and Class C both define a run() method.
Class B does not define a run() method — it defines fly() instead.
The loop iterates over instances of each class and tries to call run() on them.
This will result in a runtime error (specifically, AttributeError) when it reaches the instance of Class B because that class doesn't implement the run() method. Nevertheless, this pattern is used to illustrate the concept of polymorphism.
2. What Is Polymorphism?
Polymorphism allows different types of objects to be treated the same way if they implement the same interface (in this case, the run() method). In Python, this is often referred to as duck typing: "If it walks like a duck and quacks like a duck..."
Here, both A and C respond to run() in their own way. The code attempts to treat all instances (regardless of class) uniformly by calling run(). This is a textbook example of dynamic (runtime) polymorphism — the actual method that gets executed depends on the object’s class at runtime.
3. Evaluating the Other Options:
A. Serialization: This has nothing to do with method calling or class structure. Serialization is about converting objects to a storable or transmittable format.
B. Inheritance: No inheritance relationships exist between these classes.
C. Encapsulation: This refers to restricting access to internal object data via methods — not relevant to the behavior demonstrated here.
D. Polymorphism: This is correct. The loop expects each object to support a run() method, demonstrating polymorphic behavior.
Even though the code causes an error due to class B lacking run(), the core idea behind this structure demonstrates polymorphism, where multiple classes provide the same interface. Hence, the best-fit answer is D.
Which of the following best describes the behavior of a decorator function that accepts arguments and wraps another function using multiple nested levels?
A. It demonstrates how a decorator can accept its own parameters.
B. It is an example of applying multiple decorators to a function.
C. It illustrates a decorator prone to infinite recursion.
D. The code contains a logical or syntax error.
Correct Answer: A
Explanation:
To understand this Python code, it’s essential to be familiar with how decorators function—particularly when they are designed to take arguments themselves. A typical decorator directly wraps another function, but when a decorator also takes input parameters, a layered structure is required. This structure includes an outer function that accepts the decorator arguments, a middle function that acts as the true decorator (taking the target function), and an inner wrapper function that manages execution and argument passing.
Outer Function – my_decorator(coating)
This level accepts an external argument (coating), such as in @my_decorator('sugar'). This means it's not a simple decorator but a parameterized decorator. It's the first sign that the decorator supports argument customization.
Middle Function – level1_wrapper(my_function)
This function serves as the actual decorator. It accepts the function to be wrapped (my_function) and returns the inner wrapper.
Inner Function – level2_wrapper(*args)
This function takes any number of positional arguments and passes them to the original function (my_function). This form is common to ensure the decorator can handle any type of function signature.
Return Chain
Each function returns the next: level2_wrapper is returned by level1_wrapper, which is returned by my_decorator. This structure forms a three-tier decorator capable of accepting arguments while still wrapping another function.
Now, evaluating the incorrect options:
B. This isn’t decorator stacking, which involves applying multiple @decorator lines above a function. That is unrelated to this pattern.
C. There’s no sign of infinite recursion; the inner function correctly invokes my_function, not itself.
D. The structure is syntactically and logically valid—there’s no error present.
In summary, this is a valid and clean example of a decorator that accepts arguments and wraps another function using nested closures. The correct term for this pattern is a parameterized decorator, and the correct answer is A.
What is the most accurate explanation regarding the function definition def f1(*arg, **args): in Python?
A. It is syntactically valid, even though the parameter names break typical naming practices.
B. The *arg parameter collects a variable number of unnamed arguments.
C. The function lacks a placeholder for unnamed arguments.
D. The definition is invalid—Python requires distinct parameter names like *args and **kwargs.
Correct Answer: D
Explanation:
In Python, function parameters can be defined to accept a flexible number of arguments using *args for positional arguments and **kwargs for keyword arguments. While these parameter names—args and kwargs—are only conventions, the underlying syntax rules require that parameter names be unique within the function signature.
This function will raise a SyntaxError when executed. Even though arg and args are technically different identifiers, Python enforces uniqueness in parameter names. More importantly, their closeness in spelling creates ambiguity, and Python treats this as a conflict.
*arg: This collects any number of positional arguments and stores them as a tuple.
**args: This collects any number of keyword arguments and stores them in a dictionary.
However, even though Python allows arbitrary names (e.g., *numbers, **options), each parameter must be distinctly named. The problem arises because arg and args are too similar, and Python considers the reuse—especially across * and **—as conflicting in terms of namespace handling and readability.
Clarifying the answer choices:
A. Incorrect. Although nonstandard names are allowed, this specific naming causes a syntax conflict.
B. While *arg does collect positional arguments, this doesn’t override the fact that the function is syntactically invalid.
C. Incorrect. The function is not missing placeholders; it defines both types, but the naming causes the issue.
D. Correct. A properly defined function using variable-length arguments should be written as def f1(*args, **kwargs):, or use any other two distinct names. For example: def f1(*data, **options): would be valid.
To summarize, the issue is not in the concept of variable argument handling, but rather in the naming collision that violates Python’s function definition rules. Therefore, D is the most accurate explanation.
In the given Python class Crossword, determine whether the code is valid and which method(s), if any, should be marked with the @classmethod decorator.
A. Only one constructor exists, so a class method isn't necessary
B. The getNumberOfCrosswords() function should be labeled with @classmethod
C. The code contains errors and is invalid
D. Both getNumberOfCrosswords() and isSolved() need to be class methods
Correct Answer: B
This question assesses your knowledge of different method types in Python—particularly class methods, instance methods, and static methods—and their appropriate use cases.
Let’s examine the components of the Crossword class one by one.
Constructor – __init__(self, height, width)
This is the standard object constructor that initializes instance variables such as height, width, and progress. It's correctly defined as an instance method using self. No changes are required here, so Option A is incorrect because it fails to recognize issues in other parts of the class.
isElementCorrect(word) method
This method is defined as a @staticmethod but attempts to call self.isSolved(). This is problematic because static methods do not receive self (the instance reference) and thus cannot access instance attributes or methods. While this is a logical mistake, it’s not a syntax error—Python will not reject the class as invalid, but it will fail at runtime if executed. Therefore, Option C is incorrect: the code is not structurally broken, just misused.
isSolved(self) method
This is an instance method, correctly using self to reference the instance’s progress attribute. It does not need to be a class method, as it operates at the object level. Thus, Option D is also wrong because isSolved() is properly defined.
getNumberOfCrosswords(cls) method
This method accesses a class-level variable named number_of_Crosswords. While it receives cls as its parameter, that alone does not make it a class method. In Python, you must explicitly decorate a class method with @classmethod; otherwise, it is treated as a regular instance method that incorrectly expects an instance. As such, the method will not function correctly without the decorator.
Only getNumberOfCrosswords() requires correction. It needs to be explicitly marked with the @classmethod decorator since it interacts with a class-level attribute. This correction ensures the method can be invoked properly without an instance and use cls appropriately. The static method misuse in isElementCorrect() is an implementation flaw but not a structural code error. Hence, the correct answer is B.
Review the Item class, which defines a special method named __ne__. What is the correct interpretation of this method’s purpose?
A. __ne__() is not a recognized built-in method in Python
B. The code contains structural errors
C. The method supports the unary negation operator, such as -a
D. The method defines behavior for the inequality operator !=
Correct Answer: D
This question focuses on your understanding of Python’s special methods—specifically those used for operator overloading.
Option A:
This is incorrect. The __ne__() method is indeed a built-in special method in Python. It's the logical complement of __eq__() and is specifically designed to handle inequality checks (i.e., !=). Saying it's not built-in reflects a misunderstanding of Python's data model.
Option B:
Also incorrect. Even though the body of __ne__() is represented with an ellipsis (...), this is valid Python syntax used as a placeholder. It does not raise a syntax error, nor does it make the code invalid. So, structurally, the code is correct.
Option C:
This option is wrong because the unary negation operator (e.g., -a) is managed by the __neg__() method in Python—not __ne__(). The names are similar but refer to completely different operations. This option confuses negation (-) with inequality (!=).
Option D:
This is the correct answer. The __ne__() method allows developers to define how two objects should be compared when using the != operator. If __ne__() isn’t defined, Python will fall back to not __eq__() as a default behavior. However, if the logic for equality and inequality are not simple complements, it’s necessary to explicitly implement both. By defining __ne__(), developers can customize how object comparisons using != should behave.
The __ne__() method is a standard built-in method that supports the use of the != operator for custom object comparisons. The class is not erroneous, and the method doesn’t relate to unary negation. The right explanation corresponds to Option D.
Which operator is used in Python to confirm whether two variables reference the same object in memory, returning a Boolean result?
A. == operator
B. isinstance() function
C. id() function
D. is operator
Correct Answer: D
Explanation:
In Python, it’s essential to distinguish between object identity and object equality—especially when writing automation scripts or performing system-level comparisons. This is often a critical concept for Fortinet engineers developing or analyzing FortiGate configurations with Python APIs or FortiManager scripts.
When two variables are compared, the nature of the comparison dictates the outcome. If we want to know whether two variables reference the same exact object in memory, we’re concerned with identity, not just equality.
Let’s go over each option:
Option A: == operator
This checks whether the values of two objects are equal, not whether they point to the same object. For example:
Option B: isinstance() function
This function is used to determine if a given variable is an instance of a specific class. It doesn’t compare objects to each other at all. Example:
This is unrelated to checking if two variables are the same object.
Option C: id() function
This function returns the unique identifier (memory address) of an object. Comparing id(a) == id(b) is a valid way to check identity, but it’s less readable and less Pythonic than using is. While technically correct, this isn’t preferred in production or automation scripts.
Option D: is operator
This is the most direct and Pythonic way to verify if two variables point to the same object in memory. It returns True only if both variables refer to the same memory location.
For network automation using Fortinet tools, using the is operator ensures clear and accurate validation when object references are critical (e.g., comparing device profiles or policy objects in memory).
Which statement about the use of the @property decorator in Python is incorrect?
A. It must be defined after the method that sets the encapsulated attribute.
B. It defines a method to access an attribute’s value like a regular property.
C. It makes the method’s name usable as the attribute name.
D. It should be declared before methods that modify or delete the property.
Correct Answer: A
Explanation:
In Python, the @property decorator allows developers to turn class methods into attributes that can be accessed like fields. This is particularly important when encapsulating configuration logic in automation frameworks, including Fortinet APIs or custom FortiOS handlers written in Python.
Let’s evaluate each option to find the false one.
Option A: Defined after the setter method
This is incorrect and thus the correct answer to the question. The @property decorator must be applied to the getter method first, before any setter or deleter is defined. This ensures proper property chaining. The correct order is:
If you attempt to define the setter before the getter, Python will raise an error. Therefore, the statement in Option A is false.
Option B: Defines a method for attribute access
This is true. The @property decorator marks a method as a getter, allowing users to access the result as if it were a regular attribute (obj.x instead of obj.get_x()).
Option C: Method’s name becomes the property name
Also true. The method decorated with @property will have its name used directly as the property name.
Option D: Should precede setter/deleter declarations
This is correct. The property must exist first before Python allows you to define corresponding setter and deleter methods using @propertyname.setter and @propertyname.deleter.
In Fortinet scripting scenarios, using @property can streamline class definitions for managing object properties such as firewall policies or AP configurations. It ensures clean syntax, logical encapsulation, and code maintainability.
Top Python Institute Certification Exams
Site Search:
SPECIAL OFFER: GET 10% OFF
Pass your Exam with ExamCollection's PREMIUM files!
SPECIAL OFFER: GET 10% OFF
Use Discount Code:
MIN10OFF
A confirmation link was sent to your e-mail.
Please check your mailbox for a message from support@examcollection.com and follow the directions.
Download Free Demo of VCE Exam Simulator
Experience Avanset VCE Exam Simulator for yourself.
Simply submit your e-mail address below to get started with our interactive software demo of your free trial.