You could do something like the code below. Altough, the cities will "share" the years. I don't know how efficient df.append is, but it works. Note how i changed the strings in the dictionary.
import pandas as pd
def calgary_weather(cities: (list, str), years: (list, str)) -> pd.DataFrame:
d = dict(calgary = "https://climate.weather.gc.ca/climate_data/bulk_data_e.html?format=csv&stationID=27211&Year={year}&Month=5&Day=1&timeframe=2&submit=Download+Data",
edmonton = "https://climate.weather.gc.ca/climate_data/bulk_data_e.html?format=csv&stationID=27793&Year={year}&Month=5&Day=1&timeframe=2&submit=Download+Data")
df = pd.DataFrame()
for city in cities:
for year in years:
url = d[city].format(year=year)
df = df.append(pd.read_csv(url))
return df
calgary_weather(['edmonton','calgary'], ['2016','2017','2018'])
But if you want to be able to pick the years more flexibly (although the years have to be a list of lists):
def calgary_weather2(cities: (list, str), years: (list, list, str)) -> pd.DataFrame:
d = dict(calgary = "https://climate.weather.gc.ca/climate_data/bulk_data_e.html?format=csv&stationID=27211&Year={year}&Month=5&Day=1&timeframe=2&submit=Download+Data",
edmonton = "https://climate.weather.gc.ca/climate_data/bulk_data_e.html?format=csv&stationID=27793&Year={year}&Month=5&Day=1&timeframe=2&submit=Download+Data")
df = pd.DataFrame()
for city, cityyears in zip(cities, years):
for year in cityyears:
url = d[city].format(year=year)
df = df.append(pd.read_csv(url))
return df
calgary_weather2(['edmonton','calgary'], [['2016','2017','2018'],['2012','2013']])