How to access the name of a string converted into a variable?

569 views Asked by At

I'm working with Python in FreeCAD and to add properties (adjustable variables) to an object we use:

obj.addProperty("App::PropertyFloat","variable","variable label","variable explanation").variable = 2

Using a for loop I want to add multiple properties with multiple variable names. I read how to convert a string into a variable but I didn't find how to access that variable name. In my case: how to use it at the .variable position in my code above.

Say I have the code:

varName = []
for i in range(3):
    varName.append('variable%s' %i)
    exec("%s = %d" % (varName[i],2))

I know for example that I can use print variable0 to get the value 2. How can I access the name of variable0 and put it on the .variable position? I read about creating a list or dictionary of variables but you can only access the value of the variable, not its name right?

A list can be the input for this object and its contents should be assigned to the variable names. The output should look like this (but than suitable for any length of the input list):

obj.addProperty("App::PropertyFloat","variable0,"variable label","variable explanation").variable0 = input[0]
obj.addProperty("App::PropertyFloat","variable1,"variable label","variable explanation").variable1 = input[1]
etc.
3

There are 3 answers

0
ickby On

In FreeCAD dynamic properties added from python are exposed as standart python instance attributes. Therefore you can use the normal hasattr, getattr and setattr etc. Hence your loop could look like this:

varName = []
for i in range(3):
    varName = 'variable' + str(i)
    obj.addProperty("App::PropertyFloat", varName, "awesome label","best property ever")
    setattr(obj, varName, 1.234) 
    value = getattr(obj, varname)
0
tdelaney On

I'm no expert on FreeCAD so this is something of a guess, but..., it looks like addProperty takes a name, type and description for a variable and creates one with a default value for you. The examples show creation / update in one step, like in your example. The problem is what to do when you don't know the name of the variable in advance. In python, you handle "variable attribute names" with getattr and setattr. So, if you have a name and a value you can:

name = 'some_name'
value = 1
setattr(obj.addProperty("App::PropertyFloat", name, "variable label",
    "variable explanation"), name, value)

There are various ways to generate variable names. In your example,

for i in range(3):
    setattr(obj.addProperty("App::PropertyFloat", "variable%d" % i, "variable label",
        "variable explanation"), name, i)

Or maybe you already have them in a dict somewhere

for name, value in mydict.items():
    setattr(obj.addProperty("App::PropertyFloat", name, "variable label",
        "variable explanation"), name, value)

I am really puzzled by the FreeCAD property implementation. The property object should have a single well-known name to access it's value, not some tricky name-of-the-property thing.

0
Roel On

Thnx for you answer! However, for some reaseon the first example you showed doesn't assign a value to the generated variable0, variable1 and variable2. Using the dictionary worked! When I'm inserting for example a list of objects into the obj:

dict = {}
for i in range(len(objectList)):
    dict['object%d'%i] = objectList[i]
for name, value in dict.items():
    setattr(obj.addProperty("App::PropertyPythonObject", name, "object label", "object explanation"), name, value)

I think this can be useful to make assemblies, for example a loft that consist of a user specified amount of (2D) profiles.