Validating Input Values
To learn more about the concepts covered in this lesson, check out the following:
00:00
Validating Input Values. One of the most common use cases of property()
is building managed attributes that validate the input data before storing or even accepting it as secure input.
00:14
Data validation is a common requirement in code that takes input from users or other information sources that you consider untrusted. Python’s property()
provides a quick and reliable tool for dealing with input data validation. Thinking back to that Point
example, you may require the values of .x
and .y
to be valid numbers.
00:36
Since your users are free to enter any type of data, you need to make sure that your Point
only accepts numbers. Here’s an implementation of Point
that manages this requirement.
01:05
The setter methods uses a try
… except
block that validates input data using the Python EAFP (easier to ask for forgiveness than permission) style. If the call to float()
succeeds, then the input data is valid, and you get Validated!
on your screen.
01:22
If float()
raises a ValueError
, then the user gets a ValueError
with a more specific message. Note that in this code, you use the syntax raise
… from None
to hide internal details related to the context in which you are raising the exception.
01:40
From the end user’s viewpoint, these details can be confusing and make your class look unpolished. Check out the section on the raise
statement in the documentation for more information about this topic.
01:58
The .y
property follows the same pattern as x
. It’s important to note that assigning the .x
and .y
properties directly in .__init__()
ensures that the validation also occurs during object initialization. Not doing so is a common mistake when using property()
for data validation.
02:29
Here’s how the Point
class works now.
02:48
If you assign .x
and .y
values that float()
can turn into floating-point numbers, then the validation is successful, and the value is accepted.
02:57
Otherwise, you get a ValueError
. This implementation of Point
uncovers a fundamental weakness of property()
, which you may have noticed.
03:13 You have repetitive code that follows specific patterns. This repetition breaks the DRY (Don’t Repeat Yourself) principle, so you would want to refactor this code to avoid it. To do so, you can abstract out the repetitive logic using a descriptor.
03:36
Here, you define Coordinate
as a descriptor that manages your data validation in a single place.
04:22
Point
now makes use of Coordinate
for .x
and .y
.
04:37 This code works just like the earlier implementation, and you can see it being tested on-screen.
05:16 In general, if you find yourself copying and pasting property definitions all around your code, or if you spot repetitive code, then you should consider using a proper descriptor.
05:27 In the next section, you’ll see an example using computed attributes.
Bartosz Zaczyński RP Team on Jan. 2, 2024
@jchurchi Perhaps reading the written tutorial on descriptors will help you understand what’s going on in the Coordinate
class better.
The
owner
is the class where the descriptor is used, and thename
is the class variable the descriptor was assigned to. (Source)
The owner
and name
attributes must be declared regardless of whether they’re used or not because they’re a part of the descriptor protocol and Python provides values through those attributes when it calls your .__set_name__()
method.
emru67 on March 23, 2024
It’s important to note that assigning the .x and .y properties directly in .init() ensures that the validation also occurs during object initialization. Not doing so is a common mistake when using property() for data validation.
I think that the previous ststement needs a deeper explanation or a reference to an article with a deeper explanation…I get the point but I don’t really understand it…
Become a Member to join the conversation.
jchurchi on Dec. 26, 2023
I’m having a difficult time understanding what is going on in the Coordinate object with the owner and name variables. the “owner” variable doesn’t even seem to ever get used.