Monarch
(Monarch)
February 24, 2024, 7:21pm
1
Working with an API response, I have 2 possible choices of handling the return and access but I’m lost on which one’s ideal:
# Example API Response
{
'title': 'Blade Runner',
'year': 1982
}
Option 1: property
class Movie:
def __init__(self, search):
self._search = search
def api_response(self):
response = requests.post(url)
@property
def title(self) -> str:
return response["title"]
@property
def year(self) -> int:
return response["year"]
Option 2: dataclass
@dataclass
class Movie:
title: str
year: int
class SearchMovie:
def __init__(self, search):
self._search = search
def api_response(self):
response = requests.post(url)
return Movie(title=response["title"], year=response["year"])
There was a more detailed Stackoverflow post here but I couldn’t really gauge a conclusion from it
MegaIng
(Cornelius Krupp)
February 24, 2024, 7:32pm
2
Almost always dataclass
. And that SearchMovie
class shouldn’t exists, at least not in it’s current form:
@dataclass
class Movie:
title: str
year: int
@classmethod
def from_api(cls, search):
url = url_from_search(search)
response = requests.post(url)
return Movie(...)
Or, if you have a proper API manager class:
class API:
def __init__(self, url=...):
self.base_url = url
self.session = requests.Session(...)
def search_movie(self, search) -> Movie:
response = self.session.post(self.build_url_for_search(search))
return Movie(...)
In general: attributes for things, properties for computed things, methods for actions.
2 Likes
Monarch
(Monarch)
February 24, 2024, 7:35pm
3
Thank you! Can you expand on the last bit?
In general: attributes for things, properties for computed things, methods for actions.
cameron
(Cameron Simpson)
February 25, 2024, 9:52pm
4
Properties look like attributes. They should not have side effects.
If something happens , it should look like a function/method call.
1 Like
chepner
(Clint Hepner)
February 26, 2024, 2:45pm
5
The most obvious reason to reject Option 1 has nothing to do with properties or dataclasses, but the fact that Movie.api_response
doesn’t use self
at all. It should be a class method, a static method, or a standalone function (IMO, in increasing order of appropriateness).
Whether Movie
exposes its title
and year
attributes publicly or via properties is an orthogonal question. The way properties work, you can start with a simple class (whether you use dataclasses.dataclass
to help define that class is almost irrelevant), and later replace the instance attributes with properties without changing the public interface of the class.
1 Like