By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,715 Members | 768 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,715 IT Pros & Developers. It's quick & easy.

adding methods at runtime and lambda

P: n/a
I was messing around with adding methods to a class instance at
runtime and saw the usual code one finds online for this. All the
examples I saw say, of course, to make sure that for your method that
you have 'self' as the first parameter. I got to thinking and thought
"I have a lot of arbitrary methods in several utility files that I
might like to add to things. How would I do that?" And this is what I
came up with:
def AddMethod(currObject, method, name = None):
if name is None: name = method.func_name
class newclass(currObject.__class__):pass
setattr(newclass, name, method)
return newclass()

And lets say I have a utility function that can check if a drive
exists on my windows box called HasDrive. I can add that like this:

superdict = addm(dict(), lambda self, d: myUtils.HasDrive(d),
"hasdrive")

and then I can call

superdict.HasDrive('c')

lambda makes it possible to add any random function because you can
use it to set self as the first parameter. I've found several real
uses for this already. My big question is, will something like this be
possible in python 3000 if lambda really does go away? I've not heard
much about lambda, reduce, etc. lately but I know Guido wanted them
out of the language.

Is there a better way to do this today than to use lambda? It seemed
the simplest way to do this that I could find.

May 3 '07 #1
Share this Question
Share on Google+
9 Replies


P: n/a
In the above example 'addm' should be 'AddMethod'

superdict = AddMethod(dict(), lambda self, d:
myUtils.HasDrive(d),"hasdrive")

May 3 '07 #2

P: n/a
Mike wrote:
I was messing around with adding methods to a class instance at
runtime and saw the usual code one finds online for this. All the
examples I saw say, of course, to make sure that for your method that
you have 'self' as the first parameter. I got to thinking and thought
"I have a lot of arbitrary methods in several utility files that I
might like to add to things. How would I do that?" And this is what I
came up with:
def AddMethod(currObject, method, name = None):
if name is None: name = method.func_name
class newclass(currObject.__class__):pass
setattr(newclass, name, method)
return newclass()

And lets say I have a utility function that can check if a drive
exists on my windows box called HasDrive. I can add that like this:

superdict = addm(dict(), lambda self, d: myUtils.HasDrive(d),
"hasdrive")

and then I can call

superdict.HasDrive('c')

lambda makes it possible to add any random function because you can
use it to set self as the first parameter. I've found several real
uses for this already. My big question is, will something like this be
possible in python 3000 if lambda really does go away? I've not heard
much about lambda, reduce, etc. lately but I know Guido wanted them
out of the language.

Is there a better way to do this today than to use lambda? It seemed
the simplest way to do this that I could find.
You don't absolutely require lambda.

def add_self(afun):
def _f(self, *args, **kwargs):
return afun(*args, **kwargs)
return _f

superdict = addm(dict(), add_self(myUtils.HasDrive), "hasdrive")

James
May 3 '07 #3

P: n/a
ici
On May 3, 10:52 pm, Mike <msu...@comcast.netwrote:
I was messing around with adding methods to a class instance at
runtime and saw the usual code one finds online for this. All the
examples I saw say, of course, to make sure that for your method that
you have 'self' as the first parameter. I got to thinking and thought
"I have a lot of arbitrary methods in several utility files that I
might like to add to things. How would I do that?" And this is what I
came up with:

def AddMethod(currObject, method, name = None):
if name is None: name = method.func_name
class newclass(currObject.__class__):pass
setattr(newclass, name, method)
return newclass()

And lets say I have a utility function that can check if a drive
exists on my windows box called HasDrive. I can add that like this:

superdict = addm(dict(), lambda self, d: myUtils.HasDrive(d),
"hasdrive")

and then I can call

superdict.HasDrive('c')

lambda makes it possible to add any random function because you can
use it to set self as the first parameter. I've found several real
uses for this already. My big question is, will something like this be
possible in python 3000 if lambda really does go away? I've not heard
much about lambda, reduce, etc. lately but I know Guido wanted them
out of the language.

Is there a better way to do this today than to use lambda? It seemed
the simplest way to do this that I could find.
from win32com.client import Dispatch as CreateObject

class HDDs(list):
def __init__(self):
fso = CreateObject('Scripting.FileSystemObject')
for d in fso.Drives:
if d.DriveType == 2: # Fixed
list.append(self, d.DriveLetter)

if __name__ == "__main__":
drv_list = HDDs()
for d in drv_list:
print d

try:
# Found
print drv_list.index('P')
except ValueError:
# Not Found
print "P: Not Exists!"

May 3 '07 #4

P: n/a
En Thu, 03 May 2007 16:52:55 -0300, Mike <ms****@comcast.netescribió:
I was messing around with adding methods to a class instance at
runtime and saw the usual code one finds online for this. All the
examples I saw say, of course, to make sure that for your method that
you have 'self' as the first parameter. I got to thinking and thought
"I have a lot of arbitrary methods in several utility files that I
might like to add to things. How would I do that?" And this is what I
came up with:
I don't see the reason to do that. If you have a function that does not
use its "self" argument, what do you get from making it an instance method?
If -for whatever strange reason- you want it to actually be a method, use
a static method:

pydef foo(x):
.... print "I like %r" % x
....
pyclass A(object): pass
....
pya = A()
pyA.foo = staticmethod(foo)
pya.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 1 argument (0 given)
pya.foo("coffee")
I like 'coffee'
pyA.foo("tea")
I like 'tea'

--
Gabriel Genellina
May 4 '07 #5

P: n/a
On May 3, 11:25 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
En Thu, 03 May 2007 16:52:55 -0300, Mike <msu...@comcast.netescribió:
I was messing around with adding methods to a class instance at
runtime and saw the usual code one finds online for this. All the
examples I saw say, of course, to make sure that for your method that
you have 'self' as the first parameter. I got to thinking and thought
"I have a lot of arbitrary methods in several utility files that I
might like to add to things. How would I do that?" And this is what I
came up with:

I don't see the reason to do that. If you have a function that does not
use its "self" argument, what do you get from making it an instance method?
If -for whatever strange reason- you want it to actually be a method, use
a static method:

pydef foo(x):
... print "I like %r" % x
...
pyclass A(object): pass
...
pya = A()
pyA.foo = staticmethod(foo)
pya.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 1 argument (0 given)
pya.foo("coffee")
I like 'coffee'
pyA.foo("tea")
I like 'tea'

--
Gabriel Genellina
staticmethod makes the function available to the whole class according
to the docs. What if I only want it to be available on a particular
instance? Say I'm adding abilities to a character in a game and I want
to give a particular character the ability to 'NukeEverybody'. I don't
want all characters of that type to be able to wipe out the entire
planet, just the particular character that got the powerup.

May 4 '07 #6

P: n/a
Mike wrote:
staticmethod makes the function available to the whole class according
to the docs. What if I only want it to be available on a particular
instance? Say I'm adding abilities to a character in a game and I want
to give a particular character the ability to 'NukeEverybody'. I don't
want all characters of that type to be able to wipe out the entire
planet, just the particular character that got the powerup.
Static methods are for specialists, you don't need them. But then, your
initial post looked like you were just exploring the possibilities...

You can

- have the Character.nuke_everybody() method check a self._can_nuke_eb flag
- subclass the Character class with a NukingChar subclass and make only one
instance of that class
- add an instancemethod to one Character instance

The simpler the approach you take the smarter you are ;)

Peter
May 4 '07 #7

P: n/a
On May 4, 2:05 pm, Peter Otten <__pete...@web.dewrote:
Mike wrote:
staticmethod makes the function available to the whole class according
to the docs. What if I only want it to be available on a particular
instance? Say I'm adding abilities to a character in a game and I want
to give a particular character the ability to 'NukeEverybody'. I don't
want all characters of that type to be able to wipe out the entire
planet, just the particular character that got the powerup.

Static methods are for specialists, you don't need them. But then, your
initial post looked like you were just exploring the possibilities...
Yeah, I'm just poking around.
>
You can

- have the Character.nuke_everybody() method check a self._can_nuke_eb flag
I don't like this one because it would require me to know every
ability everybody might ever have up front.
- subclass the Character class with a NukingChar subclass and make only one
instance of that class
A possibility, I guess, but does this then mean I would need a new
class for every type of character? Probably not, but you would at
least need types grouped by general class, kind of like D&D characters
(Fighter, Magic User, etc.). It makes it harder for anybody to learn
anything they want.
- add an instancemethod to one Character instance

The simpler the approach you take the smarter you are ;)

Peter
I just realized in working with this more that the issues I was having
with instancemethod and other things seems to be tied solely to
builtins like dict or object. I remember at some point just doing
something like:

x.fn = myfnFunction

and having it just work. If I do that with an instance of generic
object however, I get an AttributeError. So:

x = object()
x.fn = myFn

blows up. However, if I do

class nc(object):pass
x = nc()
x.fn = myFn

Then all is well.

checking for an ability on somebody is as simple as

'fn' in dir(x)

or

hasattr(x, 'fn')
I had thought this was a lot easier than I was making it out to be.
What I don't know is why using an object derived from object allows
you to dynamically add methods like this but the base object does not.
At this point it is more of a curiosity than anything, but if somebody
knows the answer off the top of their head, that would be great.

Thanks.

May 4 '07 #8

P: n/a
Mike wrote:
I just realized in working with this more that the issues I was having
with instancemethod and other things seems to be tied solely to
What you describe below is a function that happens to be an attribute of an
instance. There are also "real" instance methods that know about "their"
instance:
>>import new
class A(object):
.... def __init__(self, name):
.... self.name = name
....
>>def method(self): # a function...
.... print self.name
....
>>a = A("alpha")
b = A("beta")
a.method = new.instancemethod(method, a) # ...turned into a method...
a.method()
alpha
>>b.method() # ... but only known to a specific instance of A
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'method'
builtins like dict or object. I remember at some point just doing
something like:

x.fn = myfnFunction

and having it just work.
With the caveat that x.fn is now an alias for myfnFunction, but doesn't get
x passed as its first argument (conventionally named 'self') and therefore
has no knowledge of the instance x.
If I do that with an instance of generic
object however, I get an AttributeError. So:

x = object()
x.fn = myFn

blows up. However, if I do

class nc(object):pass
x = nc()
x.fn = myFn

Then all is well.

checking for an ability on somebody is as simple as

'fn' in dir(x)

or

hasattr(x, 'fn')
I had thought this was a lot easier than I was making it out to be.
What I don't know is why using an object derived from object allows
you to dynamically add methods like this but the base object does not.
At this point it is more of a curiosity than anything, but if somebody
knows the answer off the top of their head, that would be great.
Arbitrary instance attributes are implemented via a dictionary (called
__dict__), and that incurs a certain overhead which is sometimes better to
avoid (think gazillion instances of some tiny class). For example, tuples
are derived from object but don't have a __dict__.
As a special case, what would happen if dict were to allow attributes? It
would need a __dict__ which would have a __dict__ which would have...
As a consequence object could no longer be the base class of all (newstyle)
classes.

Peter

May 4 '07 #9

P: n/a
On May 4, 5:46 pm, Peter Otten <__pete...@web.dewrote:
Mike wrote:
I just realized in working with this more that the issues I was having
with instancemethod and other things seems to be tied solely to

What you describe below is a function that happens to be an attribute of an
instance. There are also "real" instance methods that know about "their"
instance:
>import new
class A(object):

... def __init__(self, name):
... self.name = name
...>>def method(self): # a function...

... print self.name
...>>a = A("alpha")
>b = A("beta")
a.method = new.instancemethod(method, a) # ...turned into a method...
a.method()
alpha
>b.method() # ... but only known to a specific instance of A

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'method'
builtins like dict or object. I remember at some point just doing
something like:
x.fn = myfnFunction
and having it just work.

With the caveat that x.fn is now an alias for myfnFunction, but doesn't get
x passed as its first argument (conventionally named 'self') and therefore
has no knowledge of the instance x.
If I do that with an instance of generic
object however, I get an AttributeError. So:
x = object()
x.fn = myFn
blows up. However, if I do
class nc(object):pass
x = nc()
x.fn = myFn
Then all is well.
checking for an ability on somebody is as simple as
'fn' in dir(x)
or
hasattr(x, 'fn')
I had thought this was a lot easier than I was making it out to be.
What I don't know is why using an object derived from object allows
you to dynamically add methods like this but the base object does not.
At this point it is more of a curiosity than anything, but if somebody
knows the answer off the top of their head, that would be great.

Arbitrary instance attributes are implemented via a dictionary (called
__dict__), and that incurs a certain overhead which is sometimes better to
avoid (think gazillion instances of some tiny class). For example, tuples
are derived from object but don't have a __dict__.
As a special case, what would happen if dict were to allow attributes? It
would need a __dict__ which would have a __dict__ which would have...
As a consequence object could no longer be the base class of all (newstyle)
classes.

Peter
Thanks.

May 7 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.