J
Josiah Carlson
Look, here is a partial list of the symptoms of the illness of using
I've never used metaclasses, and don't forsee a need for them in
development I'll be undertaking any time in the near (or far) future.
Standard inheritance works for me and a vast majority of users out there.
In various cases, PEP 318 (decorator syntax) seems to alleviate many
people's needs for metaclasses and the magic behind them.
Singletons aren't nearly as prevalent as you seem to believe. Take a
peek in the standard library, and you'll find a large body of good code
that has chosen not to use the "singleton design pattern". Truth be
told, I've used singletons before, but only once.
Please express what you mean by "functional". I believe you mean...
class blah:
def __call__(cls):
print cls
__call__ = classmethod(call)
blah(object) #should print "<type 'object'>"
In this situation, I believe that a pure module-level function is
preferable,
def blah(cls):
print cls
If I have misinterpreted what you mean by 'functional', please correct me.
Yeah, I don't see a problem with this. However, if you feel really
strongly about it, with a little work, you can create a pseduo-module
with everything your heart desires. Of course it'll be ugly, and pretty
much a hack, but it can be done (without metaclasses).
The real trick is to understand the difference between "is a" and "has
a" relations.
Modules /are/ namespaces. They do not have __call__ semantics because
namespaces shouldn't be called. Things /inside/ namespaces should be
called. Honestly, I'd like to hear an example of a language where
namespaces are callable
Classes /have/ namespaces. To handle the encapsulation of data and
functions into a single passable object, it is convenient for them to
have namespaces. The explicit requirement to give a name to the
instance being implicitly passed (usually 'self'), is to remind users
"hey, I'm an instance method". Note that you can call 'self' anything
you want, it is merely convention, in a similar fashion to using 'cls'
for classmethods.
I've seen examples of a module and class having the same name, but I
believe that with the exception of singletons (which are rare in the
code that I've seen), naming an instance the same as a module or class
where it came from, is generally frowned upon due to the shadowing of
the original module/class name.
I also believe that the general consensus for future standard library
modules is to name classes different from the module that contains them.
I wouldn't call import statements inheritance, I would call it loading
an external module and binding the results to a name.
Just because you can emulate object inheritance with modules, doesn't
mean it should be done. In fact, such things are frowned upon in Python.
Take for example the following import statement...
from module import *
The above is frowned upon by Guido and basically everyone else in the
Python community because it pollutes namespace.
However...
class foo(goo):
pass
....is perfectly acceptable. Why? Because fewer people have issues with
class inheritance than with module imports. I don't know why, I just
try to answer questions like "I'm importing A from B and importing B
from A, why doesn't it work?" in a way they'll understand.
Yeah, and it allows functions to exist without being bound to a class or
an instance. Ahh, now I know, you're coming from a Java background!
See, in many other languages (C, C++, Lisp, Pascal, SML, Prolog, etc.),
functions are not required to be bound to classes or class instances.
Personally, I like the flexibility, and can be found to fill entire
modules with nothing but functions. In Java, I would have to make them
static methods on some object, a fairly foolish (if arbitrary) requirement.
You don't need to use the names 'self' or 'cls' if you don't want to,
they are just standard convention. It helps the programmer understand
that there may be a difference in terms of functionality.
You should also realize that generally, handling module-level attributes
from within the module, via global, is generally frowned upon. Again,
if you feel strongly about it, you are free to destroy the meaning of
your application by doing something like the following...
class self(object):
#module-level self
class foo:
def goo(self): pass
def bar(self): pass
bar = classmethod(bar)
def baz(self): pass
baz = staticmethod(baz)
Again, the names are different so that there is a signal to the
programmer that something different may be happening with this
particular object.
I don't believe that Python is going the way of prototype-based OOP any
time soon (if ever). If you are so prototype-fixated (goodness, you
certainly seem to be), Prothon has prototypes, and I'm sure they will be
delighted to have you.
- Josiah
class-and-module-based OOP:
(a) You need metaclasses. You have special syntax for usage of
metaclasses: you need to use the __metaclass__ name tag, in specific
places.
I've never used metaclasses, and don't forsee a need for them in
development I'll be undertaking any time in the near (or far) future.
Standard inheritance works for me and a vast majority of users out there.
In various cases, PEP 318 (decorator syntax) seems to alleviate many
people's needs for metaclasses and the magic behind them.
(b) Singletons become a "design pattern", since classes usually cannot
be used as instances directly.
Singletons aren't nearly as prevalent as you seem to believe. Take a
peek in the standard library, and you'll find a large body of good code
that has chosen not to use the "singleton design pattern". Truth be
told, I've used singletons before, but only once.
(c) You have to create staticmethod and/or classmethod to make a class
functional.
Please express what you mean by "functional". I believe you mean...
class blah:
def __call__(cls):
print cls
__call__ = classmethod(call)
blah(object) #should print "<type 'object'>"
In this situation, I believe that a pure module-level function is
preferable,
def blah(cls):
print cls
If I have misinterpreted what you mean by 'functional', please correct me.
(d) Modules can't have properties, nor are callable.
Yeah, I don't see a problem with this. However, if you feel really
strongly about it, with a little work, you can create a pseduo-module
with everything your heart desires. Of course it'll be ugly, and pretty
much a hack, but it can be done (without metaclasses).
The real trick is to understand the difference between "is a" and "has
a" relations.
Modules /are/ namespaces. They do not have __call__ semantics because
namespaces shouldn't be called. Things /inside/ namespaces should be
called. Honestly, I'd like to hear an example of a language where
namespaces are callable
Classes /have/ namespaces. To handle the encapsulation of data and
functions into a single passable object, it is convenient for them to
have namespaces. The explicit requirement to give a name to the
instance being implicitly passed (usually 'self'), is to remind users
"hey, I'm an instance method". Note that you can call 'self' anything
you want, it is merely convention, in a similar fashion to using 'cls'
for classmethods.
(e) You often need to create three objects: module, class, instance,
to do the job of one single object. Hence you often see usage of the
same name for all three of them, weird as it may seem.
I've seen examples of a module and class having the same name, but I
believe that with the exception of singletons (which are rare in the
code that I've seen), naming an instance the same as a module or class
where it came from, is generally frowned upon due to the shadowing of
the original module/class name.
I also believe that the general consensus for future standard library
modules is to name classes different from the module that contains them.
(f) Module inheritance ('import' for containment, 'from ... import'
for inheritance) differs in syntax with class inheritance ('class
A(B):')
I wouldn't call import statements inheritance, I would call it loading
an external module and binding the results to a name.
Just because you can emulate object inheritance with modules, doesn't
mean it should be done. In fact, such things are frowned upon in Python.
Take for example the following import statement...
from module import *
The above is frowned upon by Guido and basically everyone else in the
Python community because it pollutes namespace.
However...
class foo(goo):
pass
....is perfectly acceptable. Why? Because fewer people have issues with
class inheritance than with module imports. I don't know why, I just
try to answer questions like "I'm importing A from B and importing B
from A, why doesn't it work?" in a way they'll understand.
(g) Module functions and class methods become two distinct types of
objects.
Yeah, and it allows functions to exist without being bound to a class or
an instance. Ahh, now I know, you're coming from a Java background!
See, in many other languages (C, C++, Lisp, Pascal, SML, Prolog, etc.),
functions are not required to be bound to classes or class instances.
Personally, I like the flexibility, and can be found to fill entire
modules with nothing but functions. In Java, I would have to make them
static methods on some object, a fairly foolish (if arbitrary) requirement.
(h) In module-level functions, you need to use the 'global' statement
to access module-level attributes. In class (instance) methods, you
use the 'self' parameter to access instance attributes. (In class'
classmethods, you use 'cls'.) (Notice that there is a big difference
between saying "class method" and "classmethod".)
You don't need to use the names 'self' or 'cls' if you don't want to,
they are just standard convention. It helps the programmer understand
that there may be a difference in terms of functionality.
You should also realize that generally, handling module-level attributes
from within the module, via global, is generally frowned upon. Again,
if you feel strongly about it, you are free to destroy the meaning of
your application by doing something like the following...
class self(object):
#module-level self
class foo:
def goo(self): pass
def bar(self): pass
bar = classmethod(bar)
def baz(self): pass
baz = staticmethod(baz)
Again, the names are different so that there is a signal to the
programmer that something different may be happening with this
particular object.
In prototype-based OOP, you don't have any of these problems. You can
see that the usage of modules and classes introduces a whole lot of
repeated/redundant concepts and/or inconsistencies. That's the price
you pay. It's just an unfortunate historical development that lead us
to where we are today.
I don't believe that Python is going the way of prototype-based OOP any
time soon (if ever). If you are so prototype-fixated (goodness, you
certainly seem to be), Prothon has prototypes, and I'm sure they will be
delighted to have you.
- Josiah