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?

6

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.