'How do I get a function to return the frequency of a specific item from a dictionary?
I trying to create a program that combines C++ and Python that opens and reads a text file of grocery items. The first function ListItemsPurchased works and it returns all items purchased along with their frequencies. However, I am currently working on a function called FrequencyOfItem. Once it is called, it is supposed to return the frequency of a specific item entered by the user in the C++ file and then passed on to the function in the Python file. But whenever I call the function, I get an error saying "Local variable 'item_frequency' referenced before assignment." Can someone help me with this?
C++ file
#include <Python.h>
#include <iostream>
#include <Windows.h>
#include <cmath>
#include <string>
using namespace std;
/*
Description:
To call this function, simply pass the function name in Python that you wish to call.
*/
void CallProcedure(string pName)
{
char* procname = new char[pName.length() + 1];
std::strcpy(procname, pName.c_str());
Py_Initialize();
PyObject* my_module = PyImport_ImportModule("setup");
PyErr_Print();
PyObject* my_function = PyObject_GetAttrString(my_module, procname);
PyObject* my_result = PyObject_CallObject(my_function, NULL);
Py_Finalize();
delete[] procname;
}
/*
Description:
To call this function, pass the name of the Python functino you wish to call and the
string parameter you want to send
*/
int callIntFunc(string proc, string param)
{
char* procname = new char[proc.length() + 1];
std::strcpy(procname, proc.c_str());
char* paramval = new char[param.length() + 1];
std::strcpy(paramval, param.c_str());
PyObject* pName, * pModule, * pDict, * pFunc, * pValue = nullptr, * presult =
nullptr;
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyUnicode_FromString((char*)"setup");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, procname);
if (PyCallable_Check(pFunc))
{
pValue = Py_BuildValue("(z)", paramval);
PyErr_Print();
presult = PyObject_CallObject(pFunc, pValue);
PyErr_Print();
}
else
{
PyErr_Print();
}
//printf("Result is %d\n", _PyLong_AsInt(presult));
Py_DECREF(pValue);
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
// clean
delete[] procname;
delete[] paramval;
return _PyLong_AsInt(presult);
}
/*
Description:
To call this function, pass the name of the Python function you wish to call and the
string parameter you want to send
*/
int callIntFunc(string proc, int param)
{
char* procname = new char[proc.length() + 1];
std::strcpy(procname, proc.c_str());
PyObject* pName, * pModule, * pDict, * pFunc, * pValue = nullptr, * presult = nullptr;
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyUnicode_FromString((char*)"setup");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, procname);
if (PyCallable_Check(pFunc))
{
pValue = Py_BuildValue("(i)", param);
PyErr_Print();
presult = PyObject_CallObject(pFunc, pValue);
PyErr_Print();
}
else
{
PyErr_Print();
}
//printf("Result is %d\n", _PyLong_AsInt(presult));
Py_DECREF(pValue);
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
// clean
delete[] procname;
return _PyLong_AsInt(presult);
}
// Displays a list of options to user
void displayMenu() {
cout << endl;
cout << "1: Produce a list of all items purchased in a day" << endl;
cout << "2: Produce a number respresenting how many times an item was purchased" <<
endl;
cout << "3: Produce a histogram listing all items purchased in a day" << endl;
cout << "4: Exit the program" << endl;
cout << "Enter your selection as a number 1, 2, 3, 4." << endl;
}
void menuSelection() {
int option;
string item;
do
{
displayMenu();
cin >> option;
if (option == 1) {
// Calls function from Python file
CallProcedure("ListItemsPurchased");
}
else if (option == 2) {
cout << "Enter an item: " << endl;
cin >> item;
// Calls function from Python file
cout << callIntFunc("FrequencyOfItem", item);
}
else if (option == 3) {
// Calls function from Python file
cout << callIntFunc("ItemHistogram", item);
}
else if (option == 4) {
cout << endl;
cout << "You have exited the application." << endl;
break;
}
else {
cout << "You have entered an invalid input." << endl;
}
} while (option != 4);
}
void main()
{
menuSelection();
}
Python file
import re
import string
def ListItemsPurchased():
frequency = {}
with open('GroceryList.txt') as file:
# Finds the frequency of each word in the text file
for word in file:
count = frequency.get(word,0)
frequency[word] = count + 1
# Allows us to see our keys
frequency_list = frequency.keys()
# Gets the word and its frequency
for words in frequency_list:
print (words, frequency[words])
file.close()
return None
def FrequencyOfItem(item):
frequency = {}
with open('GroceryList.txt') as file:
# Finds the frequency of each word in the text file
for word in file:
count = frequency.get(word,0)
frequency[word] = count + 1
# Allows us to see our keys
frequency_list = frequency.keys()
# Gets frequency of item
for words in frequency_list:
if words == item:
item_frequency = frequency[words]
return item_frequency
Solution 1:[1]
As @jarmod has suggested in a comment, you can fix your code by initializing item_frequency outside the for loop to avoid the error you're seeing:
def FrequencyOfItem(item):
frequency = {}
item_frequency = 0
with open('GroceryList.txt') as file:
# Finds the frequency of each word in the text file
for word in file:
count = frequency.get(word,0)
frequency[word] = count + 1
# Allows us to see our keys
frequency_list = frequency.keys()
# Gets frequency of item
for words in frequency_list:
if words == item:
item_frequency = frequency[words]
return item_frequency
Also, not sure if you are specifically attempting to roll your own frequency counting logic, but if not I thought I'd mention that in the collections module in Python there's a class called Counter that can help with this:
def FrequencyOfItem(item):
with open('GroceryList.txt') as file:
# Finds the frequency of each word in the text file
words = Counter(word for word in file)
return words[item]
UPDATED: Because there's no test file provided, I've created the following version of the above code (both your original approach and the Counter approach) with a hardcoded test case. To try it with your file, just change TESTING from True to False in two places:
def GetItemsFromFile():
words = []
with open('GroceryList.txt') as file:
for word in file:
words += word
return words
def GetItemsFromTestCase():
return ["Spinach", "Olives", "Spinach", "Olives", "Olives", "Spinach", "Spinach", "Spinach", "Gravy"]
def FrequencyOfItem(item):
frequency = {}
item_frequency = 0
TESTING = True # change to False to use with input file
groceryList = GetItemsFromTestCase() if TESTING else GetItemsFromFile()
for word in groceryList:
count = frequency.get(word,0)
frequency[word] = count + 1
# Allows us to see our keys
frequency_list = frequency.keys()
# Gets frequency of item
for words in frequency_list:
if words == item:
item_frequency = frequency[words]
return item_frequency
def FrequencyOfItem_2(item):
TESTING = True # change to False to use with input file
groceryList = GetItemsFromTestCase() if TESTING else GetItemsFromFile()
words = Counter(word for word in groceryList)
return words[item]
print(FrequencyOfItem("Spinach"))
print(FrequencyOfItem_2("Spinach"))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
