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.

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.

  • 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 4: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 6:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.