The Python programming language is known for performing poorly on many tasks. While to some extent this is to be expected from a dynamic language, it is not clear how much each dynamic feature contributes to the costs of interpreting Python. In this study we attempt to quantify the costs of language features such as dynamic typing, reference counting for memory management, boxing of numbers, and late binding of function calls.We use an experimental compilation framework for Python that can make use of type annotations provided by the user to specialize the program as well as elide unnecessary reference counting operations and function lookups. The compiled programs run within the Python interpreter and use its internal API to implement language semantics. By separately enabling and disabling compiler optimizations, we can thus measure how much each language feature contributes to total execution time in the interpreter.We find that a boxed representation of numbers as heap objects is the single most costly language feature on numeric codes, accounting for up to 43 % of total execution time in our benchmark set. On symbolic object-oriented code, late binding of function and method calls costs up to 30 %. Redundant reference counting, dynamic type checks, and Python's elaborate function calling convention have comparatively smaller costs.Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than the author(s) must be honored. Abstracting with credit is permitted. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Request permissions from Permissions@acm.org.Python is a popular programming language, but it has a reputation of being slow. Projects such as the PyPy just-intime compiler [BCFR09] show that it is possible to execute some Python programs up to 50 times faster while remaining faithful to its semantics.Why, then, is the standard Python interpreter (often called CPython) so slow? Is it due to interpretation overhead? Due to dynamic typing and late binding of operations? Due to the boxing of numbers, or due to the overhead of automatic memory management by reference counting?We attempt to answer some of these questions by measuring the execution times of Python programs with and without enabling the corresponding language features. Simply turning off language features is obviously infeasible in the standard interpreter, but we sidestep this problem in a novel way by using a compiler to specialize programs while still running them inside the interpreter. Type annotations from the user and simple program analysis allow us to turn off language features where it is safe to do so, but to still adhere to Python's dynamic semantics otherwise.This kind of analysi...