Set changed size during iteration - python

I'm new to python coming from a c++ background. I was just playing around with sets trying to calculate prime numbers and got a "Set changed size during iteration" error.
How internally does python know the set changed size during iteration?
Is it possible to do something similar in user defined objects?

The pythonic way to filter sets, lists or dicts is with list [or dict] expressions
your_filtered_set = set([elem for elem in original_set if condition(elem)])

It's trivial to do so with a user-defined object: just set a flag each time you modify the object, and have the iterator check that flag each time it tries to retrieve an item.
Generally, you should not modify a set while iterating over it, as you risk missing an item or getting the same item twice.

Related

Why do i get <map object at 0x0389DCD0> when using map

What i have understood so far from the map function is that it applies a given function to each item in an iterable and returns the list of the result.
def square(num):
return num**2
list_num = [1,2,3,4]
considering the above function and the list of numbers as an example.
if we: list(map(square,list_num)) we will get as an output [1,4,9,16].
now comes the part that i am not able to find a sensible explenation of, if i
print(map(square,list_num)) i will get as an output <map object at 0x038B0290>.
My question is, Why am i getting the memory location and not a list when i use the print() function or when use map(square,list_num).
map doesn't return a list. It returns a map object that lazily produces results as needed:
print(type(map(int, [1])))
<class 'map'>
It also doesn't override the stringify method which would produce pretty-printed results. That may be because that would require forcing the entire list to be evaluated, and if that's acceptable in your program, you probably shouldn't be using map in the first place; unless you're debugging, in which case use of list is probably fine unless you're dealing with an infinite list.
If you want a full-element print out, explicitly force it by placing it in a list before printing as you saw, or use a strict list production method like a list comprehension.

How is the for-loop able to use a variable that isn't defined yet

I'm new to coding and I'm a little confused. How/why can a for loop use a variable that isn't defined yet?
For example:
demond = {'green':'grass', 'red':'fire', 'yellow':'sun'}
for i in demond:
print(i)
Output:
green
yellow
red
In python, you don't need to declare variables. In C/C++/JAVA etc. you will have to declare them first and then use them.
Variables are nothing but reserved memory locations to store values.Based on the data type of a variable, the interpreter allocates memory and decides what can be stored in the reserved memory.Python variables do not need explicit declaration to reserve memory space. The declaration happens automatically when you assign a value to a variable.
There are two things that you need to keep in mind:
because Python is a weakly-typed language, you do not need to explicitly declare any variable to a certain object type. This is something you already know, and why you can assign things without having to state what type they will be.
For loop constructs do a lot of things in the background that you don't explicitly see. This means that although it doesnt LOOK like anything is being defined, it is.
With that in mind, I dont want to really explain how for loops work, because there are already answers available for that but the main point is that a for loop in python is the same as the following pseudo code.
#set up your iterable
demond = SOME_ITERABLE_OBJECT (this can be a list, string, dict, etc)
#this
for i in demond:
do_something(i)
#is the same as this
i = demond[0] # the first item in demond
do_something(i)
i = demond[1] # the second item in demond
do_something(i)
i = demond[2]
...
...
..
i = demond[n] # the last item in demond
do_something(i)
Now your follow up question may be this: what makes it so that, in your code, for i in demond sets i to equal to it's keys? Well that is just part of the design of python, specifically how dicts work. What the for loop is ACTUALLY doing is calling an iterables next() function until the iterable generator is done. Each iterable can have a different result from a for loop (see the first link).
NOTE:
In my code example, I am setting i = demond[some_index]. This looks like a list index grab but it is really meant to just show that is iterating through the list in some sort of order. IT IS PSUEDO CODE. Just keep that in mind.

How to map a function to each dictionary element?

I have a dictionary self.what_to_build
I am iterating on each element, and apply another method to each element using the following way:
[self.typeBuild(obj_type,dest) for obj_type,dest in self.what_to_build.items()]
It is my understanding this builds a list in memory, while there is no real impact on the program, I would like to refrain from this, I really do not need the list, just applying the method.
How would I do this same map, in the most Pythonic way, without doing a list comprehension
Just use a regular loop:
for obj_type,dest in self.what_to_build.items():
self.typeBuild(obj_type, dest)
A list comprehension indeed creates a list object with the return values of the self.typeBuild() calls, which is a waste of CPU and memory if you don't need those return values.
Don't get too hung up trying to write 'compact' code; readability is found in just the right level of verbosity.

Return multiple vars: list/tuple

I have a function which must return many values (statistics) for other function to interact with them. So I thought about returning them inside a list (array). But then I wondered: should I do so using a list (["foo", "bar"]) or using a tuple (("foo", "bar"))? what are the problems or differences there are when using one instead of the other??
Use a tuple. In your application, it doesn't seem like you will want or need to change the list of results after.
Though, with many return values you might want to consider returning a dictionary with named values. That way is more flexible and extensible, as adding a new statistic doesn't requiring modifying every single time you use the function.
If you do not need to edit the return value, use a tuple. The main difference is that lists can be edited.
See this: What's the difference between lists and tuples?

Correct way to iterate twice over a list?

What is the correct way to perform multiple iteration over a container? From python documentation:
Iterator - A container object (such as a list) produces a fresh new
iterator each time you pass it to the iter() function or use it in a
for loop. Attempting this with an iterator will just return the same
exhausted iterator object used in the previous iteration pass, making
it appear like an empty container.
The intention of the protocol is that once an iterator’s next() method
raises StopIteration, it will continue to do so on subsequent calls.
Implementations that do not obey this property are deemed broken.
(This constraint was added in Python 2.3; in Python 2.2, various
iterators are broken according to this rule.)
If I have this code:
slist = [1,2,3,4]
rlist = reversed(slist)
list(rlist)
#[4,3,2,1]
tuple(rlist)
#()
What would be the easiest and most correct way to iterate over 'rlist' twice?
rlist = list(reversed(slist))
Then iterate as often as you want. This trick applies more generally; whenever you need to iterate over an iterator multiple times, turn it into a list. Here's a code snippet that I keep copy-pasting into different projects for exactly this purpose:
def tosequence(it):
"""Turn iterable into a sequence, avoiding a copy if possible."""
if not isinstance(it, collections.Sequence):
it = list(it)
return it
(Sequence is the abstract type of lists, tuples and many custom list-like objects.)
I wouldn't stored the list twice, if you can not combine it to iterate once, then I would
slist = [1,2,3,4]
for element in reversed(slist):
print element # do first iteration stuff
for element in reversed(slist):
print element # do second iteration stuff
Just think of the reversed() as setting up a reverse iterator on slist. The reversed is cheap. That being said, if you only ever need it reversed, I would reverse it and just have it stored like that.
What is the correct way to perform multiple iteration over a container?
Just do it twice in a row. No problem.
What would be the easiest and most correct way to iterate over 'rlist' twice?
See, the reason that isn't working for you is that rlist isn't "a container".
Notice how
list(slist) # another copy of the list
tuple(slist) # still works!
So, the simple solution is to just ensure you have an actual container of items if you need to iterate multiple times:
rlist = list(reversed(slist)) # we store the result of the first iteration
# and then that result can be iterated over multiple times.
If you really must not store the items, try itertools.tee. But note that you won't really avoid storing the items if you need to complete one full iteration before starting the next. In the general case, storage is really unavoidable under those restrictions.
Why don't you simply reverse the original list in-place (slist.reverse()), then iterate over it as many times as you wish, and finally reverse it again to obtain the original list once again?
If this doesn't work for you, the best solution for iterating over the list in reversed order is to create a new reverse iterator every time you need to iterate
for _ in xrange(as_many_times_as_i_wish_to_iterate_this_list_in_reverse_order):
for x in reversed(slist):
do_stuff(x)

Categories