10.4 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.
from std.python import Python
def main() raises:
var py_module = """
def type_printer(value):
print(type(value))
"""
var 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")
Show expected 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 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(), Python.list(), and Python.tuple() static methods.
For example, to create a Python dictionary, use the Python.dict() method:
from std.python import Python
def main() raises:
var py_dict = Python.dict()
py_dict["item_name"] = "whizbang"
py_dict["price"] = 11.75
py_dict["inventory"] = 100
print(py_dict)
Show output ✓ Verified · Mojo 1.1.0 (8189361e)
{'item_name': 'whizbang', 'price': 11.75, 'inventory': 100}With the Python.list() method, you can create a Python list and optionally initialize it:
from std.python import Python
def main() raises:
var py_list = Python.list("cat", 2, 3.14159, 4)
var n = py_list[2]
print("n =", n)
py_list.append(5)
py_list[0] = "aardvark"
print(py_list)
Show output ✓ Verified · Mojo 1.1.0 (8189361e)
n = 3.14159
['aardvark', 2, 3.14159, 4, 5]The Python.tuple() method creates a Python tuple of values:
from std.python import Python
def main() raises:
var py_tuple = Python.tuple("cat", 2, 3.1415, "cat")
var n = py_tuple[2]
print("n =", n)
print("Number of cats:", py_tuple.count("cat"))
Show output ✓ Verified · Mojo 1.1.0 (8189361e)
n = 3.1415
Number of cats: 2If you want to construct a Python type that doesn't have a literal Mojo equivalent, you can also use the Python.evaluate() method. For example, to create a Python set:
from std.python import Python
def main() raises:
var py_set = Python.evaluate('{2, 3, 2, 7, 11, 3}')
var num_items = len(py_set)
print(num_items, "items in the set.")
var contained = 7 in py_set
print("Is 7 in the set:", contained)
Show output ✓ Verified · Mojo 1.1.0 (8189361e)
4 items in the set.
Is 7 in the set: TruePythonObject implements the Writable trait. This allows you to print Python values using the built-in 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:
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() 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:
from std.python import Python
def main() raises:
var value1 = PythonObject(3.7)
var 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
var value3 = value2
print("value1 is value2:", value1 is value2)
print("value2 is value3:", value2 is value3)
# Compare types
var 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)
Show expected 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: TrueAdapted from the Mojo Manual and the MAX GPU programming guides, part of the Modular Platform repository (github.com/modular/modular), Copyright (c) Modular Inc., licensed under the Apache License v2.0 with LLVM Exceptions. Changes were made: reformatted as an accessible XYZ web edition with build-verified example outputs. Mojo and MAX are trademarks of Modular Inc.; this edition is not affiliated with or endorsed by Modular. License: Apache-2.0 WITH LLVM-exception.