conditionally creating functions within a class?
Steve Holden
steve at holdenweb.com
Fri May 25 22:14:21 EDT 2007
kaens wrote:
> So, I have a class that has to retrieve some data from either xml or
> an sql database.
> This isn't a problem, but I was thinking "hey, it would be cool if I
> could just not define the functions for say xml if I'm using sql", so
> I did some fiddling around with the interpreter.
>
> First, I try conditionally creating a function, period:
>
> a = 'a'
>
> if(a == 'a')
> def b:
> print "hello"
> else:
> def c:
> print "goodbye"
>
> this works fine. b is defined, c is not. change the value of a and b
> gets defined and not c (sorry for the one-letter variables here, but
> for these little examples I don't think they detract much)
>
> then I try doing this within a function:
>
> class test:
> def __init__(self,which):
> self.which = which
>
> if(self.which == 'a'):
> def b:
> print "hello"
> else:
> def c:
> print "goodbye"
>
The problem here is that the "if" statement executes in class scope,
which means at the same level at which the "def" statements define the
methods.
Unfortunately there is no "self" defined, as "self" is a method argument
(whose value is provided automatically by the interpreter when a method
call is made on a specific instance of the class). So it's out of scope.
You could try to define the methods inside __init__, but that isn't
really appropriate because __init__ runs each time a new instance
requires initialization, and one of the primary ideas behind object
orientation is that the class defines the same methods for all instances.
You could override the methods in each instance, but this is all taking
you further and further away from your relatively simple engineering goal.
> tester = test('a')
> tester.b()
>
> This doesn't "compile", says "Name 'self' is not defined". I assume
> this is because of scope, something like it hasn't made the object
> yet, so there is no self attribute. . . but I thought that python
> wouldn't even bother reading that class statement until I tried to
> make a test object, and that it would do the __init__ function before
> anything else, so I'm a bit fuzzy here.
>
In Python the only non-executable statement is "global", so the class
definition is executed when it's encountered. This is what give rise to
the problems, which you have correctly diagnosed as being related to
scoping issues.
> Next I try creating the functions through functions:
>
> class test:
> def __init__(self, which):
> self.which = which
> self.chooser()
>
> def chooser(self):
> if( self.which == 'a'):
> def b(self):
> print "hello"
> else:
> def c(self):
> print "goodbye"
>
> tester = test('a')
> tester.b()
>
> this tells me "instance has no attribute b.
>
And it isn't lying. The problem is that "def b" is executed within the
chooser() method, so it's local to that method and invisible to the
class scope.
> I'm pretty sure this is all a scoping error of some sort (I could be
> wrong), but I don't have my head wrapped around it at all. Anyone with
> more knowledge care to explain what's going on?
>
> Also, would there be a way to conditionally create functions in a
> class? It doesn't really matter, but it'd be nice if I weren't
> creating functions that I absolutely will not need for certain
> instances at runtime
Here I'd ask you to take a step back. What you really need is two
parallel modules or classes, one of which handles SQL inputs and the
other of which handles XML inputs.
My own approach would be to define two modules with the same API and
then import one or the other. Something like this:
if intype == "a":
import sqlmodule as myinmod
# do SQL-specific stuff, if any
else:
import xmlmodule as myinmod
# do XML-specific stuff, if any
You can then call the functions and classes defined in the imported
module as
myinmod.func()
and
someinstance = myinmod.classname()
Since you only import one module, you don't execute the definitions in
the unused module at all, and as long as the APIs really are parallel
you can write code that doesn't care which one it uses.
There are other approaches you could take, but if this would answer your
needs then I'd suggest you consider it.
regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
------------------ Asciimercial ---------------------
Get on the web: Blog, lens and tag your way to fame!!
holdenweb.blogspot.com squidoo.com/pythonology
tagged items: del.icio.us/steve.holden/python
All these services currently offer free registration!
-------------- Thank You for Reading ----------------
More information about the Python-list
mailing list