subclassing a module: misleading(?) error message

E

Erik Johnson

I ran into a problem I didn't understand at first. I got part of it figured
out. Let me first demonstrate the original problem:
cat Super.py

class Super(object):
def __init__(self):
self._class = 'Super'
def hello(self):
print "%s says 'Hello'" % self._class
cat Sub.py

import Super

class Sub(Super):
def __init__(self):
self._class = 'Sub'
Python 2.3.4 (#1, Feb 7 2005, 15:50:45)
[GCC 3.3.4 (pre 3.3.5 20040809)] on linux2
Type "help", "copyright", "credits" or "license" for more information.Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "Sub.py", line 4, in ?
class Sub(Super):
TypeError: function takes at most 2 arguments (3 given)
My question is NOT "What's wrong here?"
(The answer to that is that the import in Sub.py should be: from Super
import Super
i.e., I tried to use the module itself where I meant to subclass the class
defined in that module).

My questions are:

Why does python complain about a function here? (it's a class definition
statement, right?)
Is there really a function being called here?
If so:
What function was called?
What two arguments is it expecting?
What three were given?

Thanks,
-ej
 
C

Carl Banks

Erik said:
My questions are:

Why does python complain about a function here? (it's a class definition
statement, right?)

Because you're calling the function with the wrong number of arguments.
Is there really a function being called here?

Yes. (Well, it's not exactly a function, but you are calling
something.)
If so:
What function was called?
types.ModuleType

What two arguments is it expecting?

The name of the module and a docstring.
What three were given?

1. The name of the class
2. The tuple of bases
3. A dict containing the symbols defined inside the class statement.

You are aware, I presume, that types (be it classes or built-in types)
are callable. For example, to create an instance of class of class X,
you would call X(). And to create a list, you can call list(). Well,
in the same way, you can call type(), with the three arguments above,
to create classes. And that's just what the class statement does under
the covers (usually).

The following class definition:

class A(object):
b = 1

is exactly equivalent to this explicit call to type:

A = type("A",(object,),{"b":1})

However, there are some cases where, instead of creating the class
object itself, type will instead call some other function to create it.
One way is if you define __metaclass__ in the class namespace: then
type will call the object spec. Another way is if there are any bases
which have a type other than type. (Remember, bases are supposed to be
type objects.)

That's what happened to you. type saw that type(Super) was
types.ModuleType, not type, so it called that instead of creating the
class itself. However, types.ModuleType doesn't accept that same
arguments that a normal type constructor does, so you get the error.

Does that clear things up? Probably not. For a detailed explanation
of how this all works, look for some resources on learning
"metaclasses" or "metatypes" in Python.


Carl Banks
 
H

Huayang Xia

So you know you are subclassing a module.

There is an answer @
http://www.velocityreviews.com/forums/showpost.php?p=1819038&postcount=2

I ran into a problem I didn't understand at first. I got part of it figured
out. Let me first demonstrate the original problem:
cat Super.pyclass Super(object):
def __init__(self):
self._class = 'Super'
def hello(self):
print "%s says 'Hello'" % self._class
cat Sub.pyimport Super

class Sub(Super):
def __init__(self):
self._class = 'Sub'
pythonPython 2.3.4 (#1, Feb 7 2005, 15:50:45)
[GCC 3.3.4 (pre 3.3.5 20040809)] on linux2
Type "help", "copyright", "credits" or "license" for more information.>>> from Super import SuperFile "<stdin>", line 1, in ?
File "Sub.py", line 4, in ?
class Sub(Super):
TypeError: function takes at most 2 arguments (3 given)

My question is NOT "What's wrong here?"
(The answer to that is that the import in Sub.py should be: from Super
import Super
i.e., I tried to use the module itself where I meant to subclass the class
defined in that module).

My questions are:

Why does python complain about a function here? (it's a class definition
statement, right?)
Is there really a function being called here?
If so:
What function was called?
What two arguments is it expecting?
What three were given?

Thanks,
-ej
 
G

Gabriel Genellina

Python 2.3.4 (#1, Feb 7 2005, 15:50:45)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "Sub.py", line 4, in ?
class Sub(Super):
TypeError: function takes at most 2 arguments (3 given)

Why does python complain about a function here? (it's a class definition
statement, right?)
Is there really a function being called here?
If so:
What function was called?
What two arguments is it expecting?
What three were given?

The same thing on Python 2.4.2 (at least) prints a much more meaningful error:

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: Error when calling the metaclass bases
module.__init__() takes at most 2 arguments (3 given)


--
Gabriel Genellina
Softlab SRL






__________________________________________________
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas
 
E

ej

Carl Banks wrote:

<snip> A good explanation

I have not been able to get back to news lately - lot going on, but
thank you for your time to explain that to me. It mostly makes pretty
good sense to me, but I will have to study metaclasses further. ;)

Thanks,
-ej
 

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,777
Messages
2,569,604
Members
45,230
Latest member
LifeBoostCBD

Latest Threads

Top