Create object name from string value?

Gnarlodious

Usenet Archive
Joined
Jun 15, 2003
Messages
198
Reaction score
0
I want to declare several objects from names in a list:

objects=['object1', 'object2', 'object3', 'object4']
for objectName in objects:
objectName=classname

That fails, and so do these:

exec(objectName)=classname
eval(objectName)=classname

So how to make an object whose name is the value in the variable?

-- Gnarlie
 

Ben Finney

Usenet Archive
Joined
Jun 26, 2003
Messages
2,776
Reaction score
0
Gnarlodious writes:

I want to declare several objects from names in a list:

objects=['object1', 'object2', 'object3', 'object4']
for objectName in objects:
objectName=classname

Since (I presume) you are a newcomer to Python, it's best to learn the common style <URL:http://www.python.org/dev/peps/pep-0008/>. I will assume the above is written as::

object_names = ['object1', 'object2', 'object3', 'object4'] for object_name in object_names:
object_name = Class

That fails

Well, it succeeds (runs successfully). But I get what you mean: it fails to do what you expected.

So how to make an object whose name is the value in the variable?

This is almost certainly better done with a dictionary. Like so::

object_names = ['object1', 'object2', 'object3', 'object4'] objects = {} for object_name in object_names:
objects[object_name] = Class

There are shortcuts that can be used to create the dictionary without the separate list of names. But for now the above should make sense immediately and help you get to the meat of the problem.
 

Gnarlodious

Usenet Archive
Joined
Jun 15, 2003
Messages
198
Reaction score
0
Since (I presume) you are a newcomer to Python, it's best to learn the common style <URL:http://www.python.org/dev/peps/pep-0008/>.
Thanks for that.
This is almost certainly better done with a dictionary. Like so::

    object_names = ['object1', 'object2', 'object3', 'object4'] objects = {} for object_name in object_names:
        objects[object_name] = Class

And thanks for that too. I see it returns a list of objects, Python is very cool.

-- Gnarlie
 

Steven D'Aprano

Usenet Archive
Joined
May 7, 2005
Messages
9,709
Reaction score
0
I want to declare several objects from names in a list:

objects=['object1', 'object2', 'object3', 'object4'] for objectName in objects:
objectName=classname

That's the wrong way to handle the problem. Named objects are only useful if you know the name of the object when writing the code. Otherwise, how do you know what name to use in the code?

That fails, and so do these:

exec(objectName)=classname
eval(objectName)=classname

The right way to solve this problem is with a dictionary:

for name in ["object1", "object2", "object3"]:
d = {name: classname}
print d[name]

but for the record, the way to use exec is like this:

exec("object1 = classname")

But beware, exec is not only much slower than the alternatives, but it risks putting a serious security flaw in your software. As a general rule, 9 times out of 10 if you think you want exec, you don't.
 

Gnarlodious

Usenet Archive
Joined
Jun 15, 2003
Messages
198
Reaction score
0
That's the wrong way to handle the problem. Named objects are only useful if you know the name of the object when writing the code. Otherwise, how do you know what name to use in the code?

Thank you for the help. I am gathering the names of all *.plist files in a folder, creating objects named the filename, and accessing the data like this:

Data.Server.Config.BaseURL

Adding a .plist file would automatically create a plist dictionary object inside the Data module.
The right way to solve this problem is with a dictionary:

for name in ["object1", "object2", "object3"]:
    d = {name: classname}
    print d[name]

This works! However I end up saying:

d['Server'].Config.BaseURL

to get the data, when I should be saying:

Server.Config.BaseURL
but for the record, the way to use exec is like this:

exec("object1 = classname")

I failed to make that work. So back to the original question. How to make an instance named according to a string inside a variable? I guess it should be in the top-level namespace, not inside a list or dictionary.

-- Gnarlie
http://Gnarlodious.com/Gnarlodious
 

Alf P. Steinbach

Usenet Archive
Joined
Jul 5, 2003
Messages
7,960
Reaction score
0
* Gnarlodious:
That's the wrong way to handle the problem. Named objects are only useful if you know the name of the object when writing the code. Otherwise, how do you know what name to use in the code?

Thank you for the help. I am gathering the names of all *.plist files in a folder, creating objects named the filename, and accessing the data like this:

Data.Server.Config.BaseURL

Adding a .plist file would automatically create a plist dictionary object inside the Data module.
The right way to solve this problem is with a dictionary:

for name in ["object1", "object2", "object3"]:
d = {name: classname}
print d[name]

This works! However I end up saying:

d['Server'].Config.BaseURL

to get the data, when I should be saying:

Server.Config.BaseURL
but for the record, the way to use exec is like this:

exec("object1 = classname")

I failed to make that work. So back to the original question. How to make an instance named according to a string inside a variable? I guess it should be in the top-level namespace, not inside a list or dictionary.

I don't understand how you intend to use a variable whose name comes from dynamic data.

So I agree with Steven that it's the wrong way to handle the problem -- whatever the problem is!

But, if it can help:

Cheers,

- Alf
 

Tim Chase

Usenet Archive
Joined
Jan 12, 2006
Messages
1,707
Reaction score
0
Gnarlodious said:
for name in ["object1", "object2", "object3"]:
d = {name: classname}
print d[name]

This works! However I end up saying:

d['Server'].Config.BaseURL

to get the data, when I should be saying:

Server.Config.BaseURL

It sounds like you want a mapping of strings to class objects (not instances), so you can do something like

mapping = {
"object1": object1,
"object2": some_module.object2,
"object3": other_module.namespace.object3,
}

MyClass = mapping["object1"]
server = MyClass(initialization_params)
# the above two lines can be written as
# server = mapping["object1"](init_params)
print server.Config.BaseURL

-tkc
 

Adam Tauno Williams

Usenet Archive
Joined
Jan 12, 2010
Messages
188
Reaction score
0

Dave Angel

Usenet Archive
Joined
Mar 23, 2009
Messages
2,065
Reaction score
0
Gnarlodious said:
That's the wrong way to handle the problem. Named objects are only useful if you know the name of the object when writing the code. Otherwise, how do you know what name to use in the code?

Thank you for the help. I am gathering the names of all *.plist files in a folder, creating objects named the filename, and accessing the data like this:

Data.Server.Config.BaseURL

Adding a .plist file would automatically create a plist dictionary object inside the Data module.

The right way to solve this problem is with a dictionary:

for name in ["object1", "object2", "object3"]:
d =name: classname}
print d[name]

This works! However I end up saying:

d['Server'].Config.BaseURL

to get the data, when I should be saying:

Server.Config.BaseURL

but for the record, the way to use exec is like this:

exec("object1 =lassname")

I failed to make that work. So back to the original question. How to make an instance named according to a string inside a variable? I guess it should be in the top-level namespace, not inside a list or dictionary.

-- Gnarlie
http://Gnarlodious.com/Gnarlodious
I know you figure you have a specific list of files, and that they'll never conflict with the other global variables you've defined. But adding globals dynamically is "magic", and can lead to very obscure bugs. Suppose sometime in the future somebody adds another plist file with the same name as one of your functions?

Put it inside a dummy class, as follows:

That avoids the ["Server"] syntax, but still doesn't risk polluting your global namespace with arbitrary names. And in the example above, you'd be using plists.Server.Config.BaseURL

And if you must use the global namespace, you can simply do:
>>> globals["Server"] = 42
>>> Server
42

DaveA
 

Steven D'Aprano

Usenet Archive
Joined
May 7, 2005
Messages
9,709
Reaction score
0
The right way to solve this problem is with a dictionary:

for name in ["object1", "object2", "object3"]:
    d = {name: classname}
    print d[name]

This works! However I end up saying:

d['Server'].Config.BaseURL

to get the data, when I should be saying:

Server.Config.BaseURL

There are three moments in time that the programmer needs to care about:
when you write the code, when you compile the code, and when you run the code. In this case, the two relevant ones are write-time and run-time.

If you expect to be able to write

Server.Config.BaseURL

then that means that you MUST know the name "Server" at write-time. (Otherwise, how do you know to write "Server", instead of "MyServer" or "ServerSix"?) That means that the *name* Server isn't specified at runtime, but at write-time. Since you already know the name, then the right solution is to do something like:

Server = classname

and then refer to Server, just like you would do:

x = 45
print x+1

or similar.

But if you are getting the name "Server" from a config file at runtime, say something like this:

name=Server
class=classname
flag=True

then you can't write:

Server.Config.BaseURL

in your source code, because you don't know if it will be called "Server", or "MyServer" or "Server42", or "WebServe", or "Fred". In general, you don't even know how many servers there will be: there could be one, or none, or fifty. So you need a level of indirection, hence the dictionary.
 

Gnarlodious

Usenet Archive
Joined
Jun 15, 2003
Messages
198
Reaction score
0
Put it inside a dummy class, as follows:

This has been very educational, thank you for all the suggestions.
Here is the resulting code:

class Property: pass # example of a dummy class
Plist = Property # create a Plist object from the dummy class

# accumulate dictionary attributes based on every plist file dataFolder=os.path.dirname(__file__)+'/Data/' plistFiles=glob.glob(dataFolder+'*.plist')

for file in range(len(plistFiles)):
name=plistFiles[file].replace(dataFolder,'').replace('.plist','') setattr(Plist, name, Dict(plistFiles[file]).Config) # load the Plist object with the dictionary

This is a vast improvement over my previous system. Now I can call any plist item from anywhere on my website:

Data.Plist.Site.Trace

where "Site.plist" is the name of the Plist file. This is such an elegant system I'm surprised it is not implemented as part of Python.

-- Gnarlie
http://Gnarlodious.com/Gnarlodious
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
548,049
Messages
3,104,245
Members
248,133
Latest member
DujonT

Latest Threads

Top