string to object?

G

Guy Robinson

Hello,

I have a class:

class foo:

def method1(self,args):
return 'one'
def method2(self):
return 'two'

and I have a series of strings li = ['foo.method1','foo.method2']

is there anyway I can do this?:

for l in li:
print l(args)

getattr('foo','method1') didn't work as 'foo' is invalid.

Any suggestions appreciated.

Guy
 
P

Peter Otten

Guy said:
I have a class:

class foo:

def method1(self,args):
return 'one'
def method2(self):
return 'two'

Do you really want to allow incompatible signatures for the methods?
and I have a series of strings li = ['foo.method1','foo.method2']

Does the part before the dot a class or an instance?
Does that instance/class vary over the list items?
is there anyway I can do this?:

for l in li:
print l(args)

getattr('foo','method1') didn't work as 'foo' is invalid.

That is because "foo" is a string, and strings don't have a method1()
method.
Any suggestions appreciated.
.... def method1(self, args):
.... return "one"
.... def method2(self, args):
.... return "too"
....
foo = Foo()
args = (99,)
calls = ["foo.method1", "foo.method2", "bar.method1"]
bar = Foo()
for instmethod in calls:
.... inst, method = instmethod.split(".")
.... print getattr(globals()[inst], method)(*args)
....
one
too
one
As you can see, various complications are possible. They might be avoided,
though, if you can describe your needs in plain English rather than with
the Python example, which happens to show too many loose ends.

Peter
 
L

Larry Bates

This does what you asked for, but I suspect
it isn't the best way to accomplish what you
want to do (just guessing). You can't call
a class, you must call an instance of a class
(e.g. ifoo below).

class foo:
def method1(self, *args):
return 'one'
def method2(self, *args):
return 'two'

ifoo=foo()
li=[ifoo.method1, ifoo.method2]

args=(1,)
for l in li:
print apply(l, args)


HTH,
Larry Bates
Syscon, Inc.
 
G

Guy Robinson

Peter and Larry,

To clarify things more (as I should have done yesterday):

incompatible signatures are not what I want and I do understand I need
to instance the class first so yes

class foo:
def method1(self, *args):
return 'one'
def method2(self, *args):
return 'two'
ifoo=foo()

is more like it. I have a number of classes with methods. For various
reasons the class.method to run is only available as a string. The
arguments arrive independently. So the question is how can I convert a
string to a class.method object for instancing?

Pseudo python:

s = 'foo.method1'
arg = []
sclass,smethod = string2class(s)
isclass = sclass.smethod(arg)

TIA,

Guy
This does what you asked for, but I suspect
it isn't the best way to accomplish what you
want to do (just guessing). You can't call
a class, you must call an instance of a class
(e.g. ifoo below).

class foo:
def method1(self, *args):
return 'one'
def method2(self, *args):
return 'two'

ifoo=foo()
li=[ifoo.method1, ifoo.method2]

args=(1,)
for l in li:
print apply(l, args)


HTH,
Larry Bates
Syscon, Inc.


Hello,

I have a class:

class foo:

def method1(self,args):
return 'one'
def method2(self):
return 'two'

and I have a series of strings li = ['foo.method1','foo.method2']

is there anyway I can do this?:

for l in li:
print l(args)

getattr('foo','method1') didn't work as 'foo' is invalid.

Any suggestions appreciated.

Guy
 
P

Peter Otten

Guy said:
To clarify things more (as I should have done yesterday):

incompatible signatures are not what I want and I do understand I need
to instance the class first so yes

class foo:
def method1(self, *args):
return 'one'
def method2(self, *args):
return 'two'
ifoo=foo()

is more like it. I have a number of classes with methods. For various
reasons the class.method to run is only available as a string. The
arguments arrive independently. So the question is how can I convert a
string to a class.method object for instancing?

Pseudo python:

s = 'foo.method1'
arg = []
sclass,smethod = string2class(s)
isclass = sclass.smethod(arg)

You are still concentrating too much on the technical details. For the
problem at hand, a plain english description would probably allow us to
come up with a better approach. Anyway, here's another variant:

class foo:
def method1(self, *args):
return "foo-method1%r" % (args,)
def method2(self, *args):
return "foo-method2%r" % (args,)

class bar:
def alpha(self, *args):
return "bar-alpha%r" % (args,)


def ensureInstance(klass, instCache={}):
try:
return instCache[klass]
except KeyError:
inst = instCache[klass] = globals()[klass]()
return inst

calls = ["foo.method1", "foo.method2", "bar.alpha", "foo.method2"]
args = (1,2,3)

for call in calls:
className, methodName = call.split(".")
inst = ensureInstance(className)
boundMethod = getattr(inst, methodName)
print boundMethod(*args)

If you need the classes as namespaces rather than to preserve state you
could make the methods static methods. The code would then become

class foo:
def method1(*args):
return "foo-method1%r" % (args,)
method1 = staticmethod(method1)

def method2(*args):
return "foo-method2%r" % (args,)
method2 = staticmethod(method2)

class bar:
def alpha(*args):
return "bar-alpha%r" % (args,)
alpha = staticmethod(alpha)


calls = ["foo.method1", "foo.method2", "bar.alpha", "foo.method2"]
args = (1,2,3)

for call in calls:
className, methodName = call.split(".")
staticMethod = getattr(globals()[className], methodName)
print staticMethod(*args)

Peter
 

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
474,201
Messages
2,571,049
Members
47,655
Latest member
eizareri

Latest Threads

Top