1

I have a class that will have a number of external methods that will all call the same smaller set of internal methods. So something like:

obj.method_one(a, c) and obj.method_two(a, c)

where obj.method_one calls obj._internal_method(a, c, y) and obj.method_two calls obj._internal_method(a, c, z).

They're nearly identical but they have one argument at the end that differs on the internal call (which is a constant).

I could just copy and paste a few times but I was wondering if theres any way to dynamically create these external methods.

tonyl7126
  • 297
  • 3
  • 13

1 Answers1

4

There are ways, but unless you have at least half a dozen, I'd suggest:

class myclass(object):
   def _internal_method(self,a,c,y):
       pass # add code here

   def method_one(self,a,c): self._internal_method(a,c,"method one")
   def method_two(self,a,c): self._internal_method(a,c,"another method")

The other option is to actually really create it dynamically. This can be confusing, because if the object is inspected, the methods aren't there. It looks like this:

class test(object):
    def __getattr__(self,attrname):
        def _internal_method(a,c):
            print "You called %s  with %s and %s" % (attrname,a,c)
        if attrname in ["method_one","method_two"]:
            return _internal_method
        else:
            raise NameError

a=test()
a.method_one("first","second")

This makes use of the fact that a getting a property (like a method) that does not exist, the object's __getattr__ is called, and the result is passed back. Note that we are passing back the FUNCTION _internal_method as a.method_one, not calling it at this stage; that is done after the call to getattr has returned. Think of the last line as being:

tmp=a.method
tmp("first","second")

The first of these calls __getattr__ which returns _internal_method (but does not call it), the latter calls _internal_method.

Since _internal_method is declared within __getattr__, it has the same scope as the call that created it, so self and attrname are accessible. Also, _internal_method is TRULY private, not just "private by convention".

I will reiterate that this is confusing for the next person to maintain your code. For example, if you ask for help(a.method_one), you will get the help for _internal_method instead!

The length of this explanation, and your probable confusing is a very good reason not to use this unless you have to.

AMADANON Inc.
  • 426
  • 2
  • 10
  • yeah the second way makes sense but you're right, it's too complicated for my use case. Maybe if I had 100s (or something really big) of external methods, then it would make sense. Anyway, great response. – tonyl7126 Feb 18 '14 at 04:14
  • 1
    I think it's worth mentioning that if you override \_\_getattr\_\_ to add methods to a class, then they won't show up when you run dir() on the class. If you really need to add methods dynamically, it's better to use either a metaclass or a class decorator. – user16764 Feb 18 '14 at 06:01