0

IPython seems inconsistent here:

In [1]: import sys

In [2]: sys.version
Out[2]: '3.10.11 (main, May 16 2023, 00:28:57) [GCC 11.2.0]'

In [4]: type(sys)
Out[4]: module

In [5]: type(module)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 type(module)

NameError: name 'module' is not defined

In [6]: type(type(sys))
Out[6]: type

How can something that is not defined be a type and have a type?

I found this after discovering that no class module exists, although, if I import some module of mine, it automatically inherits attributes

 '__builtins__',
 '__cached__',
 '__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',

What are these attributes inherited from?

Pierre ALBARÈDE
  • 413
  • 4
  • 10
  • 1
    I found this link talking about attributes of modules: https://peps.python.org/pep-0451/ – minolee Jun 19 '23 at 00:07
  • "This PEP proposes to add a new class to importlib.machinery called “ModuleSpec”". `import importlib.machinery;importlib.machinery.__file__`, I look at file content and find `from ._bootstrap import ModuleSpec`. Running this in Python: `mportError: attempted relative import with no known parent package`. – Pierre ALBARÈDE Jun 19 '23 at 00:27
  • I did not find it in my system but there it is https://pykaldi.github.io/_modules/importlib/_bootstrap.html. – Pierre ALBARÈDE Jun 19 '23 at 00:31
  • Theoretically, taking type of type leads to metaclass and some sort of paradox may be expected https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python?rq=2 – Pierre ALBARÈDE Jun 19 '23 at 05:46
  • cpython has implementation detail of module object: https://docs.python.org/3/c-api/module.html and https://github.com/python/cpython/blob/4426279a4399158027a1145cff1c4c92424bf5b5/Objects/moduleobject.c#L109 – minolee Jun 19 '23 at 07:19
  • Can you check `type(module)` in cpython? I may install cpython as well but it would take more time. – Pierre ALBARÈDE Jun 19 '23 at 09:22

1 Answers1

1

Although sys.version returns Python version number, I realize that I am using IPython (version 8.14.0 from ipython --version in the Unix command line.)

The situation differs in Python:

>>> import sys;sys.version
'3.10.11 (main, May 16 2023, 00:28:57) [GCC 11.2.0]'
>>> type(sys)
<class 'module'>
>>> type(type(sys))
<class 'type'>
>>> typesys=type(sys)
>>> typesys
<class 'module'>
>>> type(typesys)
<class 'type'>
>>> dir(typesys)
['__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', 
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', 
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
'__sizeof__', '__str__', '__subclasshook__']

>>>help(typesys)
Help on class module in module builtins:

class module(object)
 |  module(name, doc=None)
 |  
 |  Create a module object.
 |  
 |  The name must be a string; the optional doc argument can have any type.
 |  
 |  Methods defined here:
 |  
 |  __delattr__(self, name, /)
 |      Implement delattr(self, name).
 |  

Answer to the first question

Python wraps type value:

>>> type(2)
<class 'int'>

so that it takes less space but does not refer to an object:

>>> <class 'int'>
  File "<stdin>", line 1
    <class 'int'>
    ^
SyntaxError: invalid syntax

This is confusing at first since everything is supposed to be an object in Python but the same occurs when defining a function:

>>> def f1(x):return x
>>> f1
<function f1 at 0x7f3df38f88b0>

Even more confusing, IPython does not show any wrapper.

Hence, type(2) does not evaluate to <class 'int'>) but int, which refers to an object by accident with respect to most classes. import(sys);type(sys) evaluates to module which does not refer to an object. Same with function:

In [3]: def f1(x):return x

In [4]: type(f1)
Out[4]: function

In [5]: function
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 function

NameError: name 'function' is not defined

The wrapped object can be accessed by naming:

>>> typeint=type(int)
>>> import sys;typesys=type(sys)
>>> (typeint,typesys)
(<class 'type'>, <class 'module'>)

It occurs that int, function, module are normal names in Python or iPython (int=4 does not throw an error).

One way to fix IPython is simply import sys;module=type(sys) so that type(module) works nicely like type(int) although now module has this apparently confusing behaviour:

In [7]: module
Out[7]: module

like

In [1]: int
Out[1]: int

Partial answer to the second question

The class module exists. help(type(sys))works.

Probably, it has many subclasses, possibly ModuleSpec, though I can't prove it.

Difference between type and class

When type is applied twice (or more, on any object) it always evaluates to the class type.

>>> type(type(1))
<class 'type'>

In Python 2.7 type(type(1)) or type(type(sys)) evaluates to <type 'type'>. In Python ≥ 2.7, type and class have no semantic difference.

Alternative syntax:

>>> int.__class__
<class 'type'>

Type or class is a member of itself:

>>> type(type)
<class 'type'>
>>> type(type)==type
True
>>> type(type) is type
True
>>> isinstance(type,type)
True

class can be used to define a class:

>>> class object:pass

type with functional syntax can also be used with 3 parameters to define a class (see help(type)).

See also

Pierre ALBARÈDE
  • 413
  • 4
  • 10