Hi! The way, we are constructing an object instance currently is bypassing the city as an argument for
the location.
So we are passing the API key and a city name. Now, the Earth's surface, is not all cities and towns.
There are also places which are forests or mountains which are not associated with a name, but they
are associated with some geographic coordinates.
So latitude and longitude, every location on the Earth's surface has a latitude and longitude.
Therefore, we have to take this into account to provide the users with a good library that does not
work only with cities and towns.
So we have two different cases that we want to process in our init function.
And so we want init to take a decision whether it has to process the data based on a city or a location,
because if you go in here in the open weather API documentation, we saw that by city name
we constructed this type of URL and by location,
so by geographic coordinates instead of Q equal to city name, we use lat equal to that number and
lon equal to that particular number.
So the other URL would be not q, but lat equal to for example 40.1, and lon
equal to 3.4, and then don't forget the other & operator to provide the API key as well.
So that's how you do it.
And then if I try this URL
with requests dot get the URL there, and I'm going to directly get the Json data, so the dictionary you
see that it's working with lat and lon, and that's how you do it.
So we have two scenarios here.
URL based on the city and URL based on the latitude and longitude, which means that we have
to create our function to take a decision.
So we we're talking about conditional blocks if, elif, else.
Therefore, what I'm going to do is first I'm going to check if city as simple as that.
And then I'm going to ident that, so what I'm checking here is that if city simply checks, if the
city variable is not none.
Let me show you what I mean.
Let's say if city is none and you say if city,
print one, execute that and you get nothing
printed out, but if it has a value which is not none
and you execute that block again, this is going to be executed.
So in this case, what we can do is we can assigne none to city by default.
And so we check on a priority basis, so first we check if the user has passed a value of city such
as in this case here.
So if city has a value such as Valencia, for example, then we are going to construct the URL based
on a city location.
So with this particular item here. If the user happens to pass lat equal to 4.1
for example, and lan equal to 3.2, that means the city will have a value of none.
Therefore, this will not be executed, as you saw in the case of this.
So if city was none of this was not executed, but we want to execute something else out.
Elif lat. Since this is a pair, I'm going to do lat
and lon.
In that case, we want to get that URL indented.
In here, so that is the URL with lat and lon, then don't forget to replace these values, these
costants with the actual names of the variables.
So lat there.
So this lay is this one in here.
And this lat is part of the URL, same for lon, so 3.4, delete that curly brackets and
lon and also we do the same for the API key.
Delete that and curly brackets API key.
This way we have all three placeholders in the string to be replaced by the corresponding variables.
Then we carry on with that same procedure as here above.
So we copy and paste the requests using this URL.
So, either this or this will be executed, but not both, and then we get the data stored in the self.data
attribute.
As a dictionary using r.json and we also need an else statement here, which would be the case
when the user didn't enter any city or any lat and lon coordinates, which means that city would
be equal to none since it has a default value of none and so would be latitude and longitude.
Therefore, this would not be true and this would not be executed.
This would not be true either.
It would be false and these would not be executed.
Therefore, whatever we have here is going to be executed in the case when the user doesn't pass the
city or let and lon.
So maybe we want to show a message to the user, provide either a city or lat and lon arguments, close
the quotes, close the parentheses, and now I'll try the code.
Let me delete these two unnecessary lines so we don't have multiple print functions printing out output
there.
We only want to print out the output of next 12 hours method.
So I'm going to remove that.
Also that line and this is a code that we have.
So I'm going to execute the code now, given this object instantiation with these two, lat and lon values.
And apparently we have an error.
Let's read it without panicking, so key error list and it's happened in this line, line 21, which was
in here.
So it seems like this self.data dictionary doesn't have a key name to list.
Therefore, the first thing I want to do in order to find out the error is I want to check what really
this self.data dictionary is.
So I want to print it out just before the line where the error occurred.
So the error occurred in this line.
I want to print out to use a print function in this line, so I'm going to execute it again.
And this time we're going to get this message so that the output of the print function and again the
error, of course, so this is dictionary we are getting instead of getting the data, are we are getting
a code 401 and a message, invalid API key.
Please see this link.
Well, actually, I didn't change the API key, so I don't think there is an issue with the API key.
I can verify that by passing city so I know where the problem is.
But I want to show you the process of troubleshooting a program when it doesn't work.
So I want to actually.
Excludes the API key issue.
I don't think that is the issue that, as you can see, we get the data correctly here with the same
API key.
But using Madrid, you can also see that the other dictionary printed out by self data, so the complete
data have a code of 200, which means successful.
So it's working fine with a city name.
Why it doesn't work with latitude and longitude?
Well, the next thing you could do to try out would be to print out the URL.
If it's being constructed correctly, so just after constructing the URL there in the elif lat
and lon, you print out the URL and see how it looks like.
So that's the URL and now we're going to see that
the URL is being passed together with the variables, so the variables somehow are not being replaced
with values.
The reason is that I didn't put the F here. Now with the F there.
That makes the shrink a dynamic string.
And that means we are going to get the data correctly, as you can see here, 200 this time, successful
message, alright, it's working.
So now I can remove this print function and this one in here. These were just print functions for troubleshooting.
Now back to our main purpose.
So, the code works with the city when we pass a city.
It works when we pass a latitude and longitude.
And what about if there is no argument for location at all?
What's going to happen?
So we get an error. First, we get a message, it says, that provide either a city or let and lon arguments
because of this line in here.
So neither this, nor that block who was executed, this block here was executed.
But we have an error, we don't simply have the message, we have an error, which says attribute error,
"weather" object has no attribute data in line 21.
So it seems like weather is self.
So whether dot... So, whether the object that we have instantiated because you know that self is actually
the instantiated object, the object we are creating, whether in this case.
So whether it doesn't have data as attributes.
Well, but we actually did assign a Delta attributes to whether, we assigned it in here.
Right.
And also here.
Well, we did, but these blocks were not executed.
That means self.data was not defined at all, therefore, what's happening here is that only this
line is executed, so that object is instantiated like that.
But then when Python goes to execute this line, so it calls the next_12_hours methods, and it realizes
that self.data is not defined.
No, I don't like this kind of error because it doesn't actually describe the very root of the problem.
The issue, the problem, the real problem here, the actual problem is that the user didn't pass
any location, any city, lat, or lon.
But we want to tell the user the real problem.
So we are at a library developer and we don't want to just say the weather object has no attribute data
because that's not a very helpful information.
So using print functions to you that something is not working, it's not a good idea.
The good idea is to raise an error instead of printing something.
And I'm going to teach you that in the next video. See you.