{"id":12094,"date":"2026-07-05T04:06:16","date_gmt":"2026-07-05T04:06:16","guid":{"rendered":"https:\/\/www.askpython.com\/?p=12094"},"modified":"2026-07-05T10:55:56","modified_gmt":"2026-07-05T10:55:56","slug":"colon-in-python","status":"publish","type":"post","link":"https:\/\/www.askpython.com\/python\/examples\/colon-in-python","title":{"rendered":"Colon in Python: Every Place It Appears and What It Does"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I kept tripping on the colon in Python, where every few lines something refused to run over one character. The colon plays five different roles in the language, each with its own failure mode.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Knowing which role is on screen is most of the job.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Starting a code block<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The most common position is at the end of an if line. The same rule covers every compound statement: else, elif, for, while, def, class, try, except, finally, with, and match all end their header line with a colon, and the colon tells the interpreter an indented block follows.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nmarks = 75\nif marks &gt; 40:\n    print(&quot;Pass&quot;)\nelse:\n    print(&quot;Fail&quot;)\n\n# Output: Pass\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Type a colon in the REPL and hit Enter: the prompt changes to &#8230; and waits for the indented body.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"760\" height=\"304\" src=\"https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-indentation-repl.png\" alt=\"Python REPL showing a colon starting an if\/else block with automatic indentation\" class=\"wp-image-66899\" srcset=\"https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-indentation-repl.png 760w, https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-indentation-repl-300x120.png 300w\" sizes=\"auto, (max-width: 760px) 100vw, 760px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Loops and function definitions follow the same rule I described above. One colon, one indented block, no braces:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nfor i in range(3):\n    print(i, end=&quot; &quot;)\n# Output: 0 1 2\n\ndef area(r):\n    return 3.14159 * r * r\n\nprint(area(2))\n# Output: 12.56636\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Slicing strings and lists<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The second colon I ran into lived inside square brackets, where it works as the slice operator: sequence[start:stop:step]. Leave any part out and Python fills in a sensible default. The stop index is always excluded.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\ntext = &quot;AskPython&quot;\n\nprint(text&#x5B;3:])    # Python  (index 3 to end)\nprint(text&#x5B;:3])    # Ask     (start to index 2)\nprint(text&#x5B;3:7])   # Pyth    (index 3 up to, not including, 7)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Add a second colon and you control the step. A step of 2 takes every other character, and a step of -1 walks backwards, which is a string-reversal trick worth remembering:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"760\" height=\"330\" src=\"https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-slicing-repl.png\" alt=\"Python REPL demonstrating string slicing with colon syntax\" class=\"wp-image-66900\" srcset=\"https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-slicing-repl.png 760w, https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-slicing-repl-300x130.png 300w\" sizes=\"auto, (max-width: 760px) 100vw, 760px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Lists slice exactly the same way:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nnums = &#x5B;10, 20, 30, 40, 50]\n\nprint(nums&#x5B;1:4])   # &#x5B;20, 30, 40]\nprint(nums&#x5B;::2])   # &#x5B;10, 30, 50]\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The double colon you sometimes see, like nums[::2], is not a separate operator. It is a normal slice with the start and stop left empty.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Separating keys and values in dictionaries<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Dictionaries were where the colon stopped surprising me and started feeling consistent: it pairs each key with its value, both in literals and in comprehensions:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nprices = {&quot;apple&quot;: 40, &quot;banana&quot;: 10}\nprices&#x5B;&quot;cherry&quot;] = 80\nprint(prices)\n# {&#039;apple&#039;: 40, &#039;banana&#039;: 10, &#039;cherry&#039;: 80}\n\nsquares = {n: n**2 for n in range(1, 6)}\nprint(squares)\n# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Type hints and annotations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Type hints were the use I discovered last, mostly because nothing forces you to write them. Since PEP 484 the colon annotates variables and function parameters with expected types.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The interpreter ignores these at runtime. Editors and type checkers like mypy use them to catch bugs before the code runs, and they show up in any function signature another person will read.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\ndef greet(name: str, times: int = 1) -&gt; str:\n    return &quot;, &quot;.join(&#x5B;f&quot;Hello {name}&quot;] * times)\n\nprint(greet(&quot;Ninad&quot;, 2))\n# Output: Hello Ninad, Hello Ninad\n\nage: int = 30\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Two lookalikes that are not plain colons<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Two symbols share the colon\u2019s shape but follow different rules, and both show up in modern Python code often enough to trip a reader who has just built the five-role mental model.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The walrus operator (:=)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">While mapping the real colons I kept bumping into two symbols that look related but play by different rules. Python 3.8 added :=, which assigns a value inside an expression. I reach for it when a computed value needs testing on the same line:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\ndata = &#x5B;4, 11, 2, 19]\nif (n := len(data)) &gt; 3:\n    print(f&quot;{n} items, more than expected&quot;)\n# Output: 4 items, more than expected\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">The colon in lambda<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Inside a lambda, the colon separates the argument list from the single expression the function returns:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\ndouble = lambda x: x * 2\nprint(double(21))\n# Output: 42\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">The error you get when the colon is missing<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Most colon bugs come from forgetting it on a block header. Python 3.10+ names the problem exactly:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"760\" height=\"200\" src=\"https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-syntaxerror.png\" alt=\"Python SyntaxError: expected colon when the colon is missing after an if statement\" class=\"wp-image-66901\" srcset=\"https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-syntaxerror.png 760w, https:\/\/www.askpython.com\/wp-content\/uploads\/2026\/07\/colon-syntaxerror-300x79.png 300w\" sizes=\"auto, (max-width: 760px) 100vw, 760px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Older versions print the vaguer SyntaxError: invalid syntax pointing at the same spot. Add the colon back to the line above the indented block.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Assigning to a slice<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Slices work on the left side of = too. Assigning to a slice replaces that section of the list in place, and the replacement does not need to be the same length:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nnums = &#x5B;10, 20, 30, 40, 50]\nnums&#x5B;1:3] = &#x5B;99]          # two elements replaced by one\nprint(nums)\n# &#x5B;10, 99, 40, 50]\n\nnums&#x5B;len(nums):] = &#x5B;60]   # append via slice\nprint(nums)\n# &#x5B;10, 99, 40, 50, 60]\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Extended slices (with a step) accept an iterable of exactly matching length. Handy for overwriting every other element in one statement:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nletters = list(&quot;python&quot;)\nletters&#x5B;::2] = &quot;PTO&quot;\nprint(letters)\n# &#x5B;&#039;P&#039;, &#039;y&#039;, &#039;T&#039;, &#039;h&#039;, &#039;O&#039;, &#039;n&#039;]\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Strings refuse this because they are immutable. Slice assignment is a list, bytearray, and array trick only.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quick reference<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Where<\/th><th>What the colon does<\/th><th>Example<\/th><\/tr><\/thead><tbody><tr><td>Block headers<\/td><td>Starts an indented block<\/td><td>if x &gt; 0:<\/td><\/tr><tr><td>Square brackets<\/td><td>Slices with start:stop:step<\/td><td>text[1:5:2]<\/td><\/tr><tr><td>Dictionaries<\/td><td>Separates key and value<\/td><td>{&#8220;a&#8221;: 1}<\/td><\/tr><tr><td>Slice assignment<\/td><td>Replaces part of a list in place<\/td><td>nums[1:3] = [99]<\/td><\/tr><tr><td>Annotations<\/td><td>Attaches a type hint<\/td><td>age: int = 30<\/td><\/tr><tr><td>Lambda<\/td><td>Separates args from expression<\/td><td>lambda x: x * 2<\/td><\/tr><tr><td>Walrus (:=)<\/td><td>Assigns inside an expression<\/td><td>if (n := len(d)) &gt; 3:<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1783199709883\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">What does the colon do in Python?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>The colon starts an indented code block after statements like if, for, while, def, and class. It also slices sequences (text[1:5]), separates keys from values in dictionaries, attaches type hints, and separates arguments from the expression in a lambda.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783199709884\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">What does :: (double colon) mean in Python?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>It is a slice with the start and stop left empty, so only the step applies. nums[::2] takes every second element and text[::-1] reverses a string.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783199709885\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">Why am I getting SyntaxError: expected &#8216;:&#8217;?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>A statement that opens a block (if, for, def, class, and similar) is missing its trailing colon. Python 3.10 and newer point at the exact spot where the colon should be. Add it and the error goes away.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>I kept tripping on the colon in Python, where every few lines something refused to run over one character. The colon plays five different roles in the language, each with its own failure mode. Knowing which role is on screen is most of the job. Starting a code block The most common position is at [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":12939,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"class_list":["post-12094","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-examples"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts\/12094","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/comments?post=12094"}],"version-history":[{"count":0,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts\/12094\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/media\/12939"}],"wp:attachment":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/media?parent=12094"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/categories?post=12094"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/tags?post=12094"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}