module not callable - why not?

  • Thread starter Diez B. Roggisch
  • Start date
J

Josiah Carlson

Look, here is a partial list of the symptoms of the illness of using
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
 
H

Hung Jung Lu

(i) For getting attributes by string names, for attributes of
instances you do getattr(self, 'name'), for module attributes you do
globals()['name']. I mention this because every once a month or so a
newbie would ask how to get module level attributes by name.

That's not the only answer, and it's not the one I use:

import foo
getattr(foo, 'name')

You can't do this when you are inside the module itself. Similarly,
unless I am inside a class, I wouldn't use getattr(self, 'name'). I
was comparing apple to apple. You gave me an orange. :)

Hung Jung
 
D

Dave Benjamin

Now usually I'd create a file called "quaternion.py", define my quaternion
class in there and then import and create an instance like this:

import quaternion

q = quaternion.quaternion()

Thats a lot to type. doing a

from quaternion import quaternion

would solve that - but AFAIK thats considered bad for some reasons.

Lately, I've become particularly fond of creating "factory" functions and
using those instead. For instance:

import Quaternion
q = Quaternion.create()

Aside from the less redundant naming style, factories are nice because they
allow you to return different classes of objects depending on their
parameters. For instance, Quaternion.create() might give you a
Quaternion.SimpleQuaternion, where Quaternion.create(foo='bar') might give
you a FooQuaternion instead. (I don't know much about quaternions, so I
can't give you a better example in that context.)
 
H

Hung Jung Lu

Fredrik Lundh said:
inside the module, it's spelled

name

</F>

Can't believe I have to reply to all these silly bursts. :)

This is a frequently asked question, Fredrik. I don't make it up. Now,
think again why newbies and oldies alike at times need to access
variables by name strings. Next time, digest first before you post.
Don't disappoint me. :)

regards,

Hung Jung
 
F

Fredrik Lundh

Hung said:
Can't believe I have to reply to all these silly bursts. :)

This is a frequently asked question, Fredrik. I don't make it up. Now,
think again why newbies and oldies alike at times need to access
variables by name strings. Next time, digest first before you post.

it's a common question from people who know certain other scripting languages
but not Python, and don't know how to use dictionaries and other data structures
to get the result they're after. globals() is hardly ever the right answer.

frankly, are you sure *you* know Python well enough to write *Python* pro-
grams in Python? given the things you complain about, I'm not so sure.

</F>
 
M

Michael Hudson

Paul Rubin said:
And yet, you can call a class instance if it has a __call__
operation defined. I don't see why modules shouldn't be the same.

Well, for a possible counter argument, consider that you can only call
an instance of a new-style class if the CLASS defines the __call__
method...

Cheers,
mwh
 
B

Bengt Richter

Well, for a possible counter argument, consider that you can only call
an instance of a new-style class if the CLASS defines the __call__
method...
ISTM you could give the module class a __call__ property, so you could
customize the callability of module instances something like:
----
class Callablinst(object):
def _getcallable(self): return self.__dict__['__call__']
def _setcallable(self,v): self.__dict__['__call__'] = v
__call__ = property(_getcallable, _setcallable)
---- Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "callablinst.py", line 2, in _getcallable
def _getcallable(self): return self.__dict__['__call__']
KeyError: '__call__' Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "callablinst.py", line 2, in _getcallable
def _getcallable(self): return self.__dict__['__call__']
KeyError: '__call__' 'I am c2'

UIAM, a def __call__(whatever): ... somewhere in the global scope of such a
module's source should then be picked up (depending on how the execution of
the def actually does the function name binding perhaps -- presumably it would
either bypass the attribute/property mechanism, or would use it). Either way
I would guess subsequent use of the module as callable would pick up the function
bound to __call__, but I'm not certain.

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,149
Latest member
Vinay Kumar Nevatia0
Top