I think it is a bad idea.
Its a very odd use of meta classes which will contribute to confusion of anyone trying to follow your code. In order to make it worth using this technique, you need the advantages to outweigh that confusion.
As for your reasons:
- Creating an accesible Foo class that can be instantiated, but doesn't actually work like a typical object is much more prone to misuse than an internal class that you know you aren't supposed to call.
- Don't name the base class with an underscore. If its intended to be inherited by other modules, it shouldn't be named that way.
- There already is a method to implement static classes in python,
staticmethod
or classmethod
. As noted, its not hard to implement a staticproperty
In general, there is a theme in your approach of trying to prevent client code from doing the wrong thing. That's not a pythonic attitude. The pythonic approach is to trust your client code. If they want to do something crazy, let them. Don't try to prevent client from instantiating your internal object, there may well be a good reason to do that.
I'm a bit of a purist and think that you shouldn't be storing state like this. So the very fact that you are asking the question means you're already doing it wrong. If you have state, I think it should be in an object. I think storing any sort of state at the module level should be avoided. I think its only a good idea to implement something like this if you have no changing state.
To close off, I'd like to plug the Code Review Stack Exchange, where I'm a moderator. If you post your code there you can get suggestions on how to make it better. I think you may get some helpful suggestions for how to restructure your code to avoid this question from even coming up.
Your friend was wrong. Methods are attributes.
Everything in Python is objects, really, with methods and functions and anything with a __call__()
method being callable objects. They are all objects that respond to the ()
call expression syntax.
Attributes then, are objects found by attribute lookup on other objects. It doesn't matter to the attribute lookup mechanism that what is being looked up is a callable object or not.
You can observe this behaviour by looking up just the method, and not calling it:
>>> class Foo(object):
... def bar(self):
... pass
...
>>> f = Foo()
>>> f.bar
<bound method Foo.bar of <__main__.Foo object at 0x1023f5590>>
Here f.bar
is an attribute lookup expression, the result is a method object.
Of course, your friend me be a little bit right too; what is really happening is that methods are special objects that wrap functions, keeping references to the underlying instance and original function, and are created on the fly by accessing the function as an attribute. But that may be complicating matters a little when you first start out trying to understand Python objects. If you are interested in how all that works, read the Python Descriptor HOWTO to see how attributes with special methods are treated differently on certain types of attribute access.
This all works because Python is a dynamic language; no type declarations are required. As far as the language is concerned, it doesn't matter if Foo.bar
is a string, a dictionary, a generator, or a method. This is in contrast to compiled languages, where data is very separate from methods, and each field on an instance needs to be pinned down to a specific type beforehand. Methods generally are not objects, thus a separate concept from data.
Best Answer
Look for such answers in here: http://www.python.org/dev/peps/
Basics is in the most famous one: http://www.python.org/dev/peps/pep-0008/
By the looks and code i have seen, you got pretty good idea about that. Good luck, hope it'll help :)
UPDATE: While following pep rules you come up with about the same anyway :) so pure convention for classes - yes there is none or i haven't heard of it. How you should write it - pep8. By common programming sense you write you variables, fields above methods. Same things happen with everything else. Just code as the Holy Zen of Python teaches you: