Most general-purpose programming languages have either no support or limited support for complex numbers. Your typical options are learning some specialized tool like MATLAB or finding a third-party library. Python is a rare exception because it comes with complex numbers built in.
Despite the name, complex numbers aren’t complicated! They’re convenient in tackling practical problems that you’ll get a taste of in this tutorial. You’ll explore vector graphics and sound frequency analysis, but complex numbers can also help in drawing fractals, such as the Mandelbrot set.
In this tutorial, you’ll learn how to:
- Define complex numbers with literals in Python
- Represent complex numbers in rectangular and polar coordinates
- Use complex numbers in arithmetic expressions
- Take advantage of the built-in
cmathmodule - Translate mathematical formulas directly to Python code
If you need a quick refresher or a gentle introduction to the theory of complex numbers, then you can watch Khan Academy’s video series. To download the sample code used throughout this tutorial, click the link below:
Get Sample Code: Click here to get the sample code you’ll use to learn about complex numbers in Python in this tutorial.
Creating Complex Numbers in Python
Creating and manipulating complex numbers in Python isn’t much different from other built-in data types, particularly numeric types. It’s possible because the language treats them as first-class citizens. This means you can express mathematical formulas that involve complex numbers with little overhead.
Python lets you use complex numbers in arithmetic expressions and call functions on them just like you would with other numbers in Python. It leads to elegant syntax that reads almost like a math textbook.
Complex Number Literal
The quickest way to define a complex number in Python is by typing its literal directly in the source code:
>>> z = 3 + 2j
Although this looks like an algebraic formula, the expression to the right of the equals sign is already a fixed value that needs no further evaluation. When you check its type, you’ll confirm that it’s indeed a complex number:
>>> type(z)
<class 'complex'>
How is that different from adding two numbers with the plus operator? A clear giveaway is the letter j glued to the second number, which completely changes the meaning of the expression. If you removed the letter, you’d get a familiar integer result instead:
>>> z = 3 + 2
>>> type(z)
<class 'int'>
By the way, you can use floating-point numbers to create complex numbers, too:
>>> z = 3.14 + 2.71j
>>> type(z)
<class 'complex'>
Complex number literals in Python mimic the mathematical notation, which is also known as the standard form, the algebraic form, or sometimes the canonical form, of a complex number. In Python, you can use either lowercase j or uppercase J in those literals.
If you learned about complex numbers in math class, you might have seen them expressed using an i instead of a j. If you’re curious about why Python uses j instead of i, then you can expand the collapsible section below to learn more.
The traditional notation for complex numbers uses the letter i instead of j since it stands for the imaginary unit. You might feel a slight discomfort with Python’s convention if you have a mathematical background. However, there are a few reasons that can justify Python’s controversial choice:
- It’s a convention already adopted by engineers to avoid name collisions with electric current, which is denoted with the letter
i. - In computing, the letter
iis often used for the indexing variable in loops. - The letter
ican be easily confused withlor1in source code.
This was brought up on Python’s bug tracker over a decade ago, and Python’s creator, Guido van Rossum himself, closed the issue with this comment:
This will not be fixed. For one thing, the letter ‘i’ or upper case ‘I’ look too much like digits. The way numbers are parsed either by the language parser (in source code) or by the built-in functions (int, float, complex) should not be localizable or configurable in any way; that’s asking for huge disappointments down the road. If you want to parse complex numbers using ‘i’ instead of ‘j’, you have plenty of solutions available already. (Source)
So there you have it. Unless you want to start using MATLAB, you’ll have to live with using j to denote your complex numbers.
The algebraic form of a complex number follows the standard rules of algebra, which is convenient in performing arithmetic. For example, addition has a commutative property, which lets you swap the order of the two parts of a complex number literal without changing its value:
>>> 3 + 2j == 2j + 3
True
Similarly, you can substitute addition for subtraction in a complex number literal because the minus sign is just a shorthand notation for an equivalent form:
>>> 3 - 2j == 3 + (-2j)
True
Does a complex number literal in Python always have to comprise two numbers? Can it have more? Are they ordered? To answer these questions, let’s run some experiments. Unsurprisingly, if you specify only one number, without the letter j, then you’ll end up with a regular integer or a floating-point number:
>>> z = 3.14
>>> type(z)
<class 'float'>
On the other hand, appending the letter j to a numeric literal will immediately turn it into a complex number:
>>> z = 3.14j
>>> type(z)
<class 'complex'>
Strictly speaking, from a mathematical standpoint, you’ve just created a pure imaginary number, but Python can’t represent it as a stand-alone data type. Therefore, without the other part, it’s just a complex number .
How about the opposite? To create a complex number without the imaginary part, you can take advantage of zero and add or subtract it like so:
>>> z = 3.14 + 0j
>>> type(z)
<class 'complex'>
In fact, both parts of the complex number are always there. When you don’t see one, it means that it has a value of zero. Let’s check what happens when you try stuffing more terms into the sum than before:
>>> 2 + 3j + 4 + 5j
(6+8j)
This time, your expression is no longer a literal because Python evaluated it into a complex number comprising only two parts. Remember that the basic rules of algebra carry over to complex numbers, so if you group similar terms and apply component-wise addition, then you’ll end up with 6 + 8j.
Notice how Python displays complex numbers by default. Their textual representation contains an enclosing pair of parentheses, a lowercase letter j, and no whitespace. Additionally, the imaginary part comes second.
Complex numbers that also happen to be pure imaginary numbers show up without parentheses and only reveal their imaginary part:
>>> 3 + 0j
(3+0j)
>>> 0 + 3j
3j
This helps differentiate imaginary numbers from most complex numbers made up of real and imaginary parts.
complex() Factory Function
Python has a built-in function, complex(), that you can use as an alternative to the complex number literal:
>>> z = complex(3, 2)
In this form, it resembles a tuple or an ordered pair of ordinary numbers. The analogy isn’t that far-fetched. Complex numbers have a geometric interpretation in the Cartesian coordinate system that you’ll explore in a bit. You can think of complex numbers as two-dimensional.
Fun fact: In math, complex numbers are traditionally denoted with the letter z as it’s the next letter in the alphabet after x and y, which commonly represent coordinates.
The complex number factory function accepts two numeric parameters. The first one represents the real part, while the second one represents the imaginary part denoted with the letter j in the literal you saw earlier:
>>> complex(3, 2) == 3 + 2j
True
Both parameters are optional, with default values of zero, which makes it less clunky to define complex numbers without the imaginary part or both the real and imaginary parts:
>>> complex(3) == 3 + 0j
True
>>> complex() == 0 + 0j
True
The single-argument version can be useful in type casting. For example, you can pass a nonnumeric value like a string literal to obtain a corresponding complex object. Note that the string can’t contain any whitespace, though:
>>> complex("3+2j")
(3+2j)
>>> complex("3 + 2j")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: complex() arg is a malformed string
Later, you’ll find out how to make your classes compatible with this type casting mechanism. Interestingly, when you pass a complex number to complex(), you’ll get the same instance back:
>>> z = complex(3, 2)
>>> z is complex(z)
True
That’s consistent with how other types of numbers in Python work because they’re all immutable. To make a distinct copy of a complex number, you must call the function with both arguments again or declare another variable with the complex number literal:
>>> z = complex(3, 2)
>>> z is complex(3, 2)
False
When you provide two arguments to the function, they must always be numbers, such as int, float, or complex. Otherwise, you’ll get a runtime error. Technically speaking, bool is a subclass of int, so it’ll work too:
>>> complex(False, True) # Booleans, same as complex(0, 1)
1j
>>> complex(3, 2) # Integers
(3+2j)
>>> complex(3.14, 2.71) # Floating-point numbers
(3.14+2.71j)
>>> complex("3", "2") # Strings
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: complex() can't take second arg if first is a string
Things get seemingly more bizarre when you supply the complex() factory function with complex numbers as arguments. If you provide only the first argument, though, it’ll behave like a proxy as before:
>>> complex(complex(3, 2))
(3+2j)
However, when two arguments are present and at least one of them is a complex number, you’ll get results that may be difficult to explain at first sight:
>>> complex(1, complex(3, 2))
(-1+3j)
>>> complex(complex(3, 2), 1)
(3+3j)
>>> complex(complex(3, 2), complex(3, 2))
(1+5j)
To get the answers, let’s take a peek at the factory function’s docstring or the online documentation, which explain what’s going on under the hood when you call complex(real, imag):
Return a complex number with the value real + imag*1j or convert a string or number to a complex number. (Source)
In this explanation, real and imag are names of the function arguments. The second argument gets multiplied by the imaginary unit j, and the result is added to the first argument. Don’t worry if it still doesn’t make any sense. You can come back to this part when you’ve read about complex numbers arithmetic. The rules that you’ll learn about will make this straightforward.
When would you want to use the complex() factory function over the literal? It depends, but calling the function may be more convenient when you’re dealing with dynamically generated data, for example.
Getting to Know Python Complex Numbers
In mathematics, complex numbers are a superset of real numbers, which means that every real number is also a complex number whose imaginary part is equal to zero. Python models this relationship through a concept called the numeric tower, described in PEP 3141:
>>> import numbers
>>> issubclass(numbers.Real, numbers.Complex)
True
The built-in numbers module defines a hierarchy of numeric types through abstract classes that can be used for type checking and classifying numbers. For example, to determine if a value belongs to a specific set of numbers, you can call isinstance() on it:
>>> isinstance(3.14, numbers.Complex)
True
>>> isinstance(3.14, numbers.Integral)
False
The floating-point value 3.14 is a real number that also happens to be a complex number but not an integral one. Note that you can’t use built-in types directly in such a test:
>>> isinstance(3.14, complex)
False
The difference between complex and numbers.Complex is that they belong to separate branches in the numeric type hierarchy tree, and the latter is an abstract base class without any implementation:

Abstract base classes, which are denoted in red on the diagram above, can bypass the regular inheritance check mechanism by registering unrelated classes as their virtual subclasses. That’s why a floating-point value in the example appears to be an instance of numbers.Complex but not complex.
Accessing Real and Imaginary Parts
To get the real and imaginary parts of a complex number in Python, you can reach for the corresponding .real and .imag attributes:
>>> z = 3 + 2j
>>> z.real
3.0
>>> z.imag
2.0
Both properties are read-only because complex numbers are immutable, so trying to assign a new value to either of them will fail:
>>> z.real = 3.14
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
Since every number in Python is a more specific type of a complex number, attributes and methods defined in numbers.Complex are also available in all numeric types, including int and float:
>>> x = 42
>>> x.real
42
>>> x.imag
0
The imaginary part of such numbers is always zero.
Calculating the Conjugate of a Complex Number
Python complex numbers have only three public members. Apart from the .real and .imag properties, they expose the .conjugate() method, which flips the sign of the imaginary part:
>>> z = 3 + 2j
>>> z.conjugate()
(3-2j)
For numbers whose imaginary part equals zero, it won’t have any effect:
>>> x = 3.14
>>> x.conjugate()
3.14
This operation is its own inverse, so calling it twice will get you the original number you started with:
>>> z.conjugate().conjugate() == z
True