Re: dynamic construction of variables / function names

2006-03-30 Thread bruno at modulix
Steven D'Aprano wrote:
> Sakcee wrote:
> 
>> python provides a great way of dynamically creating fuctions calls and
>> class names from string
>>
(snip)

> Personally, I think the best way is: find another way to solve your
> problem.
> 

See Duncan's post for a pretty clean and pythonic solution. Another one
that may be more explicit and avoid messing with locals() or globals() is:

>> is it correct way, is there a simple way, is this techniqe has a name?
> 
> 
> I'm told that some people call this "dynamic programming",

In some other languages, it could be called 'metaprogramming', but this
is such a common idiom in Python that I'd just call this "programming" !-)

> but
> personally I call it "difficult to maintain, difficult to debug
> programming".

Oh yes ? Why so ? I've used such patterns hundreds of time, and it has
never been a problem so far.

Dynamically selecting the function to call given a name (as string) is
is a well-known programming pattern. I learned this in C, using a
hashtable to store names/function pointer pairs. And that's mostly what
the proposed solutions (the one based on globals() or locals() as well
as Duncan's class-based one) do - the main difference being that Python
offers the hashtable for free !-)

nb : I agree that the use of the global or local namespaces may not be
the best thing to do - better to use (any variant of) Duncan's solution
IMHO.

> (Before people get all cranky at me, I'm aware that it isn't *always*
> the Wrong Way to solve problems,  but it is a technique which is subject
> to abuse and can often be avoided by using function objects instead of
> function names.)

When you get the function name as user input, you cannot directly access
the function object.

And anyway, what do you think Python do when you call a function ?
Python namespaces *are* hash tables mapping symbols names (as string) to
objects (as pointers). I don't see much difference here.

(nb 2 : I agree that it is of course better to avoid 'manual' namespace
lookup whenever possible)



-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])"
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dynamic construction of variables / function names

2006-03-29 Thread Steven D'Aprano
Sakcee wrote:

> python provides a great way of dynamically creating fuctions calls and
> class names from string
> 
> a function/class name can be stored as string and called/initilzed
> 
> e.g
> 
> def foo(a,b):
> return a+b
> 
> def blah(c,d):
> return c*d
> 
> 
> list = ["foo", "blah"]
> 
> for func in list:
>   print func(2,4)
> 
> or similar items

Have you actually tried to do this? It doesn't work:

Traceback (most recent call last):
   File "", line 2, in ?
TypeError: object of type 'string' is not callable

(Also, it is poor practice to shadow the built-in list 
as you have.)

You are attempting to call "foo"(2, 4). Strings are not 
callable.

Two ways to actually do what you are trying to do is 
with eval and exec:

 >>> eval("foo(2, 3)")
5
 >>> exec("print foo(2, 3)")
5

but be aware of the possible security implications of 
eval and exec.

If you are calling instance methods, you can use getattr:

 >>> class Foo:
... def foo(self, x,y):
... return x+y
...
 >>> getattr(Foo(), "foo")(2, 3)
5

But the best way is, if possible, avoid this altogether 
and remember that functions are first-class objects in 
Python. Instead of doing this:

L = ["foo", "bar"]
for func in L:
 print eval(func + "(2, 3)")

do this:

L = [foo, bar]  # list containing function objects
for func in L:
 print func(2, 3)


> what is the way if the names of functions are some modification e.g

As far as I know, the only ways are: use eval or exec, 
or look in locals and/or globals:

 >>> func = locals().get("f" + "oo", None)
 >>> if callable(func):
... func(2, 3)
...
5

You can use globals() instead of locals(), but there 
may be issues with scoping rules that I can't think of.

Personally, I think the best way is: find another way 
to solve your problem.


> is it correct way, is there a simple way, is this techniqe has a name?

I'm told that some people call this "dynamic 
programming", but personally I call it "difficult to 
maintain, difficult to debug programming".

(Before people get all cranky at me, I'm aware that it 
isn't *always* the Wrong Way to solve problems, but it 
is a technique which is subject to abuse and can often 
be avoided by using function objects instead of 
function names.)


-- 
Steven.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dynamic construction of variables / function names

2006-03-29 Thread Duncan Booth
Sakcee wrote:

> python provides a great way of dynamically creating fuctions calls and
> class names from string
> 
> a function/class name can be stored as string and called/initilzed
> 
> e.g
> 
> def foo(a,b):
> return a+b
> 
> def blah(c,d):
> return c*d
> 
> 
> list = ["foo", "blah"]
> 
> for func in list:
>  print func(2,4)
> 
> or similar items

No, that doesn't work. To convert a string to a function name you have to 
look it up in a suitable namespace, or store a list of functions instead of 
a list of strings. So something like this would work:

 lst = [foo, blah]
 
 for func in lst:
  print func(2,4)


> 
> 
> what is the way if the names of functions are some modification e.g
> 
> def Newfoo(a,b):
> return a+b
> 
> def Newblah(c,d):
> return c*d
> 
> list = ["foo", "blah"]
> 
> for func in list:
>  print "New"+func(2,4)
> 
> or define a variable
> 
> "New"+list[0] = "First Funciton"
> 
> 
> I think ,   print "New"+func(2,4)  and "New"+list[0] = "First
> Funciton"
> 
> will not work,  either eval or exec should be used
> is it correct way, is there a simple way, is this techniqe has a name?
> 
One common way is to group the functions you want callable together in a 
class and then use getattr to access them.

class Commands:
  def Newfoo(self, a,b):
  return a+b
 
  def Newblah(self, c,d):
  return c*d

  def call(self, fname, *args. **kw):
  fn = getattr(self, "New"+fname)
  return fn(*args, **kw)

cmds = Commands()
lst = ["foo", "blah"]
for func in lst:
print cmds.call(func, 2, 4)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dynamic construction of variables / function names

2006-03-29 Thread Felipe Almeida Lessa
Em Qua, 2006-03-29 às 22:44 -0800, Sakcee escreveu:
> either eval or exec should be used
> is it correct way, is there a simple way, is this techniqe has a name?

eval and exec are insecure. Try looking at globals():

$ python2.4
Python 2.4.3c1 (#2, Mar 29 2006, 08:34:35)
[GCC 4.0.3 (Debian 4.0.3-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def Newfoo(a, b):
... return a+b
...
>>> def Newblah(c, d):
... return c*d
...
>>> list = ["foo", "blah"]
>>> for func in list:
... print globals()["New"+func](2, 4)
...
6
8
>>> # That was a bit confusing, let see in parts
... print globals()
{'Newblah': ,
 '__builtins__': ,
 'Newfoo': ,
 'list': ['foo', 'blah'],
 'func': 'blah',
 '__name__': '__main__',
 '__doc__': None}
>>> print globals()["New"+func]

>>> print globals()["New"+func](2, 4)
8
>>> # HTH,
...

-- 
Felipe.

-- 
http://mail.python.org/mailman/listinfo/python-list

Re: dynamic construction of variables / function names

2006-03-29 Thread limodou
On 29 Mar 2006 22:44:24 -0800, Sakcee <[EMAIL PROTECTED]> wrote:
> python provides a great way of dynamically creating fuctions calls and
> class names from string
>
> a function/class name can be stored as string and called/initilzed
>
> e.g
>
> def foo(a,b):
> return a+b
>
> def blah(c,d):
> return c*d
>
>
> list = ["foo", "blah"]
>
> for func in list:
> print func(2,4)
>
> or similar items
>
>
> what is the way if the names of functions are some modification e.g
>
> def Newfoo(a,b):
> return a+b
>
> def Newblah(c,d):
> return c*d
>
> list = ["foo", "blah"]
>
> for func in list:
> print "New"+func(2,4)
>
> or define a variable
>
> "New"+list[0] = "First Funciton"
>
>
> I think ,   print "New"+func(2,4)  and "New"+list[0] = "First
> Funciton"
>
> will not work,  either eval or exec should be used
> is it correct way, is there a simple way, is this techniqe has a name?
>
> thanks
>

You could get the function object from globals(), for example:

for func in list:
   f = globals().get("New"+func, None)
   if f and callable(f):
print f(2, 4)

--
I like python!
My Blog: http://www.donews.net/limodou
My Site: http://www.djangocn.org
NewEdit Maillist: http://groups.google.com/group/NewEdit
-- 
http://mail.python.org/mailman/listinfo/python-list


dynamic construction of variables / function names

2006-03-29 Thread Sakcee
python provides a great way of dynamically creating fuctions calls and
class names from string

a function/class name can be stored as string and called/initilzed

e.g

def foo(a,b):
return a+b

def blah(c,d):
return c*d


list = ["foo", "blah"]

for func in list:
print func(2,4)

or similar items


what is the way if the names of functions are some modification e.g

def Newfoo(a,b):
return a+b

def Newblah(c,d):
return c*d

list = ["foo", "blah"]

for func in list:
print "New"+func(2,4)

or define a variable

"New"+list[0] = "First Funciton"


I think ,   print "New"+func(2,4)  and "New"+list[0] = "First
Funciton"

will not work,  either eval or exec should be used
is it correct way, is there a simple way, is this techniqe has a name?

thanks

-- 
http://mail.python.org/mailman/listinfo/python-list