adding methods at runtime and lambda

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mike

    #1

    adding methods at runtime and lambda

    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(currO bject, method, name = None):
    if name is None: name = method.func_nam e
    class newclass(currOb ject.__class__) :pass
    setattr(newclas s, 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.HasDriv e(d),
    "hasdrive")

    and then I can call

    superdict.HasDr ive('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.

  • Mike

    #2
    Re: adding methods at runtime and lambda

    In the above example 'addm' should be 'AddMethod'

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

    Comment

    • James Stroud

      #3
      Re: adding methods at runtime and lambda

      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(currO bject, method, name = None):
      if name is None: name = method.func_nam e
      class newclass(currOb ject.__class__) :pass
      setattr(newclas s, 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.HasDriv e(d),
      "hasdrive")
      >
      and then I can call
      >
      superdict.HasDr ive('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(myUtil s.HasDrive), "hasdrive")

      James

      Comment

      • ici

        #4
        Re: adding methods at runtime and lambda

        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(currO bject, method, name = None):
        if name is None: name = method.func_nam e
        class newclass(currOb ject.__class__) :pass
        setattr(newclas s, 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.HasDriv e(d),
        "hasdrive")
        >
        and then I can call
        >
        superdict.HasDr ive('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('S cripting.FileSy stemObject')
        for d in fso.Drives:
        if d.DriveType == 2: # Fixed
        list.append(sel f, 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!"

        Comment

        • Gabriel Genellina

          #5
          Re: adding methods at runtime and lambda

          En Thu, 03 May 2007 16:52:55 -0300, Mike <msurel@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(fo o)
          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

          Comment

          • Mike

            #6
            Re: adding methods at runtime and lambda

            On May 3, 11:25 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a r>
            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(fo o)
            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.

            Comment

            • Peter Otten

              #7
              Re: adding methods at runtime and lambda

              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

              Comment

              • Mike

                #8
                Re: adding methods at runtime and lambda

                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.

                Comment

                • Peter Otten

                  #9
                  Re: adding methods at runtime and lambda

                  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.instancemet hod(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

                  Comment

                  • Mike

                    #10
                    Re: adding methods at runtime and lambda

                    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.instancemet hod(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.

                    Comment

                    Working...