PCAP Object-Oriented Programming Practice Question
A developer wants to ensure that the 'radius' attribute of a Circle class is always non-negative. Which implementation using @property is correct?
⚠ Common 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.
Answer choices
Why each option matters
Answer the question above first, then reveal the full breakdown to understand why each option is right or wrong.
Correct answer & explanation
✓
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
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.
Answer analysis
Option-by-option breakdown
For each option: why learners choose it and why it is or isn't the right answer here.
- ✗
class Circle:\n def __init__(self, radius):\n self._radius = radius\n def radius(self):\n return self._radius
Why it's wrong here
Because radius is defined as a plain method, accessing obj.radius returns a bound method object, not the stored numeric value. To retrieve the radius you must call obj.radius(), which makes the attribute-style interface required by the spec impossible. Additionally, since there is no property setter, the _radius field is public-ish and can be assigned any value without validation, but the most immediate failure is the method shadowing the intended property.
- ✗
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
Why it's wrong here
Although the property setter raises ValueError for negative values, __init__ assigns to self._radius directly, completely bypassing the setter. As a result, a Circle can be created with a negative radius, violating the invariant the setter is supposed to enforce. The getter works, but the constructor never exercises the validation logic, so the class is not robust under its own public contract.
- ✓
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
Why this is correct
The correct pattern routes initial assignment through the property setter because __init__ says self.radius = radius, not self._radius = radius. Every time radius is set, regardless of whether it's during construction or later, the setter checks the value and raises ValueError for a negative input. The getter then simply returns the validated _radius, giving a clean, consistent public attribute.
- ✗
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
Why it's wrong here
With @property and no @radius.setter, radius is a read-only attribute, so the assignment self.radius = radius in __init__ raises AttributeError before any object is fully initialized. The separate set_radius method is not connected to the property; even manually calling it would not validate negative values, and it does nothing to make the property writable. Therefore the code fails at the outset and cannot provide the required attr-style radius.
Quick reference
AAA Protocol Comparison
| Protocol | Port(s) | Encryption | Transport | Primary Use |
|---|---|---|---|---|
| RADIUS | 1812 / 1813 | Password only | UDP | Network access control |
| TACACS+ | 49 | Full packet | TCP | Device administration |
| Diameter | 3868 | Full session | TCP / SCTP | Carrier / mobile networks |
| 802.1X | — | EAP-based | Layer 2 | Port-based access control |
TACACS+ encrypts the entire packet; RADIUS only encrypts the password field — a key exam distinction.
Go deeper
Related to this question
About these practice questions
One of 421 original PCAP practice questions on Courseiva, each with a full explanation and wrong-answer analysis — not exam dumps or protected exam content. Learn why practice questions differ from exam dumps →
JA
Written by Johnson Ajibi, MSc IT Security
Senior Network & Security Engineer · founder of Courseiva
This PCAP practice question is part of Courseiva's free Python Institute certification practice question bank. Courseiva provides original exam-style practice questions with explanations, topic-based practice, mock exams, readiness tracking, and study analytics to help learners prepare for the PCAP exam.