call dict iterator function for each member in dict - python-2.7

I want to execute some function for each item from dictionary/List. I tried doing this but its not giving expected results. Here is the code.
class GroupDict(dict):
def iteritems(self):
# do some operation for every member in dict
print "in __iter__"
return super(GroupDict, self).iteritems()
a = GroupDict()
a['a'] = 0
a['b'] = 1
for key in a.iteritems():
print key
for this I am getting output
in __iter__
('a', 0)
('b', 1)
But expected is
in __iter__
('a', 0)
in __iter__
('b', 1)
I don't want to do operation inside the for loop but whatever I mention in the class should be executed for every member. Please help me with this.

iteritems() only gets called once, before the loop actually starts.
Let's see why. This loop:
for x in EXP:
do_something()
Roughly translates to:
it = iter(EXP)
while True:
try:
x = next(it)
except StopIteration:
break
do_something()
If you want to do something for every member, it is easier to do what you want by yielding from iteritems():
def iteritems(self):
for k, v in super(GroupDict, self).iteritems():
print "doing something with %s / %s" % (k,v)
yield k, v

Related

object returning memory location instead of value

So I have this class:
#!/usr/bin/python3
class MyClass(object):
def __init__(self, length):
self._list = length
def get(self, index):
try:
return self._list[index]
except IndexError:
return None
which takes in a list and returns a value, a list index I think. I am trying to get that value:
def my_function(a_list):
a_list = MyClass
for x in (10**p for p in range(1, 9)):
if a_list:
print(a_list)
def main():
length = my_function(MyClass([i for i in range(0, 543)]))
but I keep getting only the memory location of the list, I think this is supposed to return an int.
I am hoping this is a workable bit of code, but I am struggling, with the concept of passing an "object" to a class, it doesn't make any sense to me.
Here is a test I am supposed to use:
def test_large_list():
s_list = My_Class([i for i in xrange(0, 100000)])
assert len(s_list._list) == list_length(s_list)
Ok, Here is my full function that works, it is done, how od I do this so that the first line takes an argument
#!/usr/bin/python3
#def list_length(single_method_list): This is what I am supposed to work with
from single_method_list import SingleMethodList
def my_function(): # This is how I have done it and it works.
a_list = MyClass([i for i in range(0, 234589)])
for x in (10**p for p in range(1, 8)):
if a_list.get(x):
print("More than", x)
first = x
else:
print("Less than", x)
last = x
break
answer = False
while not answer:
result = (first + last)/2
result = int(round(result))
print(result)
if s_list.get(result):
first = result
print('first', result)
else:
last = result
print('last', result)
if s_list.get(result) and not s_list.get(result + 1):
answer = True
print(result + 1)
my_function()
I don't know what more I can give to explain where I am stuck, it is the OOP part of this that I don't know I need the same results here, just passing it to the function instead of creating it inside the function which I did in order to do the algorithm.
Well your class does something else.MyClass is designed to take a List at initialization, so the naming length is not a good idea.
The get() method of this class takes in a number and returns the element located at that particular index in the initialized self._list.
Your logic should be like:
def my_function(a_list):
a_list = MyClass(a_list)
...
def main():
length = my_function([i for i in range(0, 543)])
Just to clarify some misunderstanding that you might have.
Class does not return anything. It is a blueprint for creating objects.
What can return value is a method (function). For instance, if you want to write a method which returns length of some list:
def my_function(some_list):
return len(some_list)
Or in your case:
def my_function(a_list):
return len(a_list._list)
Note that you should not call your variables list. It's a built-in function in python which creates lists.
And as you can see there is another built-in function len in python which returns length of list, tuple, dictionary etc.
Hope this helps, although it's still a bit unclear what you're trying to achieve.

Return instead of print key in a Python list

I'm trying to create a function where each key in a list becomes an updatable parameter for another function.
I know that I can print all the keys in a list like this:
x = [a , b, c, d]
for key in x:
print(key)
But when I use the return statement like:
for key in x:
return key
It only returns a.
How can I iterate over a list and return each value every time the loop is performed.
Thank you very much.
A slight modification is ok:
def PrintKey(x):
for key in x:
yield key
When you use the return statement you leave the function, thus after the first loop the interpreter exits the function and returns the first index of your list.
Could you post more code?
I see no reason to put this in a function but if you need to, one option could be :
for i in range(len(list)):
storeSomeWhere = myFunction(list, i)
def myFunction(list, i):
return list[i]
For what? The for loop already hands you one value from the list at a time.
If you insist you can use a generator function that accepts the list and returns the next element each time it is used (until it runs out of elements, then a StopIteration exception is raised):
def gen(li):
for element in li:
yield element
li = [1, 2, 3, 4]
a = gen(li)
print(next(a))
# 1
print(next(a))
# 2
print(next(a))
# 3
print(next(a))
# 4
print(next(a))
Traceback (most recent call last):
File "main.py", line 63, in <module>
print(next(a))
StopIteration
But again, I don't see any reason to use this in your case. Simply use the value that the for loop hands you.

Determining if an int exist in a list, without using the "in" function

I need to get user input to generate a list of 8 numbers, but when they input a number that is already in the list print and error . Without using the in function to determine if its in the list. Here's what I have so far.
def main():
myList = range(9)
a= True
for i in myList:
while a == True:
usrNum = int(input("Please enter a number: "))
if usrNum != myList[i]:
myList.append(usrNum)
print(i)
main()
Error for above code,
Scripts/untitled4.py", line 18, in main
myList.append(usrNum)
AttributeError: 'range' object has no attribute 'append'
The issue seems to be your way of generating myList. If you generate it with myList = [range(9)] you'll get:
[[0, 1, 2, 3, 4, 5, 6, 7, 8]]
Try using simply:
myList = range(9)
Also, you need to change myList.append[usrNum] with myList.append(usrNum) or you'll get a:
TypeError: 'builtin_function_or_method' object has no attribute '__getitem__'
You could also use wim's suggestion instead of the != operator:
if myList.__contains__(usrNum):
myList.append(usrNum)
There are two ways you can go about this:
Loop through the list to check each element.
The in operator is effectively doing:
for each value in the list:
if the value is what you're looking for
return True
if you reach the end of the list:
return False
If you can add that check into your code, you'll have your problem solved.
Use an alternate way of tracking which elements have been added
Options include a dict, or bits of an int.
For example, create checks = {}. When you add an value to the list, set checks[usrNum] = True. Then checks.get(usrNum, False) will return a boolean indicating whether the number already exists. You can simplify that with a collections.DefaultDict, but I suspect that may be more advanced than you're ready for.
The first is probably the result your instructor is after, so I'll give you a simple version to work with and massage to fit your needs.
myList = []
while True:
usrNum = int(input())
found = False
for v in myList:
if usrNum == v:
found = True
if not found:
myList.append(usrNum)
else:
#number was already in the list, panic!
Most instructors will be more impressed, and hence award better grades, if you can figure out how to do something like method 2, however.
You could do something like this, modify as needed (not sure when/if you want to break when the user enters a number that is already in the list, etc.)
This prompts for user input until they enter an item that already exists in the list, then it prints a message to the user, and stops execution.
def main():
mylist = range(9)
while True:
usrNum = int(input("Please enter a number: "))
if existsinlist(mylist, usrNum):
print("{} is already in the list {}".format(usrNum, mylist))
break
else:
mylist.append(usrNum)
def existsinlist(lst, itm):
for i in lst:
if itm == i:
return True
return False
Perhaps the point of this homework assignment is to help you understand how an operator like in is more efficient to read (and write, and compile) than the explicit loop that I used in the existsinlist function.
Not sure if list-comperehension would be allowable in this case, but you also could've done something like this, without relying on the existsinlist helper function:
def main():
mylist = range(9)
while True:
usrNum = int(input("Please enter a number: "))
if [i for i in mylist if i == usrNum]:
print("{} is already in the list {}".format(usrNum, mylist))
break
else:
mylist.append(usrNum)
In this case, the result of the list-comprehension can be evaluated for truthiness:
An empty list like [] results if no matching value exists, and this will be considered False
A non-empty list will result if at least one matching value exists, and this will be considered True
Yet another option which short-circuits and may be preferable:
if any(usrNum == i for i in mylist)

Append/add sum to list

I am trying to append or add the sum of iterables through a range to an empty list. I was able to do it using a for loop:
list=[]
list_2=[]
def clique(n):
for i in range(n):
list.append(i)
list_2=sum(list)
print clique(4)
but everytime I try to do it within a function I get this error:
TypeError: range() integer end argument expected, got list.
the outputs is:
None
When you do print some_function(), the output is the return value of the function. If the function has no return statement, the return value is None by default. This is why print clique(4) prints None.
If you want print clique(4) to show the contents of list, then return list.
def clique(n):
for i in range(n):
list.append(i)
list_2=sum(list)
return list
try this:
list=[]
def clique(n):
for i in range(n):
list.append(i)
list_2=sum(list)
print 'list', list
print 'list_2', list_2
clique(4)

find all ocurrences inside a list

I'm trying to implement a function to find occurrences in a list, here's my code:
def all_numbers():
num_list = []
c.execute("SELECT * FROM myTable")
for row in c:
num_list.append(row[1])
return num_list
def compare_results():
look_up_num = raw_input("Lucky number: ")
occurrences = [i for i, x in enumerate(all_numbers()) if x == look_up_num]
return occurrences
I keep getting an empty list instead of the ocurrences even when I enter a number that is on the mentioned list.
Your code does the following:
It fetches everything from the database. Each row is a sequence.
Then, it takes all these results and adds them to a list.
It returns this list.
Next, your code goes through each item list (remember, its a sequence, like a tuple) and fetches the item and its index (this is what enumerate does).
Next, you attempt to compare the sequence with a string, and if it matches, return it as part of a list.
At #5, the script fails because you are comparing a tuple to a string. Here is a simplified example of what you are doing:
>>> def all_numbers():
... return [(1,5), (2,6)]
...
>>> lucky_number = 5
>>> for i, x in enumerate(all_numbers()):
... print('{} {}'.format(i, x))
... if x == lucky_number:
... print 'Found it!'
...
0 (1, 5)
1 (2, 6)
As you can see, at each loop, your x is the tuple, and it will never equal 5; even though actually the row exists.
You can have the database do your dirty work for you, by returning only the number of rows that match your lucky number:
def get_number_count(lucky_number):
""" Returns the number of times the lucky_number
appears in the database """
c.execute('SELECT COUNT(*) FROM myTable WHERE number_column = %s', (lucky_number,))
result = c.fetchone()
return result[0]
def get_input_number():
""" Get the number to be searched in the database """
lookup_num = raw_input('Lucky number: ')
return get_number_count(lookup_num)
raw_input is returning a string. Try converting it to a number.
occurrences = [i for i, x in enumerate(all_numbers()) if x == int(look_up_num)]