I am having trouble with a python class i wrote, the particular problem is in the parseData() function.
at the end of the function i have commented where the problem is. The problem is that when i finish the inner loop of the code towards the bottom of the parseData() function is run the value of self.listOfParsedWeatherData is correct, however once the scope falls out of the second loop the value of each element in self.listOfParsedWeatherData is a copy of the previous last element.
Basically when i check the value of the list within the scope of the second loop it would be something like [0, 1, 2, 3, 4, 5] but when i check the value of the same list outside of the second loop it it comes up as
[5, 5, 5, 5, 5, 5].
I am sure it has something to do with scopes or deep and shallow copies but I'm still fairly new to the python language and I'm not sure of some of the intricacies. Though i doubt the problem is something really complex.
Any help would be greatly appreciated the class is shown below and the object I'm inserting is a simple custom class that i wrote.
# imports
import pywapi # used to grab weather data from NOAA in a JSON format
import copy
from WeatherData import WeatherData # import custom weatherdata object
import pprint
pp = pprint.PrettyPrinter(indent=4) # set up pretty printer object
##
## Class used for grabing and parsing weather data from
## NOAA
##
class NOAAParser:
# initliazer for the NOAAParser class
def __init__(self):
# stores the list of json city data
self.listOfCityData = []
# A list of weatherData
self.listOfParsedWeatherData = []
##
## function to grab the weather and returns a JSON object of the weather data
##
## Parameters: self, dictionary of cities and their codes
##
def retrieveNOAAWeatherJson(self, cityCodes):
# loop through city codes and append them to a list of
cityData = []
# weather objects returned from pywapi
for key, value in cityCodes.iteritems():
cityData.append(pywapi.get_weather_from_noaa(value))
# set the list of city json data
self.listOfCityData = cityData
##
## This function parses the listOfCityData and returns a list
## of weatherData objects which can be displayed to the user
##
##
def parseData(self):
# check if the listOfCities has been populated
if not self.listOfCityData:
return False
else:
# create a new object of weather data
newWeatherData = WeatherData()
# loop over list and parse the data
for index in range(len(self.listOfCityData)):
# loop over the dictionary values in the list
for key, value in self.listOfCityData[index].iteritems():
# grab weather Description key: "weather" (String)
if key == "weather":
# print value
newWeatherData.weatherCondition = value
# grab the location key: "location" (String)
if key == "location":
# print value
newWeatherData.location = value
# grab temp key: "temperature_string" (String)
if key == "temperature_string":
# print value
newWeatherData.currentTemp = value
# grab Humidity key: "relative_humidity" (Int)
if key == "relative_humidity":
# print value
newWeatherData.humidity = value
# grab wind direction key: "wind_dir" (String)
if key == "wind_dir":
# print value
newWeatherData.windDirection = value
# grab last updated time key: "observation_time" (String)
if key == "observation_time":
# print value
newWeatherData.lastUpdated = value
# append the new weather data object to the list
self.listOfParsedWeatherData.append(newWeatherData)
## VALUE OF self.listOrParsedWeatherData is correct
## VALUE OF self.listOfParsedWeatherData is only the value of the last element
## of the previous self.listOfParsedWeatherData (incorrect)
# return success from the function
return True
This is happening because you only ever create a single instance of the WeatherData class, so you just keep updating that same one over and over again.
You just need to move the line newWeatherData = WeatherData() inside of your first for loop.
Related
I want to:
Take a list of lists
Make a frequency table in a dictionary
Do things with the resulting dictionary
The class works, the code works, the frequency table is correct.
I want to get a class that returns a dictionary, but I actually get a class that returns a class type.
I can see that it has the right content in there, but I just can't get it out.
Can someone show me how to turn the output of the class to a dictionary type?
I am working with HN post data. Columns, a few thousand rows.
freq_pph = {}
freq_cph = {}
freq_uph = {}
# Creates a binned frequency table:
# - key is bin_minutes (size of bin in minutes).
# - value is freq_value which sums/counts the number of things in that column.
class BinFreq:
def __init__(self, dataset, bin_minutes, freq_value, dict_name):
self.dataset = dataset
self.bin_minutes = bin_minutes
self.freq_value = freq_value
self.dict_name = dict_name
def make_table(self):
# Sets bin size
# Counts how of posts in that timedelta
if (self.bin_minutes == 60) and (self.freq_value == "None"):
for post in self.dataset:
hour_dt = post[-1]
hour_str = hour_dt.strftime("%H")
if hour_str in self.dict_name:
self.dict_name[hour_str] += 1
else:
self.dict_name[hour_str] = 1
# Sets bins size
# Sums the values of a given index/column
if (self.bin_minutes == 60) and (self.freq_value != "None"):
for post in self.dataset:
hour_dt = post[-1]
hour_str = hour_dt.strftime("%H")
if hour_str in self.dict_name:
self.dict_name[hour_str] += int(row[self.freq_value])
else:
self.dict_name[hour_str] = int(row[self.freq_value])
Instantiate:
pph = BinFreq(ask_posts, 60, "None", freq_pph)
pph.make_table()
How can pph be turned into a real dictionary?
If you want the make_table function to return a dictionary, then you have to add a return statement at the end of it, for example: return self.dict_name.
If you then want to use it outside of the class, you have to assign it to a variable, so in the second snipped do: my_dict = pph.make_table().
Classes can't return things – functions in classes could. However, the function in your class doesn't; it just modifies self.dict_name (which is a misnomer; it's really just a reference to a dict, not a name (which one might imagine is a string)), which the caller then reads (or should, anyway).
In addition, there seems to be a bug; the second if block (which is never reached anyway) refers to row, an undefined name.
Anyway, your class doesn't need to be a class at all, and is easiest implemented with the built-in collections.Counter() class:
from collections import Counter
def bin_by_hour(dataset, value_key=None):
counter = Counter()
for post in dataset:
hour = post[-1].hour # assuming it's a `datetime` object
if value_key: # count using `post[value_key]`
counter[hour] += post[value_key]
else: # just count
counter[hour] += 1
return dict(counter.items()) # make the Counter a regular dict
freq_pph = bin_by_hour(ask_posts)
freq_cph = bin_by_hour(ask_posts, value_key="num_comments") # or whatever
i my code i have created one function for generate pdf. it can be called more then 2 times in code but at 1st time it can be fetch my data but after second time they give me none value. how can i store my data in list.
i am using list.append but when method call 2nd time then it can be give me null value [that is stored default in database]
my code is:-
def GeneratePdf(request, type):
# data for testing
# global data
template = get_template("employeereport/appointment.html")
# real data
empid = request.GET.get('empid')
Date = request.GET.get('date')
a = []
a.append(Date)
print(a)
output:-
['07/13/2020']
[None]
expected output-
['07/13/2020',None]
declare the list before using it
a = []
def function():
a.append(1)
function()
function()
print(a)
How do I get dictionary from variable coin which I have define in my code. There are 32 elements in variable coin but I'm getting only one key and value which is TUSD in last line.
import requests
import json
r=requests.get('https://koinex.in/api/ticker')
koinexData=r.json()
koinexprice = koinexData['stats']['inr']
for coin in koinexprice:
print(coin)
coindata={}
coindata["koinex"]={
coin:{
"SellingPrice":koinexprice[coin]["highest_bid"],
"buyingPrice":koinexprice[coin]["lowest_ask"]
}
}
# data.append(coindata)
# print(data)``
# s = json.dumps(coindata)
print(s)
You keep overwriting your coindata dictionary inside the loop, which is why only the last value remains. The second issue with your code is that you keep overriding the coindata['koinex'] dictionary inside the loop. This should be a list not a dictionary because you'll keep adding values to it.
If you move the initialization code outside the loop, you will not have this problem:
coindata = {}
coindata['koinex'] = [] # this should be a list, not a dictionary
for coin in koinexprice:
print(coin)
# Create a temporary dictionary d to hold the data you want
# to add to coindata
d = {coin: {'SellingPrice': koinexprice[coin]['highest_bid'],
'buyingPrice': koinexprice[coin]['lowest_ask']}
}
coindata["koinex"].append(d) # add the new dictionary to the list
print(coindata)
I have a dictionary with various variable types - from simple strings to other nested dictionaries several levels deep. I need to create a pointer to a specific key:value pair so it can be used in a function that would update the dictionary and could be called like so:
dict_update(my_dictionary, value, level1key, *level2key....)
Data coming from a web request like this:
data {
'edited-fields': ['level1key-level2key-level3key', 'level1key-level2key-listindex', 'level1key'],
'level1key-level2key-level3key': 'value1',
'level1key-level2key-listindex': 'value2',
'level1key': 'value3'
}
I can get to the original value to read it like this:
for field in data["edited-fields"]:
args = field.split("-")
value = my_dictionary
for arg in args:
if arg.isdigit():
arg = int(arg)
value = value[arg]
print(value)
But have no idea how to edit it using the same logic. I can't search and replace by the value itself as there can be duplicates and having several if statements for each possible arg count doesn't feel very pythonic.
EXAMPLE:
data {
'edited-fields': ['mail-signatures-work', 'mail-signatures-personal', 'mail-outofoffice', 'todo-pending-0'],
'mail-signatures-work': 'I'm Batman',
'mail-signatures-personal': 'Bruce, Wayne corp.',
'mail-outofoffice': 'false',
'todo-pending-0': 'Call Martha'
}
I'd like to process that request like this:
for field in data['edited-fields']:
update_batman_db(field, data[field])
def update_batman_db(key-to-parse, value):
# how-to?
# key-to-parse ('mail-signatures-work') -> batman_db pointer ["mail"]["signatures"]["work"]
# etc:
batman_db["mail"]["signatures"]["work"] = value
batman_db["mail"]["outofoffice"] = value # one less level
batman_db["todo"]["pending"][0] = value # list index
The hard part here is to know whether an index must be used as a string form a mapping of as an integer for a list.
I will first try to process it as an integer index on a list, and revert to a string index of a mapping in case of any exception:
def update_batman_db(key, value):
keys = key.split('-') # parse the received key
ix = batman_db # initialize a "pointer" to the top most item
for key in keys[:-1]: # process up to the last key item
try: # descending in the structure
i = int(key)
ix = ix[i]
except:
ix = ix[key]
try: # assign the value with last key item
i = int(keys[-1])
ix[i] = value
except:
ix[keys[-1]] = value
I have a dictionary carrying key:value however it only saves the last iteration and discards the previous entries where is it being reset ?? This is the output from the ctr of iterations and the length of the dictionary
Return the complete Term and DocID Ref.
LENGTH:6960
CTR:88699
My code:
class IndexData:
def getTermDocIDCollection(self):
...............
for term in terms:
#TermDocIDCollection[term] = sourceFile['newid']
TermDocIDCollection[term] = []
TermDocIDCollection[term].append(sourceFile['newid'])
return TermDocIDCollection
The piece of code you've commented out does the following:
Sets a value to the key (removing whatever was there before, if it existed)
Sets a new value to the key (an empty list)
Appends the value set in step 1 to the new empty list
Sadly, it would do the same each iteration, so you'd end up with [last value] assigned to the key. The new code (with update) does something similar. In the old days you'd do this:
if term in TermDocIDCollection:
TermDocIDCollection[term].append(sourceFile['newid'])
else:
TermDocIDCollection[term] = [sourceFile['newid']]
or a variation of the theme using try-except. After collections was added you can do this instead:
from collections import defaultdict
# ... code...
TermDocIDCollection = defaultdict(list)
and you'd update it like this:
TermDocIDCollection[term].append(sourceFile['newid'])
no need to check if term exists in the dictionary. If it doesn't, the defaultdict type will first call to the constructor you passed (list) to create the initial value for the key