> For the complete Mojo documentation index, see [llms.txt](/llms.txt).
> Markdown versions of all pages are available by appending .md to any URL (e.g. /docs/manual/basics.md).

# Python types

When calling Python methods, Mojo needs to convert back and forth between native
Python objects and native Mojo objects. Most of these conversions happen
automatically, but there are a number of cases that Mojo doesn't handle yet.
In these cases you may need to do an explicit conversion, or call an extra
method.

## Mojo types in Python

Mojo primitive types implicitly convert into Python objects. Today we support
integers, floats, booleans, and strings.

To demonstrate, the following example dynamically creates an in-memory Python
module named `py_utils` containing a `type_printer()` function, which simply
prints the type of a given value. Then you can see how different Mojo values
convert into corresponding Python types.

```mojo
from std.python import Python

def main() raises:
    py_module = """
def type_printer(value):
    print(type(value))
"""
    py_utils = Python.evaluate(py_module, file=True, name="py_utils")

    py_utils.type_printer(4)
    py_utils.type_printer(3.14)
    py_utils.type_printer(True)
    py_utils.type_printer("Mojo")
```

```output
<class 'int'>
<class 'float'>
<class 'bool'>
<class 'str'>
```

## Python types in Mojo

You can also create and use Python objects from Mojo.

### Mojo wrapper objects

When you use Python objects in your Mojo code, Mojo adds the
[`PythonObject`](/docs/std/python/python_object/PythonObject/) wrapper around
the Python object. This object exposes a number of common double underscore
methods (dunder methods) like `__getitem__()` and `__getattr__()`, passing them
through to the underlying Python object. Most of the time, you can treat the
wrapped object just like you'd treat it in Python. You can use dot-notation to
access attributes and call methods, and use the `[]` operator to access an item
in a sequence.

You can explicitly create a wrapped Python object by initializing a
`PythonObject` with a Mojo integer, float, boolean, or string. Additionally, you
can create several types of Python collections directly in Mojo using the
[`Python.dict()`](/docs/std/python/python/Python/#dict),
[`Python.list()`](/docs/std/python/python/Python/#list), and
[`Python.tuple()`](/docs/std/python/python/Python/#tuple) static methods.

For example, to create a Python dictionary, use the
[`Python.dict()`](/docs/std/python/python/Python/#dict) method:

```mojo
from std.python import Python

def main() raises:
    py_dict = Python.dict()
    py_dict["item_name"] = "whizbang"
    py_dict["price"] = 11.75
    py_dict["inventory"] = 100
    print(py_dict)
```

```output
{'item_name': 'whizbang', 'price': 11.75, 'inventory': 100}
```

With the [`Python.list()`](/docs/std/python/python/Python/#list) method, you
can create a Python list and optionally initialize it:

```mojo
from std.python import Python

def main() raises:
    py_list = Python.list("cat", 2, 3.14159, 4)
    n = py_list[2]
    print("n =", n)
    py_list.append(5)
    py_list[0] = "aardvark"
    print(py_list)
```

```output
n = 3.14159
['aardvark', 2, 3.14159, 4, 5]
```

The [`Python.tuple()`](/docs/std/python/python/Python/#tuple) method creates a
Python tuple of values:

```mojo
from std.python import Python

def main() raises:
    py_tuple = Python.tuple("cat", 2, 3.1415, "cat")
    n = py_tuple[2]
    print("n =", n)
    print("Number of cats:", py_tuple.count("cat"))
```

```output
n = 3.1415
Number of cats: 2
```

If you want to construct a Python type that doesn't have a literal Mojo
equivalent, you can also use the
[`Python.evaluate()`](/docs/std/python/python/Python/#evaluate) method. For
example, to create a Python `set`:

```mojo
from std.python import Python

def main() raises:
    var py_set = Python.evaluate('{2, 3, 2, 7, 11, 3}')
    num_items = len(py_set)
    print(num_items, "items in the set.")
    contained = 7 in py_set
    print("Is 7 in the set:", contained)
```

```output
4 items in the set.
Is 7 in the set: True
```

`PythonObject` implements the [`Writable`](/docs/std/format/Writable/)
trait. This allows you to print Python values using the built-in
[`print()`](/docs/std/io/io/print/) function, as shown in several of the
previous examples.

However, most other Mojo APIs don't accept `PythonObject` values directly. In
these cases you'll need to explicitly convert a Python value into a native Mojo
value. For example:

```mojo
from std.python import Python
from std.python import PythonObject

def main() raises:
    var py_string = PythonObject("Hello, Mojo!")
    var py_bool = PythonObject(True)
    var py_int = PythonObject(123)
    var py_float = PythonObject(3.14)

    var mojo_string = String(py=py_string)
    var mojo_bool = Bool(py=py_bool)
    var mojo_int = Int(py=py_int)
    var mojo_float = Float64(py=py_float)
```

### Comparing Python types in Mojo

You can use Python objects in Mojo comparison expressions, and the Mojo `is`
operator also works to compare the identity of two Python objects. Python values
like `False` and `None` evaluate as false in Mojo boolean expressions as well.

If you need to know the type of the underlying Python object, you can use the
[`Python.type()`](/docs/std/python/python/Python/#type) method, which is
equivalent to the Python `type()` builtin. You can test if a Python
object is of a particular type by performing an identity comparison against the
type as shown below:

```mojo
from std.python import Python

def main() raises:
    var value1 = PythonObject(3.7)
    value2 = Python.evaluate("10/3")

    # Compare values
    print("Is value1 greater than 3:", value1 > 3)
    print("Is value1 greater than value2:", value1 > value2)

    # Compare identities
    value3 = value2
    print("value1 is value2:", value1 is value2)
    print("value2 is value3:", value2 is value3)

    # Compare types
    py_float_type = Python.evaluate("float")
    print("Python float type:", py_float_type)
    print("value1 type:", Python.type(value1))
    print("Is value1 a Python float:", Python.type(value1) is py_float_type)
```

```output
Is value1 greater than 3: True
Is value1 greater than value2: True
value1 is value2: False
value2 is value3: True
Python float type: <class 'float'>
value1 type: <class 'float'>
Is value1 a Python float: True
```
