How To Get A For Loop To Affect Each Individual Object - python

folks! My question deals with a Python exercise that I'm currently trying to work out (well, to be more specific, the program is Autodesk Maya, but I'm using Python coding). The exercise involves taking a number of objects (spheres) contained in an array/list, and then using an increment variable to have them move in an offset animation. In other words, I want the first sphere to move, then the next spheres to move in a delayed time, then the next sphere with a more delayed time, etc.
The code that I have is as follows:
spheres = mc.ls(selection=True)
count=0
for i in range(len(spheres)):
count+=2
mc.selectKey(spheres)
mc.keyframe(edit=True, relative=True, timeChange=count)
print spheres(i)
The spheres are my objects, and as I said, I want the first to move normally in the timeline, then the next sphere to move with a delayed time of two, then the next to move with a delayed time of four, so on and so forth.
Any help with this would be much appreciated.
Thanks,
E

You're not actually setting the keyframe on the individual sphere; it looks like you're setting it on all spheres
Your for loop is generally bad form, but also less useful. Try changing it to this:
spheres = mc.ls(selection=True)
count=0
for sphere in spheres:
count += 2
mc.selectKey(sphere) # only selecting the one sphere!
mc.keyframe(edit=True, relative=True, timeChange=count)
print sphere # no need to look up the element
# which by the way should have been [i] not (i)
Output:
The keyframes were all lined up originally, but now offset by two frames each from the previous.

You haven't told us what the problem is, but I have a guess. (If I've guessed wrong, please elaborate your question, and I'll delete my answer.)
Are you getting an exception like this?
TypeError Traceback (most recent call last)
----> 1 print spheres(i)
TypeError: 'list' object is not callable
You claim that you have an "array/list" of spheres. If spheres is a list (or array or almost any other kind of collection) you index it using the [] operator. The () operator is used for function calls, not indexing. You're trying to call that list as if it were a function, passing it i as an argument, instead of trying to access that list as a sequence, getting the ith element.
To fix it:
print spheres[i]

Related

How can I access lists that are generated within a function?

So I'm a bit stuck with some python homework... this is my first question btw sorry if it's formatted wrong.
There is a function "co-ordinates_generator()" that produces a list of co-ordinates, [[x, y], [x, y], [x, y]] etc.
I must create a function that draws upon these co-ordinates and prints pins onto a map accordingly, using those co-ordinates.
I thought I could achieve this by doing:
def place_coords():
for point in co-ordinates_generator():
if point[0] == '1':
place_pin() etc. etc....
This DOES work, however when I do this, the lists produced by "co_ordinates_generator()" are generated TWICE. So in other words, two lists are printed to my screen instead of just a single one that I am supposed to use.
My only assumption is that because in the part:
for point in co-ordiantes_generator():
I call upon co-ordinates_generator() and doing so triggers the function, causing it print and then also print again when I call place_coords(). Is this correct
If so, or otherwise, how would I go about fixing this? I've tried just deleting the "for _ in ____" part entirely but then that creates all sorts of troubles like "'pin' is not defined". And also the fact that I've written a whole heap of for-each loops based around using the "for _ in ___" part.
Sorry it's a long one! And thank you in advance.
In absence of your function I guess you are not returning any value from the function.
def co-ordinates_generator():
.... # your existing code
.... # your existing code
.... # your existing code
return co-ordiantes_variable # whatever name you have defined for the desired result.
result = co-ordinates_generator()
for point in result:
.... # your existing code
.... # your existing code
.... # your existing code

Use all coordinates in a grid except with certain value

For a minesweeper I have created a board using python and pygame. When you flagged all bombs, you win. I have separate functions that contain the (randomised) bomb positions, and create the numbers around the bombs(on the proper coordinates). How do I make sure it checks the coordinates 0 to GRID_TILES(the maximum range) with the exception of all bomb locations? As those should remain flagged.
I got a function where when you click a bomb, you get shown the entire board. I want the same except for when the coordinates are in my BOMBS[].
def show_board():
for x in range(0,GRID_TILES):
for y in range(0, GRID_TILES):
"when" not in BOMBS:
draw_item(CELLS[x][y], x, y, (x+1,y+1))
I want to know if there is a "when" function, and how I could implement it.
If I understand you correctly, then the following should work:
If BOMBS is a list of tuples, then the following test should work if (x, y) not in BOMBS:
The in operator works on lists, as well as dicts, sets and tuples - anything that's iterable actually. In general, using it on lists is not such a great idea, because it needs to look through the whole list, in the worst case, to find an element. But for such small lists, it should not be a problem. If you find that it is, make BOMBS be a set and you should be good.

It keeps saying: TypeError: append() takes exactly one argument (0 given)

I'm trying to make a turtle/text based RPG (basically its a computerized d&d dungeonmaster) in python to impress my friends, my classmates and my teacher for my computing GCSE and my code seems alright; It draws out the room, enemies and any other things fine, has the text input printed in python shell. This is what it says:
File "E:\GCSE's\RPG No.1 Test code..py", line 22,
in chest contents+=list.append(chosen_loot)
TypeError: append() takes exactly one argument (0 given)
But this is the code segment that it's on about:
def chest():
contents=[]
chosen_loot=[]
for n in range(2):
loot=["Chestplate", "Vambraces", "Chausses", "Sabaton", "Zweihänder"]
chosen_loot+=random.choice(loot)
contents+=list.append(chosen_loot)
Please help! I've been up since 10:00 at night working on this thing!
Your syntax is completely wrong. First, chosen_loot+=random.choice(loot) adds a list and a string, which doesn't ordinarily work except with that augmented assignment (+=), which extends the list to include each character as a separate item.
>>> a = [1,2]
>>> a+= 'abc'
>>> a
[1, 2, 'a', 'b', 'c']
That line should be chosen_loot = random.choice(loot). You didn't even need two lists, so I don't know what was going on there.
Next, contents+=list.append(chosen_loot) isn't right at all. First, you're doing list.append, which could work if you called it properly, with the reference to the list you're interested in (contents in this case), but generally you want to do something like contents.append(chosen_loot). Next, you're concatenating with += on top of that. You've got several potentially useful bits of code, but you can't just mush them together and expect them to work. That line should just be contents.append(chosen_loot).
Next, you're trying to get two random items from a list. The way to do that is with random.sample.
contents = random.sample(loot, 2)
Finally, even that doesn't do anything, because it all gets thrown away when the function ends. You need to return something:
def chest():
return random.sample(["Chestplate",
"Vambraces",
"Chausses",
"Sabaton",
"Zweihänder"], 2)
That will produce two random items.

Python recursive call for list elements

I've tried to create a rough implementation of g-means to break a sample down into clusters where the clusters are gaussian using recursion, but my program seems to be going in only one direction (downward). The input values of this method were a data set, X, and a list of centers.
I'm having trouble figuring out how to solve the recursive bit of this method (the last for loop and beyond). After all of the recursive calls, I want to have a list of centers in C that can be returned to the main method.
So here's what happens in the last for loop. I'm iterating through a list of clusters (found using my cluster centers), clust, that contain all the values in each cluster. I run a test to see if there is significant evidence that the values in each cluster are gaussian. If there is evidence, then I want to remove that cluster center and add two new centers above and below. I then want to run through another recursive call and then evaluate these new center to see if the clusters they match to are gaussian or not.
The problem is my program is only evaluating the lower center bound. It seems to never reach the upper center as though the return statement means the program will stop the upper center from ever being reached.
Does anyone know how I can get my method to cover both the lower and upper sides of the cluster? (The for loop usually only makes 1 iteration ( for i in range(len(clust))) even when the length of clust = 2.
Another problem I'm having is that my method is simply overwriting the centers list instead of adding to it with each recursive call. Does anyone know how I can make recursive calls while appending to a list? I'm inserting items into the list and passing part of the list to a deeper level, but on return, I only get two values (both really low).
def gMean(X,C):
label=vq.kmeans2(X,np.array(C))
#take care of centers that do not match to clusters in kmeans2
while(len(set(range(len(C))))!=len(set((label[1])))):
emptyK=set(range(len(C)))- set(range(len(C))).intersection(set(label[1]))
emptyK=list(emptyK)
emptyK.reverse()
for i in range(len(emptyK)):
C.pop(emptyK[i])
label=vq.kmeans2(X,np.array(C))
#clust is a 2D list and holds all the values for given cluster
clust=[[] for x in range(max(label[1])+1)]
for i in range(len(label[1])):
for j in range(len(clust)):
if j==label[1][i]:
clust[j].append(X[i])
for i in range(len(clust)):
transClust=np.transpose(clust[i])
notGausFlag=False
for j in range(len(transClust)):
if stats.anderson(transClust[j])[1][2]<stats.anderson(transClust[j])[0]:
notGausFlag=True
if notGausFlag==True:
upper,lower=findCenter(clust[i],C[i])
C.pop(i)
C.insert(i,upper)
C.insert(i,lower)
for j in range(len(clust[i])):
clust[i][j]=clust[i][j].tolist()
clust[i]=np.array(clust[i])
return gMean(clust[i],C[i:i+2])
if notGausFlag==False:
return C
So I think I realize the error in my code I'm calling a recursive method and passing a cluster with two cluster centers, but when I go to step into the next level of the recursive loop, I only ever step in with the first center because the second one isn't reached in the for loop (for i in range(len(closet)):).
What I should have done was call the recursive method like this.
return gMean(clust[i],C[i])+gMean(clust[i],C[i+1])

Multi-recursive functions

I’d like to be pointed toward a reference that could better explain recursion when a function employs multiple recursive calls. I think I get how Python handles memory when a function employs a single instance of recursion. I can use print statements to track where the data is at any given point while the function processes the data. I can then walk each of those steps back to see how the resultant return value was achieved.
Once multiple instances of recursion are firing off during a single function call I am no longer sure how the data is actually being processed. The previously illuminating method of well-placed print statements reveals a process that looks quantum, or at least more like voodoo.
To illustrate my quandary here are two basic examples: the Fibonacci and Hanoi towers problems.
def getFib(n):
if n == 1 or n == 2:
return 1
return getFib(n-1) + getFib(n-2)
The Fibonacci example features two inline calls. Is getFib(n-1) resolved all the way through the stack first, then getFib(n-2) resolved similarly, each of the resultants being put into new stacks, and those stacks added together line by line, with those sums being totaled for the result?
def hanoi(n, s, t, b):
assert n > 0
if n ==1:
print 'move ', s, ' to ', t
else:
hanoi(n-1,s,b,t)
hanoi(1,s,t,b)
hanoi(n-1,b,t,s)
Hanoi presents a different problem, in that the function calls are in successive lines. When the function gets to the first call, does it resolve it to n=1, then move to the second call which is already n=1, then to the third until n=1?
Again, just looking for reference material that can help me get smart on what’s going on under the hood here. I’m sure it’s likely a bit much to explain in this setting.
http://www.pythontutor.com/visualize.html
There's even a Hanoi link there so you can follow the flow of code.
This is a link to the hanoi code that they show on their site, but it may have to be adapated to visualize your exact code.
http://www.pythontutor.com/visualize.html#code=%23+move+a+stack+of+n+disks+from+stack+a+to+stack+b,%0A%23+using+tmp+as+a+temporary+stack%0Adef+TowerOfHanoi(n,+a,+b,+tmp)%3A%0A++++if+n+%3D%3D+1%3A%0A++++++++b.append(a.pop())%0A++++else%3A%0A++++++++TowerOfHanoi(n-1,+a,+tmp,+b)%0A++++++++b.append(a.pop())%0A++++++++TowerOfHanoi(n-1,+tmp,+b,+a)%0A++++++++%0Astack1+%3D+%5B4,3,2,1%5D%0Astack2+%3D+%5B%5D%0Astack3+%3D+%5B%5D%0A++++++%0A%23+transfer+stack1+to+stack3+using+Tower+of+Hanoi+rules%0ATowerOfHanoi(len(stack1),+stack1,+stack3,+stack2)&mode=display&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=2&curInstr=0

Categories