Title: Python Sentinel Values: Using the New sentinel Built-in – Real Python
Open Graph Title: Python Sentinel Values: Using the New sentinel Built-in – Real Python
Description: Learn how to create a Python sentinel value with the new built-in in Python 3.15 and get readable signatures, type hints, and safe copying and pickling.
Open Graph Description: Learn how to create a Python sentinel value with the new built-in in Python 3.15 and get readable signatures, type hints, and safe copying and pickling.
Mail addresses
?subject=Python article for you&body=Python Sentinel Values: Using the New sentinel Built-in on Real Python
https://realpython.com/python315-sentinel-values/
Opengraph URL: https://realpython.com/python315-sentinel-values/
X: @realpython
Domain: realpython.com
{
"@context": "http://schema.org",
"@type": "Article",
"headline": "Python Sentinel Values: Using the New sentinel Built-in",
"image": {
"@type": "ImageObject",
"url": "https://files.realpython.com/media/Python-3.15-Preview-Sentinel-Values_Watermarked.4141cc1cbc76.jpg",
"width": 1920,
"height": 1080
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://realpython.com/python315-sentinel-values/",
"lastReviewed": "2026-10-12",
"author": {
"@type": "Person",
"name": "Leodanis Pozo Ramos",
"image": "https://realpython.com/cdn-cgi/image/width=862,height=862,fit=crop,gravity=auto,format=auto/https://files.realpython.com/media/Perfil_final1.9f896bc212f6.jpg",
"url": "https://realpython.com/team/lpozoramos/",
"affiliation": {
"@type": "Organization",
"@id": "https://realpython.com/#organization",
"name": "Real Python",
"url": "https://realpython.com",
"logo": "https://realpython.com/static/real-python-logo-square-512.157ae6bf64ed.png"
}
},
"reviewedBy": [
{
"@type": "Person",
"name": "Aldren Santos",
"image": "https://realpython.com/cdn-cgi/image/width=500,height=500,fit=crop,gravity=auto,format=auto/https://files.realpython.com/media/Aldren_Santos_Real_Python.6b0861d8b841.png",
"url": "https://realpython.com/team/asantos/",
"affiliation": {
"@type": "Organization",
"@id": "https://realpython.com/#organization",
"name": "Real Python",
"url": "https://realpython.com",
"logo": "https://realpython.com/static/real-python-logo-square-512.157ae6bf64ed.png"
}
},
{
"@type": "Person",
"name": "Brenda Weleschuk",
"image": "https://realpython.com/cdn-cgi/image/width=320,height=320,fit=crop,gravity=auto,format=auto/https://files.realpython.com/media/IMG_3324_1.50b309355fc1.jpg",
"url": "https://realpython.com/team/bweleschuk/",
"affiliation": {
"@type": "Organization",
"@id": "https://realpython.com/#organization",
"name": "Real Python",
"url": "https://realpython.com",
"logo": "https://realpython.com/static/real-python-logo-square-512.157ae6bf64ed.png"
}
},
{
"@type": "Person",
"name": "Bartosz Zaczy\u0144ski",
"image": "https://realpython.com/cdn-cgi/image/width=1694,height=1694,fit=crop,gravity=auto,format=auto/https://files.realpython.com/media/coders_lab_2109368.259b1599fbee.jpg",
"url": "https://realpython.com/team/bzaczynski/",
"affiliation": {
"@type": "Organization",
"@id": "https://realpython.com/#organization",
"name": "Real Python",
"url": "https://realpython.com",
"logo": "https://realpython.com/static/real-python-logo-square-512.157ae6bf64ed.png"
}
}
]
},
"datePublished": "2026-09-28T14:00:00+00:00",
"dateModified": "2026-10-12T08:15:35.644563+00:00",
"publisher": {
"@type": "Organization",
"@id": "https://realpython.com/#organization",
"name": "Real Python",
"url": "https://realpython.com",
"logo": {
"@type": "ImageObject",
"url": "https://realpython.com/static/real-python-logo-square-512.157ae6bf64ed.png",
"width": 512,
"height": 512
},
"description": "Real Python is a leading provider of online Python education and one of the largest language-specific online communities for software developers. It publishes high-quality learning resources, such as tutorials, books, and courses to an audience of millions of developers, data scientists, and machine learning engineers each month.",
"slogan": "Become a Python Expert",
"email": "info@realpython.com",
"sameAs": [
"https://github.com/realpython",
"https://www.youtube.com/realpython",
"https://twitter.com/realpython",
"https://x.com/realpython",
"https://www.linkedin.com/company/realpython-com/",
"https://www.facebook.com/learnrealpython",
"https://www.instagram.com/realpython",
"https://www.tiktok.com/@realpython.com"
]
},
"author": {
"@type": "Person",
"name": "Leodanis Pozo Ramos",
"image": "https://realpython.com/cdn-cgi/image/width=862,height=862,fit=crop,gravity=auto,format=auto/https://files.realpython.com/media/Perfil_final1.9f896bc212f6.jpg",
"url": "https://realpython.com/team/lpozoramos/",
"affiliation": {
"@type": "Organization",
"@id": "https://realpython.com/#organization",
"name": "Real Python",
"url": "https://realpython.com",
"logo": "https://realpython.com/static/real-python-logo-square-512.157ae6bf64ed.png"
}
},
"description": "Learn how to create a Python sentinel value with the new built-in in Python 3.15 and get readable signatures, type hints, and safe copying and pickling.",
"hasPart": {
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is a sentinel value in Python?",
"acceptedAnswer": {
"@type": "Answer",
"text": "\u003cp\u003eA \u003ca href=\"/ref/computer-science-glossary/sentinel-value/\" class=\"ref-link\"\u003esentinel value\u003c/a\u003e is a value that your code treats as a signal rather than as data. It marks a condition such as \u0026ldquo;no argument was passed,\u0026rdquo; \u0026ldquo;nothing was found,\u0026rdquo; or \u0026ldquo;a loop should stop.\u0026rdquo; What matters is that it stays distinct from every legitimate value your data can take.\u003c/p\u003e"
}
},
{
"@type": "Question",
"name": "How do you create a sentinel value in Python 3.15?",
"acceptedAnswer": {
"@type": "Answer",
"text": "\u003cp\u003eYou can call the \u003ccode\u003esentinel\u003c/code\u003e built-in with a string that names the marker, then assign the result to a variable with that same name. You don\u0026rsquo;t need an import because \u003ccode\u003esentinel\u003c/code\u003e lives in the built-in namespace. An optional \u003ccode\u003erepr\u003c/code\u003e keyword argument lets you display something other than the name.\u003c/p\u003e"
}
},
{
"@type": "Question",
"name": "What problems does Python\u2019s sentinel built-in solve?",
"acceptedAnswer": {
"@type": "Answer",
"text": "\u003cp\u003eThe \u003ccode\u003esentinel\u003c/code\u003e built-in fixes the drawbacks of using \u003ccode\u003eobject()\u003c/code\u003e as a marker. It prints a readable name instead of a memory address, gives you a name you can use in a \u003ca href=\"/ref/glossary/type-hint/\" class=\"ref-link\"\u003etype hint\u003c/a\u003e, and keeps its identity through \u003ccode\u003ecopy()\u003c/code\u003e, \u003ccode\u003edeepcopy()\u003c/code\u003e, and a \u003ccode\u003epickle\u003c/code\u003e round trip. Because every sentinel is a unique object, no real data can equal one by accident.\u003c/p\u003e"
}
},
{
"@type": "Question",
"name": "When should you use a sentinel instead of None?",
"acceptedAnswer": {
"@type": "Answer",
"text": "\u003cp\u003e\u003ccode\u003eNone\u003c/code\u003e is still the right default for most optional parameters. Use a sentinel when \u003ccode\u003eNone\u003c/code\u003e is legitimate data and you need a separate marker for \u0026ldquo;nothing was passed.\u0026rdquo; If you already use an \u003ccode\u003eobject()\u003c/code\u003e marker, switching to a sentinel pays off when the marker appears in a public signature or travels through \u003ccode\u003ecopy\u003c/code\u003e or \u003ccode\u003epickle\u003c/code\u003e. The guide on \u003ca href=\"https://realpython.com/null-in-python/\"\u003eusing null in Python\u003c/a\u003e covers \u003ccode\u003eNone\u003c/code\u003e and its common uses in more depth.\u003c/p\u003e"
}
},
{
"@type": "Question",
"name": "Can you use a sentinel value in a type hint?",
"acceptedAnswer": {
"@type": "Answer",
"text": "\u003cp\u003eYes. A sentinel supports the \u003ccode\u003e|\u003c/code\u003e operator, so you can use its bare name in a union alongside real types, following the precedent set by \u003ccode\u003eNone\u003c/code\u003e years ago. The sentinel stands for a type whose only member is the sentinel object itself.\u003c/p\u003e"
}
}
]
}
}
| author | Real Python |
| theme-color | #18354c |
| color-scheme | light dark |
| twitter:card | summary_large_image |
| twitter:image | https://files.realpython.com/media/Python-3.15-Preview-Sentinel-Values_Watermarked.4141cc1cbc76.jpg |
| og:image | https://files.realpython.com/media/Python-3.15-Preview-Sentinel-Values_Watermarked.4141cc1cbc76.jpg |
| twitter:creator | @realpython |
| og:type | article |
| og:site_name | Real Python |
| apple-mobile-web-app-title | Real Python |
Links:
Viewport: width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover
Robots: max-image-preview:large