Courseiva

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

ProtocolPort(s)EncryptionTransportPrimary Use
RADIUS1812 / 1813Password onlyUDPNetwork access control
TACACS+49Full packetTCPDevice administration
Diameter3868Full sessionTCP / SCTPCarrier / mobile networks
802.1X—EAP-basedLayer 2Port-based access control

TACACS+ encrypts the entire packet; RADIUS only encrypts the password field — a key exam distinction.

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 →

How Courseiva writes practice questions · Editorial policy

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.