GHPython component mysteriously changing list data from class?

Hello folks,

Let’s say I have the following code inside a GHPython component:

import Rhino.Geometry as rg
import random


TIME = 100
random.seed(2)

class MyClass:
    def __init__(self):
       self.my_list = []
    
    def update(self):
        pt = rg.Point3d(random.random(), random.random(), random.random())
        self.my_list.append(pt)


mc = MyClass()

time_list = []

for t in range(TIME): # moment in time
    mc.update()
    print mc.my_list
    time_list.append(mc.my_list)

a = time_list

The goal is to output the list of lists time_list, which includes a list of points, provided by the class MyClass for each moment in time. I have no problems converting the nested list to a tree, but my issue lies with how the component runs, at least I believe so.

If I output the nested list, all of its sublists are already populated with a TIME-number of points (here 100).
However, what I want is an increasing number of points per sublist over time. For example, at the first iteration of the for loop, only one point should be in the first sublist, than 2 points, after that 3, … and 100 points at iteration TIME-1 (here 99).

This way I want to keep track of what happens at each moment in time. Furthermore, I could probably animate the process by looping through the tree branches with a Timer and Counter combo.

I guess my problem stems from the refresh rate of the component itself, or something like that. When I print mc.m_list inside the for loop, just before appending it to the time_list, the printed output shows the right result (i-number of points per sublist). However, the sublists of the time_list after the for loop, all have TIME-number of points inside (here 100). How can that even be?

Hi this is a classic Python problem: you are not adding a copy of your list each time , you are adding a reference to your list. See this stackoverflow post for a range of possible solutions:

1 Like

Thanks @Dancergraham! I did not know that about Python lists. Now it works.

I have something similar I guess?

How can it be that my random.seed number is not callable?
I use more python scripts and also use classes within python, but just use one random.seed number. Do I have to insert the random.seed number in the class; or are the random.seed numbers of the different python scripts maybe in conflict with each other?

Sorry for my lack of information.
If I need to provide more information, please ask me. :slight_smile:

Does this happen too, if you replace the seed variable between the parentheses with a number?

Usually, the random seed is set after the import statements at the top of a Python script and applies to the whole script. I don’t believe that different components are conflicting, when you import the random module separately for each component and set each seed individually.
You see, the seed is set for each imported module, not as a global seed in grasshopper.

1 Like

Hmm this looks wrong. Which version of Rhino / GrassHopper are you using ? I think there is an error in the random module in some (all???) versions…

1 Like

In the beginning everything works, and then everything fireworks and get red.
I do not know how.

Everything is the latest version.

Yes, I thought so too. But, first, my other python scripts work with the seed, and then everything shuts down at this number to this script as shown in the image.

I do not know what happen when doing that.

YES, when I add a number like 2, the same thing happen.
If in a new script.

And print r.seed…?

1 Like

or do you have your own script called random.py ?

1 Like

@diff-arch @Dancergraham

This was even worse than the puzzle of the Ninentdo DS game The Legend of Zelda Phantom Hourglass where you have to literally close the DS to get through a puzzle.

I copied my script to a new grasshopper file. Somehow it worked. Just why? It took my hours. I still do not know what happened, but whatever. :dizzy_face:

….

I now read your comment of print.
That works too! Why?! How did you know!?
When doing r.seed(seed) again everything will stop working, but it works somehow.

No I do not have a script called random.py.

‘Copy and paste’ works also, and then I can use r.seed(seed) too again.

2 Likes

Works in what way? I was just wondering whether it would print an integer, for some unknown reason, because of the error message… :confounded:

Did you write r.seed = seed (or similar) anywhere in your GH file? Did you accidentally overwrite the .seed method?

Doing ‘it,’ whatever it is.

‘Me’ unable figuring out what is happening.

Using print.

Copied it to a new script.

As simple I can say, no have not write nor overwrite it.

1 Like

I get the same behaviour if I type r.seed = 4 in my python editor, run it, delete it and then type r.seed(4) I can’t see how to reset the editor

1 Like

i think you can open the python editor in Rhino, (editpythonscript), and go to tools->reset script engine.
also…without testing/looking at this directly…I wouldn’t use a variable name that is the same as a method…seed(seed) seems like a bad idea.

4 Likes

Strange - Ok so I tried opening the Rhino python editor, resetting as you suggest and then going back to grasshopper. Now if I type import random I get

Runtime error (MissingMemberException): ‘ScopeStorage’ object has no attribute ‘scriptcontext’
Traceback (most recent call last):
AttributeError: ‘ScopeStorage’ object has no attribute ‘scriptcontext’

1 Like

Yes from random import seed combined with an input named seed would also probably break things

Also keep in mind that your random with seed is not going to be repeatable like grasshoppers (you will not have repeatable results with the same seed) unlike Grasshoppers random which is repeatable with the same seed.

Setting a seed in Python’s random module should work the same as Grasshoppers (unless I’m misunderstanding something). This should produce the same result when repeatably ran in a GHPython component:

import random as rd
rd.seed(42)
print rd.random()

This won’t necessarily generate the same result across different Python implementations though (i.e. CPython and IronPython). Is believe IronPython implements .NET’s random functionality.

Also, remember to upload your files @ForestOwl, that would have helped debug this much faster I suspect :wink:

Also II: See this old thread regarding “phantom variables” in GHpython (i.e. what you likely experienced by assigned your seed as if it were a property, thereby overwriting the seed function to be an integer, then deleting the offending line of code, but the seed variable name still being that integer), and how to spook them out (i.e. close and re-open the Grasshopper definition).

2 Likes