This probably has been answered somewhere, but sadly I don't really know which keywords to look for, so let me describe what I mean with "internal" for loop via this code snippet that I'm using:
#htf.measures(*(htf.Measurement("{}".format(i)) for i in ["v1", "v2"]))
Here, the for loop is used in a way that doesn't work the way I've known it to do (til now), example:
for i in x:
#Do something
It seems like a very handy way to use a for loop, so I'd like to understand how it works. I could imagine the * operator to have something to do with it, but as far as I can see its only a multiplicator, right?
This is what I am trying to do with the "new" for function:
tmp = [].append(*("P{}".format(id) for id in range(1, 5, 1)))
This returns an Error, saying append doesn't take 4 arguments, so I guess the for loop works somehow, but what I meant to do was to make it append 4 items.
Finally: I have two questions, 1. What is this for loop called and how can I google it, 2. how do I make the "append 4 times" thingy work?
Related
I know this question has been asked several times, I did find some post on this forum, but they don't seem to work, that's why I ask again.
Basically I have to create a number of a graph and the code is below
fig1 = go.Figure()
fig1.update_layout(showlegend = True, xaxis_title = "Time(s)")
and I would like to tidy it up using a for loop, therefore replacing the number with a variable, but doing something like below doesn't work
exec('"fig"+str(i) = go.Figure()')
I receive
SyntaxError: cant' assign to operator
How can I tidy this number of "same" code into a neat form, please?
*I also know that there is a danger using exec if this is not the way to go, what would be the better python way, please?
Edit:
This is my final working code, thanks for everyone's input
for i in range(5):
figures.update({f'fig{i}':go.Figure()})
eval('figures["fig'+str(i)+'"]').update_layout(showlegend = True, xaxis_title = "Time(s)")
In here, I can have control of the number of variable to be created (this code to be run. Also, putting it into the normal for loop form allows me to do more other things alone with the current figure. Lastly, the dictionary method allows a name to be linked to the figure so provides convenience
Why not try this:
figures = []
for i in range(loop):
figures.append(go.Figure())
#at this point you will now have n figures each of which you can reference
This way you still can find all of your plots if you know which order you made them in. Otherwise you could simply use a dict. I think its cleaner than making 10 diffrent variables.
I don't know how to phrase this, but my current structure uses recursion. So I call upon the same function when the looping within the function is finished, and use the results of the loop as an argument to continue the program with new data to work through.
So this function of mine spits out a number, among other things. I've assigned this resulting number from the function to a variable.
My gap in knowledge is however coming up short on the thought process/logic to a solution. Although it sounds simple. I've thought about maybe a way to over ride the original information with a global variable of the same name, but that doesn't seem to over ride it since at the top of the function is the variable declaration. I've also thought about using arguments with the *args method. But that isn't working either.
My function, has a loop in it. That requires variable X for example. On the loops first run, X already has a base number to work with. This X is used in the loop as part of the equation, after all the loops run through, I get a result and assign that to variable Y.
I need to essentially add Y to X, essentially making X = X + Y and then recall the function.
Trying this line of thinking, and declaring an updated variable doesn't work with this method because when I recall the function, it updates it to the base number again.
I've also explored if statements checking if the number is X and declaring the updated variable in the else statement otherwise. But that too is not providing a fruitful outcome.
What line of thinking, or method should I be applying to solve this problem?
I can explain more if necessary, me being a new to Python I've come up short on the search for the answer before posting, maybe because I don't know the terminology for this type of method to find such answers.
I appreciate your time in reading this, thanks!
def loop1Yo(f):
matrixDict = {}
timer = 0
x = f[0]
for element in f[1:]:
depTime = 1479215120 + xyzDuration ###(This part wouldnt work but I think explains what I am trying to do.)
directionResult = (depTime) + (element)
sortedMatrixList = sorted(matrixDict.items(), key=operator.itemgetter(1))
xyz = sortedMatrixList
xyzDuration = sortedMatrixList[0][1]
f = [x for x,_ in xyz]
print (f)
loop1Yo(f)
Suppose I have a function like the following:
bigrams=[(k,v) for (k,v) in dict_bigrams.items()
if k[:pos_qu]==selection[:pos_qu]
and (k[pos_qu+1:]==selection[pos_qu+1:] if pos_qu!=1)
and k[pos_qu] not in alphabet.values()]
I want to make the second condition, namely k[pos_qu+1:]==selection[pos_qu+1:] dependent from another if statement, if pos_qu!=1. I tried (as shown above) by including the two together into parentheses but python flags a syntax error at the parentheses
If I understand your requirement correctly, you only want to check k[pos_qu+1:]==selection[pos_qu+1:] if the condition pos_qu!=1 is also met. You can rephrase that as the following condition:
pos_qu==1 or k[pos_qu+1:]==selection[pos_qu+1:]
Putting this into your comprehension:
bigrams=[(k,v) for (k,v) in dict_bigrams.items()
if k[:pos_qu]==selection[:pos_qu]
and (pos_qu==1 or k[pos_qu+1:]==selection[pos_qu+1:])
and k[pos_qu] not in alphabet.values()]
Whenever you find yourself with a complex list comprehension, trying to figure out how to do something complicated and not knowing how, the answer is usually to break things up. Expression syntax is inherently more limited than full statement (or multi-statement suite) syntax in Python, to prevent you from writing things that you won't be able to read later. Usually, that's a good thing—and, even when it isn't, you're better off going along with it than trying to fight it.
In this case, you've got a trivial comprehension, except for the if clause, which you don't know how to write as an expression. So, I'd turn the condition into a separate function:
def isMyKindOfKey(k):
… condition here
[(k,v) for (k,v) in dict_bigrams.items() if isMyKindOfKey(k)]
This lets you use full multi-statement syntax for the condition. It also lets you give the condition a name (hopefully something better than isMyKindOfKey); makes the parameters, local values captured by the closure, etc. more explicit; lets you test the function separately or reuse it; etc.
In cases where the loop itself is the non-trivial part (or there's just lots of nesting), it usually makes more sense to break up the entire comprehension into an explicit for loop and append, but I don't think that's necessary here.
It's worth noting that in this case—as in general—this doesn't magically solve your problem, it just gives you more flexibility in doing so. For example, you can use the same transformation from postfix if to infix or that F.J suggests, but you can also leave it as an if, e.g., like this:
def isMyKindOfKey(k):
retval = k[:pos_qu]==selection[:pos_qu]
if pos_qu!=1:
retval = retval and (k[pos_qu+1:]==selection[pos_qu+1:])
retval = retval and (k[pos_qu] not in alphabet.values())
return retval
That probably isn't actually the way I'd write this, but you can see how this is a trivial way to transform what's in your head into code, which would be very hard to do in an expression.
just change the order
bigrams=[(k,v) for (k,v) in dict_bigrams.items()
if k[:pos_qu]==selection[:pos_qu] #evaluated first
and pos_qu!=1 #if true continue and evaluate this next
and (k[pos_qu+1:]==selection[pos_qu+1:]) #if pos_qu != 1 lastly eval this
as the comment mentions this is not a very pythonic list comprehension and would be much more readable as a standard for loop..
Lets say I have string which changes according to input:
expression=True
or
expression="a>1"
How can I use this variable as loop's expression in the way, so I won't need to repeat myself writing double loop. (and without using eval)?
Well pseudo code:
expression="a<2"
a=1
while expression:
print a,
a+=0.1
would print something like that:
1 1.1 1.2 <...> 1.9
EDIT:
No, I don't want to print numbers, I want to change loop condition(expression) dynamically.
CODE THAT works:
a="b==2"
b=2
while eval(a):
//do things.
Sample code:
somevar = 3
expression = lambda: somevar < 5
while expression():
...
if continue_if_even:
expression = lambda: (somevar % 2) == 0
...
Maybe using lambda might be the solution for your problem. And it's way better (more elegant, more bug-free, more secure) than using eval.
Of course, there are some very special cases where eval is still needed.
You're asking how to run user input. The answer is eval (or - not here, but generally - exec). Of course this is a bad answer, but it's the only answer. And if the only answer is bad, the question is bad.
What are you really trying to do? There are few programs (most notably programming language implementations) that need to give the user this much power. Yours propably doesn't. Chances are you can do what you want to do without running user input. But we need to know what you're trying to do to suggest viable alternatives.
You seem to want to change the condition of the loop dynamically, but you're not providing a very good use case so it's hard to understand why. If you just want to print the numbers between 1 and 1.9 with an increment of 0.1, there are easy ways to do that:
for x in xrange(10):
print "1.%d" % i
is one. There's no need for this dynamic expression magic. Also, you seem to want the same value (a) to have two very different meanings at the same time, both the value to print and the expression that controls how many values to print. That's perhaps a source of some of the confusion.
This question already has answers here:
Is it possible to implement a Python for range loop without an iterator variable?
(15 answers)
Closed 5 years ago.
I was wondering if it is possible to perform a certain number of operations without storing the loop iteration number anywhere.
For instance, let's say I want to print two "hello" messages to the console. Right now I know I can do:
for i in range(2):
print "hello"
but then the i variable is going to take the values 0 and 1 (which I don't really need). Is there a way to achieve the same thing without storing those unwanted values anywhere?
Needless to say, using a variable is not a big deal at all... I'm just curious.
The idiom (shared by quite a few other languages) for an unused variable is a single underscore _. Code analysers typically won't complain about _ being unused, and programmers will instantly know it's a shortcut for i_dont_care_wtf_you_put_here. There is no way to iterate without having an item variable - as the Zen of Python puts it, "special cases aren't special enough to break the rules".
exec 'print "hello";' * 2
should work, but I'm kind of ashamed that I thought of it.
Update: Just thought of another one:
for _ in " "*10: print "hello"
Well I think the forloop you've provided in the question is about as good as it gets, but I want to point out that unused variables that have to be assigned can be assigned to the variable named _, a convention for "discarding" the value assigned. Though the _ reference will hold the value you gave it, code linters and other developers will understand you aren't using that reference. So here's an example:
for _ in range(2):
print('Hello')
Others have addressed the inability to completely avoid an iteration variable in a for loop, but there are options to reduce the work a tiny amount. range has to generate a whole bunch of numbers after all, which involves a tiny amount of work; if you want to avoid even that, you can use itertools.repeat to just get the same (ignored) value back over and over, which involves no creation/retrieval of different objects:
from itertools import repeat
for _ in repeat(None, 200): # Runs the loop 200 times
...
This will run faster in microbenchmarks than for _ in range(200):, but if the loop body does meaningful work, it's a drop in the bucket. And unlike multiplying some anonymous sequence for your loop iterable, repeat has only a trivial setup cost, with no memory overhead dependent on length.
Although I agree completely with delnan's answer, it's not impossible:
loop = range(NUM_ITERATIONS+1)
while loop.pop():
do_stuff()
Note, however, that this will not work for an arbitrary list: If the first value in the list (the last one popped) does not evaluate to False, you will get another iteration and an exception on the next pass: IndexError: pop from empty list. Also, your list (loop) will be empty after the loop.
Just for curiosity's sake. ;)
This will print 'hello' 3 times without storing i...
[print('hello') for i in range(3)]
Sorry, but in order to iterate over anything in any language, Python and English included, an index must be stored. Be it in a variable or not. Finding a way to obscure the fact that python is internally tracking the for loop won't change the fact that it is. I'd recommend just leaving it as is.
for word in ['hello'] * 2:
print word
It's not idiomatic Python, but neither is what you're trying to do.
You can simply do
print 2*'hello'