Python Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesPython Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
Get inside! Sample the range of functionality easily built with JMSL Library for Time Series Data Analysis, Heat Maps, Portfolio Optimization, Monte Carlo Simulation, Stock Price Charting and more. Download Now!
  #1  
Old March 11th, 2003, 04:36 PM
vpopper's Avatar
vpopper vpopper is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2000
Location: Southern California
Posts: 73 vpopper User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 m 24 sec
Reputation Power: 9
calling function by symbolic reference

In perl, I can call an object method by using a variable, like this:

Code:
$obj = new MyObject;
$f = 'foo';

$obj->$f($args);


How can I do this in python? I know that I can do this, with a simple function:

Code:
def foo():
    print "OK"

ref = foo
ref()  # prints "OK"


But what about an instance method?

Reply With Quote
  #2  
Old March 11th, 2003, 04:38 PM
Strike Strike is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2001
Location: Houston, TX
Posts: 383 Strike User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 1 h 41 m 27 sec
Reputation Power: 7
Send a message via ICQ to Strike Send a message via AIM to Strike Send a message via Yahoo to Strike
Re: calling function by symbolic reference

Quote:
Originally posted by vpopper

But what about an instance method?

Not sure what you mean here.

But, if you want to be able to get a reference to the function via the name, simply use the globals() dict.

Code:
>>> def foo():
...     print "Found it!"
...
>>> globals()['foo']()
Found it!
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'foo': <function foo at 0x81612cc>, '__doc__': None}
>>> globals()['foo']
<function foo at 0x81612cc>
__________________
Debian - because life's too short for worrying.
Best. (Python.) IRC bot. ever.

Reply With Quote
  #3  
Old March 11th, 2003, 05:02 PM
vpopper's Avatar
vpopper vpopper is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2000
Location: Southern California
Posts: 73 vpopper User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 m 24 sec
Reputation Power: 9
Re: Re: calling function by symbolic reference

Quote:
Originally posted by Strike
Not sure what you mean here.


I mean an instance method:

Code:
class Foo:
    def __init__(self):
        pass
    def ok(self):
        print "OK"
    def notok(self):
        print "nope"

obj = Foo()

# say I have a list of strings that correspond to 
# methods in class Foo. The string (method) to 
# call is decided at runtime:

strings = ['ok', 'notok']

for s in strings:
    # I want to be able to call a method using 
    # the variable 's' as the name of the method
    obj.s()   # this won't work, no method 's'

Reply With Quote
  #4  
Old March 11th, 2003, 07:32 PM
ZeUs's Avatar
ZeUs ZeUs is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jan 2001
Location: St. George, Utah
Posts: 63 ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 31
There are a couple of ways to do this. One is very messy:

Code:
class Foo:
    def __init__(self):
        pass
    def ok(self):
        print "OK"
    def notok(self):
        print "nope"

obj = Foo()

strings = ['ok', 'notok']

for s in strings:
    obj.__class__.__dict__[s](obj)


Some explaination here - class instances like obj have several built in attributes in python. One useful one is __class__ which refers to the class it is an instance of, and another is __dict__ which is a dictionary of the class instance's attributes. These attributes are actually used by Python if you have an expression like this:

Code:
obj.ok()


In that case, Python looks in obj's __dict__ for an attribute called "ok" It won't find it there, as ok is not an attribute of obj, but rather of it's class, Foo. So next, it looks at obj's __class__ attribute's __dict__. It finds ok there and calls it, passing obj as the first argument. So, what we are doing above is handling all that ourselves. Messy.

Here's a more correct way:

Code:
class Foo:
    def __init__(self):
        pass
    def ok(self):
        print "OK"
    def notok(self):
        print "nope"

obj = Foo()

strings = ['ok', 'notok']

for string in strings:
    eval("obj.%s()" % string)


I don't even need to explain that one, do I?
__________________
Lucas Marshall

Reply With Quote
  #5  
Old March 11th, 2003, 08:50 PM
Strike Strike is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2001
Location: Houston, TX
Posts: 383 Strike User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 1 h 41 m 27 sec
Reputation Power: 7
Send a message via ICQ to Strike Send a message via AIM to Strike Send a message via Yahoo to Strike
I'd say the first way is more correct, not to mention safer. Because I'm assuming those strings aren't hardcoded anyway. So that means they depend somewhat on user interaction. And using eval() on strings that a user passes in is extremely dangerous (for example, what if I put in 'os.system("rm -rf /")' as the string somehow?) and should always be avoided. The dict method is the most appropriate.

Reply With Quote
  #6  
Old March 11th, 2003, 08:54 PM
ZeUs's Avatar
ZeUs ZeUs is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jan 2001
Location: St. George, Utah
Posts: 63 ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level)ZeUs User rank is Sergeant Major (2000 - 5000 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 31
I did mean "more correct in this instance." Obviously if you are dealing with user-input data, you wouldn't use eval. I should have clarified that.

Using eval is more "pythonish," from a readability standpoint, anyway.

Reply With Quote
  #7  
Old March 11th, 2003, 09:21 PM
vpopper's Avatar
vpopper vpopper is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2000
Location: Southern California
Posts: 73 vpopper User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 m 24 sec
Reputation Power: 9
Quote:
Originally posted by ZeUs
Using eval is more "pythonish," from a readability standpoint, anyway.


Thank you very much for your help!

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesPython Programming > calling function by symbolic reference


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump


Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 





© 2003-2008 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway