What is type conversion in Python?

Hi,
i want to know what is type conversion in python

Type conversion in Python is the same as type conversion in nearly all
programming languages. It is converting a value from one type to another
type. Run this and see what it does:

a = "  1.0  "
print(type(a))
b = float(a)  # Type conversion.
print(type(b))

Strings like a = " 1.0 " look like a number, but they are strings.
They have methods like

  • remove spaces at the ends: print(a.strip())

  • replace substrings: print(a.replace('.', 'ZZZ'))

but you can’t do maths on them:

  • this will fail: a + 1

Here’s another example for you to experiment on:

a = (1, 2, 3)
b = list(a)

What is the type of a? What methods does it offer? What can you do
with a?

What is the type of b? What methods does it offer, and what can you do
with it?

(Hint: to see the methods offered by a value a, try dir(a), or
help(a), or read the docs.)

Just to elaborate on this a little. Notice that “float(a)” looks like a
function call? It is a function call. Well, we are calling a class
(the 'float" class), which is how you make new objects of that class,
but it is still “calling” something, and getting a result from that
call.

So “conversion” does not mean here: change the type of something in
place
. It means: make a new object of your desired type, computed
from the value of the original object.

Cheers,
Cameron Simpson cs@cskk.id.au

1 Like

Hi @cameron

Does it mean that built-in types like float are callable?

Indeed, and not only built-in types:

>>> class MyClass():
...     def hello(self):
...         print(f'Hi, I am an object of type {str(type(self))}') 
... 
>>> m = MyClass()
>>> m.hello()
Hi, I am an object of type <class '__main__.MyClass'>

“Calling” a class of any type will create an instance of that class and call its __init__() method, to give you the chance to initialize it.

Hi @Mholscher

AFAIK types and classes are different things.

A callable class implements the __call__ method, and its instantiated object can be called like a function.

In my understanding, float is a type, but not a class. So I’m curious whether it is callable or not.

Reference:

The CPython documentation disagrees with you: class float definition

I have to admit, I have been carelessly mixing type and class. To my defense, I am in good company: type returns the class of an object.

Let us experiment some:

>>> from flask import Flask
>>> hasattr(Flask, '__call__')
True

So the Flask class is a callable, so we can instantiate it by executing Flask(). Now we try:

>>> hasattr(float, '__call__')
True

So float is also class and a callable and can be instantiated by executing float().

This is careful observation. Thanks for your explanation.

Now I learn that float used in type conversion is actually a class.

In Python, “type” and “class” mean the same thing.

Of course class is a reserved keyword, and type() is a built-in
function. But they do the same thing: they both create classes.

>>> class Cat:
...     pass
... 
>>> print(Cat)
<class '__main__.Cat'>

>>> Dog = type("Dog", (), {})
>>> print(Dog)
<class '__main__.Dog'>

The class keyword is just syntactic sugar for type, which is itself
a class. When you call type with one argument, it returns the class of
that argument; when you call it with three arguments, it returns a new
instance of type:

>>> isinstance(Cat, type)
True
>>> isinstance(Dog, type)
True

That’s right: all classes in Python are instances of type. We call the
special class “type” a metaclass: it is the class of all classes.

>>> import inspect
>>> inspect.isclass(float)
True
>>> inspect.isclass(type)
True
>>> inspect.isclass(Cat)
True
>>> inspect.isclass(Dog)
True

So now, in Python 3, classes and types are the same thing. They are just
two different words for the same concept.

But back in the ancient days of Python version 1.x, types and classes
were different things. Built-in objects like strings, lists, floats,
dicts etc belonged to types; things you created yourself with the
class keyword belongs to classes, and they were different kinds of
things.

The consequences of this were:

  • you could not create a new type except with a C extension;

  • you could not subclass the built-in types like str, float etc;

  • you could not inherit from built-ins;

  • there were some slight differences in behaviour between instances of
    types and instances of classes;

  • and built-ins like int, float, str etc were actually functions.

So in Python 1.5, the metaclass of all classes you created with the
class keyword was a special type called “class”.

But in Python 2.2, classes and types were unified into a single kind of
thing:

  • “type” and “class” became different names for the same thing;

  • so now you could create new types;

  • you can now subclass built-in types like str, float etc;

  • and inherit from those built-ins;

  • and the named functions int, float etc became the actual type
    objects themselves, as they are today.

However, there is a small wrinkle. Because types and classes behaved
slightly differently in Python 1, we needed to avoid breaking code
that relied on those differences. (Until Python 3, when we finally got
rid of them!)

So we had to keep the old behaviour, which we called “Old Style
Classes”, or “Classic Classes”. Old code from Python 1 stayed exactly
the same as before.

To get a “New Style Class”, or type, you had to:

  • inherit from object;

  • or inherit from another built-in like int or list;

  • or use the three-argument form of type().

So from Python 2.2 to Python 2.7, there were new-style classes, which
are the same as types, and old-style classes, which were not. This was
horrible and confusing and finally in Python 3 old-style classes
disappeared forever.

You can read more about this type/class unification here:

https://www.python.org/download/releases/2.2.3/descrintro/

See also the relevent documentation:

https://docs.python.org/3/library/functions.html#type

https://docs.python.org/3/reference/compound_stmts.html#class

1 Like

If you want to know whether something is callable, you can use the
callable built-in to check:

>>> callable(5)
False
>>> callable(float)
True

https://docs.python.org/3/library/functions.html#callable

Objects that are callable in Python include:

  • classes/types
  • functions and methods
  • and object whose class has a special method __call__.

3. Data model — Python 3.9.1 documentation.call

float is a class, and classes are callable, so float is callable.
And sure enough, we can call float:

>>> float("123")
123.0
1 Like

AFAIK types and classes are different things.

Not in Python.

A callable class implements the __call__ method, and its instantiated object can be called like a function.
In my understanding, float is a type, but not a class. So I’m curious
whether it is callable or not.

Reference:
python - What is a "callable"? - Stack Overflow

Hahaha! The problem with stackoverflow and its friends is that they are
filled with misinformation and bad advice. Also good infrmation and good
advice, but they’re basicly hearsay. If you hear from someone with
incorrect ideas, you hear incorrect information. Or vague information.

All classes are callable, because that is what you do to instantiate a
new object:

x = int(9)      # an int from an int
x = int("9")    # an int from a string
x = int(9.0)    # an int from a float

You’re conflating call with a “callable class”. What call does
is make the instances callable.

So, an int such as 9 or a float such as 9.0 is not callable.

But if I make class with a call method:

class C:

    def __init__(self, name):
        self.name = name

    def __call__(self, something):
        return "Hello " + self.name + ", here is a " + something + "."

Then:

c = C("Ssuching Yu")

That makes an instance of “C” with the name “Ssuching Yu”. We did that
by calling the class. That returns an instance.

Because there is a call method, we can call “c”:

result = c("piece of example code")

Now the variable result should contain:

"Hello Ssuching Yu, here is a piece of example code."

By contrast, an int is not callable. First, call the int class to make
an int:

x = int("9")

but we cannot call the instance:

x()

because the class has no call method. In full at the Python prompt:

>>> x = int("9")
>>> x
9
>>> x()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

Cheers,
Cameron Simpson cs@cskk.id.au

1 Like

Hi Cameron,

Just a word to the wise… I think you are replying to these from email?
Like me.

In email, your post is fine, but on the Discuss archive, the text is
formatted using Markdown, and that gives special meaning to underscores.
Specifically, when you write __call__ without protecting it in
backticks, it gets treated as bold.

See your post here:

Without escaping: call

Backticks: __call__

Backslash escapes: __call__ (I haven’t tried this one before,
let’s see if it works.)

Hope this helps!

Just a word to the wise… I think you are replying to these from
email?
Like me.

Of course I am. Who would do otherwise?

In email, your post is fine, but on the Discuss archive, the text is
formatted using Markdown, and that gives special meaning to underscores.
Specifically, when you write __call__ without protecting it in
backticks, it gets treated as bold.

Ah, yes. I do forget that one. Fortunately the indented code examples
are not so mangled. My bitbucket commits are also missummarised:

https://bitbucket.org/cameron_simpson/css/commits/all

See commit d0ea338 for example. Not mangled in the diff, if you follow
the link. Github don’t seem to mangle that:

https://github.com/cameron-simpson/css/commits/master

but OTOH thet do intercept my mentions of decorators such as @foo and
ping the matching GitHub user if there is one. Fortunately the
collisions are few.

Without escaping: call
Backticks: __call__

Fortunately I have a double backtick vim macro to apply that, since I
use markdown in my Python docstrings.

Backslash escapes: __call__ (I haven’t tried this one before,
let’s see if it works.)

Painful. But double backticks is easy. Thanks for the heads up.

Cheers,
Cameron Simpson cs@cskk.id.au

Hi @steven.daprano @cameron. Your explanations teach me a lot. I really should take notes of your replies and learn more about Python data models.