python : read a line, then instantiate a class named in the line - python

I'm sorry if I wasn't clear enough in the title, don't hesitate to correct it if you find a better way to express that:
I have a file where there are class names, i.e.:
classa
classb
classb
classc
classc
classc
Then I want to read it line by line and to dynamically create that class.
I would do something like that in php:
while (!eof())
{
$class=fread(..)
$tab[] = new $class();
}
How would you do that in python (if it's possible)?
Thanks a lot!
Edit: after reading the answers, to be more precise on what I'm planning to do:
I'm not planning to do such a simple stuff. It will be far more complex: I want a user who doesn't know programming to edit a simple text file, and to copy/paste some declarations and change their properties and to re-launch a kind of parser which will re-run a batch and show the result of complex operations.
Simplified Example of a file:
car:(red,4_wheels,4_places)
bike:(blue,2_wheels,1_place)
Then the user will change it to:
car:(red,4_wheels,4_places)
car:(yellow,4_wheels,2_places)
bike:(blue,2_wheels,1_place)
bike:(green,2_wheels,2_places)
And then with python I'll read this file, create two instances of the class car, and two instances of the class bike. Thus a user who doesn't understand / know python will be able to edit the file without touching a line of code.
I think this is the right way to go, if you have any other suggestions for this code, you're welcome!
Olivier Pons

Assuming your classes are already in scope (i.e. they're not in a separate module), you can refer to a class by its name very easily through the globals() dict. For example:
class Foo:
pass
foo_cls = globals()['Foo']
foo = foo_cls()
# foo is now an instance of __main__.Foo

The other answers do what you asked, but I wanted to add a small measure of flexibility (and protection.) I would use a dictionary to map the line names to the class objects, so you're not letting the text file instantiate anything it wants. It has to be a class that you allow it to, in your code. This also makes it easier because you can change names on either side without trouble (and you could map multiple line-names to a single class name, if you wanted.)
classes = {'classa': classa, 'classb': classb}
cls = type(classes[line], (object,), {}) ## or whichever method to instantiate you prefer
But in general, it's not a very Pythonic thing to do, in my opinion.

As you are using YAML anyway, consider using PyYAML with the serialized classes deriving from the yaml.YAMLObject metaclass or registering your own represenenter.
From the documentation of PyYAML:
class Monster(yaml.YAMLObject):
yaml_tag = u'!Monster'
def __init__(self, name, hp, ac, attacks):
self.name = name
self.hp = hp
self.ac = ac
self.attacks = attacks
def __repr__(self):
return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % (
self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)
print yaml.load("""
--- !Monster
name: Cave spider
hp: [2,6] # 2d6
ac: 16
attacks: [BITE, HURT]
""")
prints Monster(name='Cave spider', hp=[2, 6], ac=16, attacks=['BITE', 'HURT'])
That way you can leave out many of the code you need for error handling (e.g. class is not present) and you also have system that is more robust against malicious configuration files. As an additional bonus, you are able to dump objects from your program into a YAML file.

Reading each line from the file is pretty easy:
with open(filename) as f:
for line in f:
The first thing that comes to mind for class creation is the type function:
cls = type(line, (object,), {})
This will create a new empty class which is a subclass of object and has a name given by the contents of the line.
I have to wonder why you're trying to do this, though. An empty class like that doesn't seem very useful in Python.

Assuming that all classes are declared in a module foo:
classname = sys.stdin.read().rstrip()
cls = getattr(foo, classname)()
To access classes in the same module, use the builtin globals() function.

This should be fairly easily possible using a dictionary of classes (not that this is not necessarily a restriction as each python namespace can be accessed as a dictionary so if you want these classes say to all be within a module or another class, just replace classes with the __dict__ attribute of the class or use globals as others have suggested):
classes = dict()
with open('filename') as f:
for line in f:
classes[line] = class()
(Implementation details may vary).
You may however want to look into using pickling instead as on the face of it, this approach seems flawed (it might work well in PHP though :-) ).

Related

In Python, is referencing an instance variable from a staticmethod possible?

I know the question has been asked before, but I find myself bumping into situations where a staticmethod is most appropriate, but there is also a need to reference an instance variable inside this class. As an example, lets say I have the following class:
class ExampleClass(object):
def __init__(self, filename = 'defaultFilename'):
self.file_name = filename
#staticmethod
def doSomethingWithFiles(file_2, file_1 = None):
#if user didn't supply a file use the instance variable
if file_1 is None:
# no idea how to handle the uninitialized class case to create
# self.file_name.
file_1 = __class__.__init__().__dict__['file_name'] <--- this seems sketchy
else:
file_1 = file_1
with open(file_1, 'r') as f1, open(file_2, 'w') as f2:
.....you get the idea...
def moreMethodsThatUseSelf(self):
pass
Now suppose I had a few instances of the ExampleClass (E1, E2, E3) with different filenames passed into __init__, but want to retain the ability to use either an uninitialized class ExampleClass.doSomethingWithFiles(file_2 = E1.file_name, file_1 = E2.file_name) or E1.doSomethingWithFiles(file_2 = E2.file_name, file_1 = 'some_other_file') as the situation requires.
Is there any reason for me to trying to find a way to do what I am thinking, or am I making a mess?
UPDATE
I think the comments are helpful and I also think it's an issue I'm encountering due to bad design.
The issue started out as a way to prevent concurrent access to HDF5 files by giving each class instance an rlock that I could use as a context manager for preventing any other attempts to access the file while it was in use. Each class instance had it's own rlock it acquired and released when done with whatever it needed to do. I was also using #staticmethod to perform a routine that then generated a file which was passed into it's own init() and was unique to each class instance. At the time it seemed clever, but I regret it. I also think I am entirely unsure of when #staticmethods are ever appropriate and maybe was confusing it with #classmethods, but a class variable would no longer make the rlocks and files that are unique to my class instances possible. I think I should probably just think more about design vs. trying to justify using a class definition I do not really understand in a manner it was designed to protect against.
If you think you keep bumping into situations where a staticmethod is most appropriate, you're probably wrong—good uses for them are very rare. And if your staticmethod needs to access instance variables, you're definitely wrong.
A staticmethod cannot access instance variables directly. There can be no instances of the class, or a thousands; which one would you access the variables from?
What you're trying to do is to create a new instance, just to access its instance variables. This can occasionally be useful—although it's more often a good sign you didn't need a class in the first place. (And, when it useful, it's unusual enough to be usually worth signaling, by having the caller write ExampleClass().doSomethingWithFiles instead of ExampleClass.doSomethingWithFiles.)
That's legal, but you do it by just calling the class, not by calling its __init__ method. That __init__ never returns anything; it receives an already-created self and modifies it. If you really want to, you can call its __new__ method, but that effectively just means the same thing as calling the class. (In the minor ways in which they're different, it's calling the class that you want.)
Also, once you've got an instance, you can just use it normally; you don't need to look at its __dict__. (Even if you only had the attribute name as a string variable, getattr(obj, name) is almost always what you want there, not obj.__dict__[name].)
So:
file_1 = __class__().file_name
So, what should you do instead?
Well, look at your design. The only thing an ExampleClass instance does is hold a filename, which has a default value. You don't need an object for that, just a plain old string variable that you pass in, or store as a global. (You may have heard that global variables are bad—but global variables in disguise are just as bad, and have the additional problem that they're in disguise. And that's basically what you've designed. And sometimes, global variables are the right answer.)
why not input the instance as parameter to static method. I hope this code will be helpful.
class ClassA:
def __init__(self, fname):
self.fname = fname
def print(self):
print('fname=', self.fname)
#staticmethod
def check(f):
if type(f)==ClassA :
print('f is exist.')
f.print()
print('f.fname=', f.fname)
else:
print('f is not exist: new ClassA')
newa = ClassA(f)
return newa
a=ClassA('temp')
b=ClassA('test')
ClassA.check(a)
ClassA.check(b)
newa = ClassA.check('hello')
newa.print()
You cannot refer to an instance attribute from a static method. Suppose multiple instances exist, which one would you pick the attribute from?
What you seem to need is to have a class attribute and a class method. You can define one by using the classmethod decorator.
class ExampleClass(object):
file_name = 'foo'
#classmethod
def doSomethingWithFiles(cls, file_2, file_1 = None):
file_1 = cls.file_name
# Do stuff
Maybe I'm misunderstanding what your intentions are but I think you're misusing the default parameter.
It appears you're trying to use 'defaultFilename' as the default parameter value. Why not just skip the awkward
if file_1 is None:
# no idea how to handle the uninitialized class case to create
# self.file_name.
file_1 = __class__.__init__().__dict__['file_name'] <--- this seems sketchy
and change the function as follows,
def doSomethingWithFiles(file_2, file_1='defaultFilename'):
If hardcoding that value makes you uncomfortable maybe try
class ExampleClass(object):
DEFAULT_FILE_NAME = 'defaultFilename'
def __init__(self, filename=DEFAULT_FILE_NAME):
self.file_name = filename
#staticmethod
def doSomethingWithFiles(file_2, file_1=DEFAULT_FILE_NAME):
with open(file_1, 'r') as f1, open(file_2, 'w') as f2:
# do magic in here
def moreMethodsThatUseSelf(self):
pass
In general, though, you're probably modeling your problem wrong if you want to access an instance variable inside a static method.

How to split python class into multiple files [duplicate]

Using "new" style classes (I'm in python 3.2) is there a way to split a class over multiple files? I've got a large class (which really should be a single class from an object-oriented design perspective, considering coupling, etc, but it'd be nice to split over a few files just for ease of editing the class.
If your problem really is just working with a large class in an editor, the first solution I'd actually look for is a better way to break down the problem. The second solution would be a better editor, preferably one with code folding.
That said, there are a couple of ways you might break up a class into multiple files. Python lets you use a folder as a module by putting an __init__.py in it, which can then import things from other files. We'll use this capability in each solution. Make a folder called, say, bigclass first.
In the folder put the various .py files that will eventually comprise your class. Each should contain functions and variable definitions for the eventual class, not classes. In __init__.py in the same folder write the following to join them all together.
class Bigclass(object):
from classdef1 import foo, bar, baz, quux
from classdef2 import thing1, thing2
from classdef3 import magic, moremagic
# unfortunately, "from classdefn import *" is an error or warning
num = 42 # add more members here if you like
This has the advantage that you end up with a single class derived directly from object, which will look nice in your inheritance graphs.
You could use multiple inheritance to combine the various parts of your class. In your individual modules you would write a class definition for Bigclass with parts of the class. Then in your __init__.py write:
import classdef1, classdef2, classdef3
class Bigclass(classdef1.Bigclass, classdef2.Bigclass, classdef3.Bigclass):
num = 42 # add more members if desired
If the multiple inheritance becomes an issue, you can use single inheritance: just have each class inherit from another one in chain fashion. Assuming you don't define anything in more than one class, the order doesn't matter. For example, classdef2.py would be like:
import classdef1
class Bigclass(classdef1.Bigclass):
# more member defs here
classdef3 would import Bigclass from classdef2 and add to it, and so on. Your __init__.py would just import the last one:
from classdef42 import Bigclass
I'd generally prefer #1 because it's more explicit about what members you're importing from which files but any of these solutions could work for you.
To use the class in any of these scenarios you can just import it, using the folder name as the module name: from bigclass import Bigclass
You can do this with decorators like so:
class Car(object):
def start(self):
print 'Car has started'
def extends(klass):
def decorator(func):
setattr(klass, func.__name__, func)
return func
return decorator
#this can go in a different module/file
#extends(Car)
def do_start(self):
self.start()
#so can this
car = Car()
car.do_start()
#=> Car has started
Class definitions containing hundreds of lines do occur "in the wild" (I have seen some in popular open-source Python-based frameworks), but I believe that if you ponder what the methods are doing, it will be possible to reduce the length of most classes to a manageable point. Some examples:
Look for places where mostly the same code occurs more than once. Break that code out into its own method and call it from each place with arguments.
"Private" methods that do not use any of the object state can be brought out of the class as stand-alone functions.
Methods that should be called only under certain conditions may indicate a need to place those methods in a subclass.
To directly address your question, it is possible to split up the definition of a class. One way is to "monkey-patch" the class by defining it and then adding outside functions to it as methods. Another is to use the built-in type function to create the class "by hand", supplying its name, any base classes, and its methods and attributes in a dictionary. But I do not recommend doing this just because the definition would be long otherwise. That sort of cure is worse than the disease in my opinion.
I've previously toyed around with something similar. My usecase was a class hierarchy of nodes in an abstract syntax tree, and then I wanted to put all e.g. prettyprinting functions in a separate prettyprint.py file but still have them as methods in the classes.
One thing I tried was to use a decorator that puts the decorated function as an attribute on a specified class. In my case this would mean that prettyprint.py contains lots of def prettyprint(self) all decorated with different #inclass(...)
A problem with this is that one must make sure that the sub files are always imported, and that they depend on the main class, which makes for a circular dependency, which may be messy.
def inclass(kls):
"""
Decorator that adds the decorated function
as a method in specified class
"""
def _(func):
setattr(kls,func.__name__, func)
return func
return _
## exampe usage
class C:
def __init__(self, d):
self.d = d
# this would be in a separate file.
#inclass(C)
def meth(self, a):
"""Some method"""
print "attribute: %s - argument: %s" % (self.d, a)
i = C(10)
print i.meth.__doc__
i.meth(20)
I've not used it, but this package called partial claims to add support for partial classes.
It seems like there's a few other ways you could implement this yourself as well.
You could implement separate parts of the class as mixins in seperate files, then import them all somewhere and subclass them.
Alternatively, you could implement each of the methods of your class somewhere then in a central file import them and assign them as attributes on a class, to create the whole object. Like so:
a.py:
def AFunc( self, something ):
# Do something
pass
b.py:
def BFunc( self, something ):
# Do something else
pass
c.py:
import a, b
class C:
AFunc = a.AFunc
BFunc = b.BFunc
You could even go so far as to automate this process if you really wanted - loop through all the functions provided by modules a and b and then add them as attributes on C. Though that might be total overkill.
There might be other (possibly better) ways to go about it, but those are the 2 that popped into mind.
I would like to add that the pythonic way of doing this is through multiple inheritance, not necessarily using mixins. Instance attributes can be added using super().__init__(*args, **kwargs) in __init__ calls to pass arguments to baseclasses (see ‘super considered super’ presentation by Raymond Hettinger 1). This also enables dependency injection and kind of forces you to think about organization of base classes (it works best if only one baseclass sets an attribute in __init__ and all classes using the attribute inherit from it).
This does usually require you having control over the base classes (or they being written for this pattern).
Another option is using descriptors returning functions through __get__ to add functionality to classes in a decoupled way.
You could also look at __init_subclass__ to add e.g. methods to classes during class generation (i think added in python 3.6, but check)
First I'd like to say that something this complicated it probably not a good idea just to make finding your place in the class easier - it would be best to add comments, highlight sections etc. However, I see two ways you could do this:
Write the class in several files, then read them in as text, concatenate them and exec the resulting string.
Create a separate class in each file, then inherit them all into a master class as mixins. However, if you're subclassing another class already this could lead to MRO problems. You could get around this by creating a metaclass for your master class which manually resolves the MRO, but this could get messy.
The easiest would be the first option.
First off, I don't see how splitting the class into multiple files makes editing any easier. A decent IDE should be able to find any method easily whether in one file or multiple; if you're not using a decent IDE, splitting the class means the maintainer has to guess which file a given method is in, which sounds harder rather than easier.
More fundamentally, this class - so large that you want a special language feature just to support its weight - sounds fundamentally broken. How many lines of code are we talking about? Almost certainly, it would be a better idea to do one of:
Refactor duplicated code into fewer, more general primitives
Define a base class and extend it with subclasses as Karoly Horvath suggests in comments (this is the closest thing to the 'partial classes' that you're asking for that I would endorse)
Define a few separate classes to encapsulate different parts of this
class's functionality, and compose this class of instances of those
smaller ones.
I met the same situation - I want to slipt my class to 2 files.
the reason is that - I want part 1 for GUI layout, only layout
and another file keeps all function.
like c#'s Partial class. one for XAML and another one for functions.

How can I automatically update my class variables and lists using a child class? [duplicate]

Is there any way to make certain variables in classes "private" (or whatever self.__var really is) but be accessible to another class, like friends in c++, except in python? I do not want the variables in either class being messed with. Nor do I want to copy the entire code over and convert it for the second class.
No, there is not such an option.
Use names that start with single underscores and tell the other people working on your project to not be silly about what they access.
The philosophy of Python is that issues like access control are up to programmer discipline. It doesn't attempt to encode in the language which parts of the program are internal implementation details, and which are part of the documented interface. Thus, it doesn't need constructs like friend to try to declare which other parts of the program are part of the implementation of a class and which are merely clients.
The idea is that if you can't write/design/document/use good code without partially encoding these concepts into your program, you probably can't do it when you are encoding them either. Therefore it's better not to have such constructs in the language, since they don't increase the expressive power of the language and occasionally they get in the way.
there is no option of friend function in python.
you have an option to define a protected variable by using a single underscore,
but in python protected variable is also accessed by the main function, but this is not exactly the definition of a protected variable just have a look.
class Student:
_schoolName = 'XYZ School' # protected class attribute
def __init__(self, name, age):
self._name=name # protected instance attribute
self._age=age # protected instance attribute
std = Student("Swati", 25)
std._name
#answer is ->'Swati'
std._name = 'Dipa'
std._name
#answer is ->'Dipa'
I have no clue what you're talking about.
>>> class Foo(object):
... __bar = 42
...
>>> class Quux(object):
... def spam(self):
... print Foo._Foo__bar
...
>>> q = Quux()
>>> q.spam()
42

Is it possible to divide functions of an python class into different files ? [duplicate]

Using "new" style classes (I'm in python 3.2) is there a way to split a class over multiple files? I've got a large class (which really should be a single class from an object-oriented design perspective, considering coupling, etc, but it'd be nice to split over a few files just for ease of editing the class.
If your problem really is just working with a large class in an editor, the first solution I'd actually look for is a better way to break down the problem. The second solution would be a better editor, preferably one with code folding.
That said, there are a couple of ways you might break up a class into multiple files. Python lets you use a folder as a module by putting an __init__.py in it, which can then import things from other files. We'll use this capability in each solution. Make a folder called, say, bigclass first.
In the folder put the various .py files that will eventually comprise your class. Each should contain functions and variable definitions for the eventual class, not classes. In __init__.py in the same folder write the following to join them all together.
class Bigclass(object):
from classdef1 import foo, bar, baz, quux
from classdef2 import thing1, thing2
from classdef3 import magic, moremagic
# unfortunately, "from classdefn import *" is an error or warning
num = 42 # add more members here if you like
This has the advantage that you end up with a single class derived directly from object, which will look nice in your inheritance graphs.
You could use multiple inheritance to combine the various parts of your class. In your individual modules you would write a class definition for Bigclass with parts of the class. Then in your __init__.py write:
import classdef1, classdef2, classdef3
class Bigclass(classdef1.Bigclass, classdef2.Bigclass, classdef3.Bigclass):
num = 42 # add more members if desired
If the multiple inheritance becomes an issue, you can use single inheritance: just have each class inherit from another one in chain fashion. Assuming you don't define anything in more than one class, the order doesn't matter. For example, classdef2.py would be like:
import classdef1
class Bigclass(classdef1.Bigclass):
# more member defs here
classdef3 would import Bigclass from classdef2 and add to it, and so on. Your __init__.py would just import the last one:
from classdef42 import Bigclass
I'd generally prefer #1 because it's more explicit about what members you're importing from which files but any of these solutions could work for you.
To use the class in any of these scenarios you can just import it, using the folder name as the module name: from bigclass import Bigclass
You can do this with decorators like so:
class Car(object):
def start(self):
print 'Car has started'
def extends(klass):
def decorator(func):
setattr(klass, func.__name__, func)
return func
return decorator
#this can go in a different module/file
#extends(Car)
def do_start(self):
self.start()
#so can this
car = Car()
car.do_start()
#=> Car has started
Class definitions containing hundreds of lines do occur "in the wild" (I have seen some in popular open-source Python-based frameworks), but I believe that if you ponder what the methods are doing, it will be possible to reduce the length of most classes to a manageable point. Some examples:
Look for places where mostly the same code occurs more than once. Break that code out into its own method and call it from each place with arguments.
"Private" methods that do not use any of the object state can be brought out of the class as stand-alone functions.
Methods that should be called only under certain conditions may indicate a need to place those methods in a subclass.
To directly address your question, it is possible to split up the definition of a class. One way is to "monkey-patch" the class by defining it and then adding outside functions to it as methods. Another is to use the built-in type function to create the class "by hand", supplying its name, any base classes, and its methods and attributes in a dictionary. But I do not recommend doing this just because the definition would be long otherwise. That sort of cure is worse than the disease in my opinion.
I've previously toyed around with something similar. My usecase was a class hierarchy of nodes in an abstract syntax tree, and then I wanted to put all e.g. prettyprinting functions in a separate prettyprint.py file but still have them as methods in the classes.
One thing I tried was to use a decorator that puts the decorated function as an attribute on a specified class. In my case this would mean that prettyprint.py contains lots of def prettyprint(self) all decorated with different #inclass(...)
A problem with this is that one must make sure that the sub files are always imported, and that they depend on the main class, which makes for a circular dependency, which may be messy.
def inclass(kls):
"""
Decorator that adds the decorated function
as a method in specified class
"""
def _(func):
setattr(kls,func.__name__, func)
return func
return _
## exampe usage
class C:
def __init__(self, d):
self.d = d
# this would be in a separate file.
#inclass(C)
def meth(self, a):
"""Some method"""
print "attribute: %s - argument: %s" % (self.d, a)
i = C(10)
print i.meth.__doc__
i.meth(20)
I've not used it, but this package called partial claims to add support for partial classes.
It seems like there's a few other ways you could implement this yourself as well.
You could implement separate parts of the class as mixins in seperate files, then import them all somewhere and subclass them.
Alternatively, you could implement each of the methods of your class somewhere then in a central file import them and assign them as attributes on a class, to create the whole object. Like so:
a.py:
def AFunc( self, something ):
# Do something
pass
b.py:
def BFunc( self, something ):
# Do something else
pass
c.py:
import a, b
class C:
AFunc = a.AFunc
BFunc = b.BFunc
You could even go so far as to automate this process if you really wanted - loop through all the functions provided by modules a and b and then add them as attributes on C. Though that might be total overkill.
There might be other (possibly better) ways to go about it, but those are the 2 that popped into mind.
I would like to add that the pythonic way of doing this is through multiple inheritance, not necessarily using mixins. Instance attributes can be added using super().__init__(*args, **kwargs) in __init__ calls to pass arguments to baseclasses (see ‘super considered super’ presentation by Raymond Hettinger 1). This also enables dependency injection and kind of forces you to think about organization of base classes (it works best if only one baseclass sets an attribute in __init__ and all classes using the attribute inherit from it).
This does usually require you having control over the base classes (or they being written for this pattern).
Another option is using descriptors returning functions through __get__ to add functionality to classes in a decoupled way.
You could also look at __init_subclass__ to add e.g. methods to classes during class generation (i think added in python 3.6, but check)
First I'd like to say that something this complicated it probably not a good idea just to make finding your place in the class easier - it would be best to add comments, highlight sections etc. However, I see two ways you could do this:
Write the class in several files, then read them in as text, concatenate them and exec the resulting string.
Create a separate class in each file, then inherit them all into a master class as mixins. However, if you're subclassing another class already this could lead to MRO problems. You could get around this by creating a metaclass for your master class which manually resolves the MRO, but this could get messy.
The easiest would be the first option.
First off, I don't see how splitting the class into multiple files makes editing any easier. A decent IDE should be able to find any method easily whether in one file or multiple; if you're not using a decent IDE, splitting the class means the maintainer has to guess which file a given method is in, which sounds harder rather than easier.
More fundamentally, this class - so large that you want a special language feature just to support its weight - sounds fundamentally broken. How many lines of code are we talking about? Almost certainly, it would be a better idea to do one of:
Refactor duplicated code into fewer, more general primitives
Define a base class and extend it with subclasses as Karoly Horvath suggests in comments (this is the closest thing to the 'partial classes' that you're asking for that I would endorse)
Define a few separate classes to encapsulate different parts of this
class's functionality, and compose this class of instances of those
smaller ones.
I met the same situation - I want to slipt my class to 2 files.
the reason is that - I want part 1 for GUI layout, only layout
and another file keeps all function.
like c#'s Partial class. one for XAML and another one for functions.

Best approach with dynamic classes using Python globals()

I'm working on a web application that will return a variable set of modules depending on user input. Each module is a Python class with a constructor that accepts a single parameter and has an '.html' property that contains the output.
Pulling the class dynamically from the global namespace works:
result = globals()[classname](param).html
And it's certainly more succinct than:
if classname == 'Foo':
result = Foo(param).html
elif classname == 'Bar':
...
What is considered the best way to write this, stylistically? Are there risks or reasons not to use the global namespace?
A flaw with this approach is that it may give the user the ability to to more than you want them to. They can call any single-parameter function in that namespace just by providing the name. You can help guard against this with a few checks (eg. isinstance(SomeBaseClass, theClass), but its probably better to avoid this approach. Another disadvantage is that it constrains your class placement. If you end up with dozens of such classes and decide to group them into modules, your lookup code will stop working.
You have several alternative options:
Create an explicit mapping:
class_lookup = {'Class1' : Class1, ... }
...
result = class_lookup[className](param).html
though this has the disadvantage that you have to re-list all the classes.
Nest the classes in an enclosing scope. Eg. define them within their own module, or within an outer class:
class Namespace(object):
class Class1(object):
...
class Class2(object):
...
...
result = getattr(Namespace, className)(param).html
You do inadvertantly expose a couple of additional class variables here though (__bases__, __getattribute__ etc) - probably not exploitable, but not perfect.
Construct a lookup dict from the subclass tree. Make all your classes inherit from a single baseclass. When all classes have been created, examine all baseclasses and populate a dict from them. This has the advantage that you can define your classes anywhere (eg. in seperate modules), and so long as you create the registry after all are created, you will find them.
def register_subclasses(base):
d={}
for cls in base.__subclasses__():
d[cls.__name__] = cls
d.update(register_subclasses(cls))
return d
class_lookup = register_subclasses(MyBaseClass)
A more advanced variation on the above is to use self-registering classes - create a metaclass than automatically registers any created classes in a dict. This is probably overkill for this case - its useful in some "user-plugins" scenarios though.
First of all, it sounds like you may be reinventing the wheel a little bit... most Python web frameworks (CherryPy/TurboGears is what I know) already include a way to dispatch requests to specific classes based on the contents of the URL, or the user input.
There is nothing wrong with the way that you do it, really, but in my experience it tends to indicate some kind of "missing abstraction" in your program. You're basically relying on the Python interpreter to store a list of the objects you might need, rather than storing it yourself.
So, as a first step, you might want to just make a dictionary of all the classes that you might want to call:
dispatch = {'Foo': Foo, 'Bar': Bar, 'Bizbaz': Bizbaz}
Initially, this won't make much of a difference. But as your web app grows, you may find several advantages: (a) you won't run into namespace clashes, (b) using globals() you may have security issues where an attacker can, in essence, access any global symbol in your program if they can find a way to inject an arbitrary classname into your program, (c) if you ever want to have classname be something other than the actual exact classname, using your own dictionary will be more flexible, (d) you can replace the dispatch dictionary with a more-flexible user-defined class that does database access or something like that if you find the need.
The security issues are particularly salient for a web app. Doing globals()[variable] where variable is input from a web form is just asking for trouble.
Another way to build the map between class names and classes:
When defining classes, add an attribute to any class that you want to put in the lookup table, e.g.:
class Foo:
lookup = True
def __init__(self, params):
# and so on
Once this is done, building the lookup map is:
class_lookup = zip([(c, globals()[c]) for c in dir() if hasattr(globals()[c], "lookup")])

Categories