CINXE.COM

Scott Robinson - Stack Abuse

<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Scott Robinson - Stack Abuse</title><link rel="canonical" href="https://stackabuse.com/author/scott/"/><meta property="og:url" content="https://stackabuse.com/author/scott/"/><meta name="twitter:url" content="https://stackabuse.com/author/scott/"/><link rel="next" href="https://stackabuse.com/author/scott/page/2/"/><meta property="og:site_name" content="Stack Abuse"/><meta property="og:type" content="profile"/><meta property="og:title" content="Scott Robinson - Stack Abuse"/><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Scott Robinson - Stack Abuse"/><meta name="twitter:site" content="@StackAbuse"/><script type="application/ld+json">{ "@context": "https://schema.org", "@type": "Person", "sameAs": [ "https://twitter.com/ScottWRobinson", "https://github.com/scottwrobinson" ], "name": "Scott Robinson", "url": "https://stackabuse.com/author/scott/", "mainEntityOfPage": { "@type": "WebPage", "@id": "https://stackabuse.com/" }, "image": { "@type": "ImageObject", "url": "https://s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg" } }</script><meta name="next-head-count" content="14"/><link href="//fonts.googleapis.com" rel="preconnect"/><link href="//fonts.gstatic.com" rel="preconnect" crossorigin="true"/><link href="//cdnjs.cloudflare.com" rel="preconnect"/><link href="//s3.stackabuse.com" rel="preconnect"/><link href="//googletagmanager.com" rel="dns-prefetch"/><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="HandheldFriendly" content="True"/><link rel="shortcut icon" sizes="any" href="/assets/images/favicon.ico"/><link rel="shortcut icon" type="image/svg+xml" href="/assets/images/favicon.svg"/><link rel="preload" as="style" href="//fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&amp;display=swap"/><link rel="preload" as="style" href="//fonts.googleapis.com/css?family=Nunito:400,400i,700,700i&amp;display=swap"/><meta name="referrer" content="no-referrer-when-downgrade"/><link rel="alternate" type="application/rss+xml" title="Stack Abuse" href="https://stackabuse.com/rss/"/><link rel="preload" href="/_next/static/css/eaee8aa5ba78cb00.css" as="style"/><link rel="stylesheet" href="/_next/static/css/eaee8aa5ba78cb00.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="/_next/static/chunks/webpack-7c7e5454c0385f08.js" defer=""></script><script src="/_next/static/chunks/framework-1dabaad0401a053e.js" defer=""></script><script src="/_next/static/chunks/main-1b53524783caa372.js" defer=""></script><script src="/_next/static/chunks/pages/_app-85dd70c54f224ed0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-fe043233b220ebfb.js" defer=""></script><script src="/_next/static/chunks/816-dfcc5ef3cff7cadb.js" defer=""></script><script src="/_next/static/chunks/3646-f084444085f451b1.js" defer=""></script><script src="/_next/static/chunks/7329-ea47eb245049fa3f.js" defer=""></script><script src="/_next/static/chunks/2221-aa293f4e0cf5d5c8.js" defer=""></script><script src="/_next/static/chunks/pages/author/%5B...slug%5D-9a0a529e41423fb6.js" defer=""></script><script src="/_next/static/1740324887682/_buildManifest.js" defer=""></script><script src="/_next/static/1740324887682/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div><nav class="bg-white pb-2 border-b shadow"><div class="mx-8 px-2 sm:px-4 lg:px-8"><div class="flex justify-between h-16"><div class="flex items-center px-2 lg:px-0"><a href="/"><div class="flex-shrink-0 flex items-center"><svg class="h-6 w-full" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 494.36 63"><defs><style>.cls-1{fill:#363636}.cls-2{fill:#f29c80}.cls-3{fill:#b34a28}.cls-4{fill:#f16335}</style></defs><title>SA Logotype</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M104.94,27.65q-3.15-1.44-4.65-2.16c-1-.48-2.17-1.12-3.49-1.91A10.35,10.35,0,0,1,94,21.35a3.58,3.58,0,0,1-.82-2.27,4.79,4.79,0,0,1,1.74-3.89,7.6,7.6,0,0,1,5-1.44,16,16,0,0,1,5.61,1.15,27.13,27.13,0,0,1,4.1,1.84c.73.46,1.3.83,1.71,1.12l5.2-10.8-2-1.44A28.63,28.63,0,0,0,108,2.84a29.37,29.37,0,0,0-9-1.4A18.5,18.5,0,0,0,86.2,6.52a16.81,16.81,0,0,0-5.61,13.06,14.64,14.64,0,0,0,2.81,8.61,21.59,21.59,0,0,0,7.93,6.66c.82.43,2.09,1.07,3.8,1.91s2.94,1.46,3.69,1.87a27.75,27.75,0,0,1,2.6,1.65,6.9,6.9,0,0,1,2,2.09,4.57,4.57,0,0,1,.58,2.27q0,5.84-8.14,5.83a14.52,14.52,0,0,1-6.46-1.87,35.41,35.41,0,0,1-5.1-3c-.95-.74-1.71-1.35-2.25-1.83L75.67,55.15l.89.79a19.23,19.23,0,0,0,2.8,2c1.28.77,2.71,1.55,4.31,2.34a26.52,26.52,0,0,0,6,2,33.14,33.14,0,0,0,7.25.79,29.54,29.54,0,0,0,8-1,21.94,21.94,0,0,0,6.74-3.21,14.53,14.53,0,0,0,4.79-6,21.36,21.36,0,0,0,1.74-8.93,13.77,13.77,0,0,0-3.86-9.54A28,28,0,0,0,104.94,27.65Z"></path><path class="cls-1" d="M143.66,50.69a5.8,5.8,0,0,1-1.17.57,3.84,3.84,0,0,1-1.43.29q-2.75,0-2.74-5.11V34.7h7.39V25h-7.39V11.23H126.21V25h-5.06V34.7h5.06V48.89a22.21,22.21,0,0,0,.55,5,16,16,0,0,0,1.81,4.47,9,9,0,0,0,3.73,3.38A12.76,12.76,0,0,0,138.18,63a17.23,17.23,0,0,0,8.9-2.3l-3-10.3Z"></path><path class="cls-1" d="M177.44,28.51A15.41,15.41,0,0,0,166,23.9a15.82,15.82,0,0,0-12.51,5.69,20.47,20.47,0,0,0-4.93,13.9,20.33,20.33,0,0,0,4.93,13.86A15.85,15.85,0,0,0,166,63a14.47,14.47,0,0,0,11.49-5.26h.14v4.18h12V25H177.44Zm-2,21.17a7.68,7.68,0,0,1-5.85,2.45,7.79,7.79,0,0,1-6-2.41,8.74,8.74,0,0,1-2.26-6.23,8.69,8.69,0,0,1,2.36-6.27,8.15,8.15,0,0,1,11.63,0,8.69,8.69,0,0,1,2.36,6.27A8.74,8.74,0,0,1,175.43,49.68Z"></path><path class="cls-1" d="M216.43,34.34a9.4,9.4,0,0,1,5.88,1.73l4.11-8.71-1.16-.86a15,15,0,0,0-4.18-1.73,22.57,22.57,0,0,0-6.43-.87,18.72,18.72,0,0,0-13.57,5.8,18.81,18.81,0,0,0-5.85,13.86,18.52,18.52,0,0,0,5.85,13.72A18.83,18.83,0,0,0,214.65,63a22,22,0,0,0,6.54-.94,20,20,0,0,0,3.89-1.47c.57-.36,1-.66,1.34-.9l-4.11-8.86-.61.43a9.12,9.12,0,0,1-2.16.87,10.87,10.87,0,0,1-3.11.43,7.75,7.75,0,0,1-5.88-2.66,9.22,9.22,0,0,1-2.46-6.48A9.1,9.1,0,0,1,210.55,37,7.72,7.72,0,0,1,216.43,34.34Z"></path><polygon class="cls-1" points="271.43 24.98 255.69 24.98 243.45 37.87 243.45 0 231.34 0 231.34 61.92 243.45 61.92 243.45 47.16 257.47 61.92 273.07 61.92 254.74 42.62 271.43 24.98"></polygon><polygon class="cls-1" points="296.96 2.52 274.18 61.92 288 61.92 302.84 20.88 302.98 20.88 317.82 61.92 331.63 61.92 308.86 2.52 296.96 2.52"></polygon><path class="cls-1" d="M357.42,23.9a15.41,15.41,0,0,0-11.49,4.61V0H333.82V61.92h12V57.74h.14A14.47,14.47,0,0,0,357.42,63a15.88,15.88,0,0,0,12.52-5.65,20.38,20.38,0,0,0,4.92-13.86,20.51,20.51,0,0,0-4.92-13.9A15.86,15.86,0,0,0,357.42,23.9Zm2.33,25.82a7.8,7.8,0,0,1-5.95,2.41A7.65,7.65,0,0,1,348,49.68a8.69,8.69,0,0,1-2.29-6.19A8.64,8.64,0,0,1,348,37.22a7.7,7.7,0,0,1,5.78-2.44,7.78,7.78,0,0,1,5.84,2.44A8.64,8.64,0,0,1,362,43.49,8.78,8.78,0,0,1,359.75,49.72Z"></path><path class="cls-1" d="M405.78,42.55c0,3.65-.53,6.24-1.57,7.78s-2.83,2.3-5.34,2.3-4.29-.77-5.33-2.3S392,46.2,392,42.55V25h-12.1V45.65q0,9.21,4.54,13.28T398.87,63q9.92,0,14.47-4.07t4.55-13.28V25H405.78Z"></path><path class="cls-1" d="M449.11,42.19A20.21,20.21,0,0,0,445.79,40a23.31,23.31,0,0,0-3.69-1.44,8.7,8.7,0,0,1-1-.29c-.44-.14-.74-.25-.93-.32l-.82-.32-.78-.33-.65-.32a2.25,2.25,0,0,1-.58-.4c-.12-.12-.24-.26-.38-.43a1.25,1.25,0,0,1-.27-.54,2.25,2.25,0,0,1-.07-.58,1.82,1.82,0,0,1,.85-1.76,6.53,6.53,0,0,1,2.91-.47,16,16,0,0,1,7.8,2.31l4-8.36-1.43-.72a22.21,22.21,0,0,0-4.38-1.44,24.9,24.9,0,0,0-5.95-.72q-7,0-11.18,3.14a10.32,10.32,0,0,0-4.14,8.74,9.07,9.07,0,0,0,1.91,6,18.12,18.12,0,0,0,5.2,4.06,28.82,28.82,0,0,0,3.59,1.59A14.8,14.8,0,0,1,439,49a2.2,2.2,0,0,1,1,1.9c0,1.78-1.26,2.67-3.76,2.67a9.22,9.22,0,0,1-4-1.19A23.33,23.33,0,0,1,429,50.51c-.6-.46-1.08-.85-1.44-1.19L422.61,58l1.5,1.3A17.63,17.63,0,0,0,429,61.78,21,21,0,0,0,436.15,63q16.62,0,16.62-12.6a11.23,11.23,0,0,0-1-4.75A9.24,9.24,0,0,0,449.11,42.19Z"></path><path class="cls-1" d="M494.36,43.49q0-9.43-5.24-14.51T475.55,23.9a18.46,18.46,0,0,0-13.62,5.76,19,19,0,0,0-5.67,13.83,18.9,18.9,0,0,0,5.67,13.79A18.54,18.54,0,0,0,475.55,63q12.72,0,18.19-9.65L485,48.74a13.63,13.63,0,0,1-3.9,3.28,10.84,10.84,0,0,1-4.65.83,8.3,8.3,0,0,1-5.2-1.87q-2.4-1.87-2.4-5.76h25.45A14.91,14.91,0,0,0,494.36,43.49Zm-25.17-5.33a6,6,0,0,1,1.91-4.32,6.77,6.77,0,0,1,4.79-1.66,6.51,6.51,0,0,1,4.48,1.55,7,7,0,0,1,2.15,4.43Z"></path><polygon class="cls-2" points="66.05 19.08 73.15 1.3 57.25 1.3 50.16 19.08 66.05 19.08"></polygon><polygon class="cls-3" points="40.21 43.99 32.99 62.06 48.88 62.06 56.1 43.99 40.21 43.99"></polygon><polygon class="cls-4" points="57.69 40.01 64.46 23.05 48.57 23.05 41.8 40.01 57.69 40.01"></polygon><polygon class="cls-2" points="33.06 19.08 40.16 1.3 24.27 1.3 17.17 19.08 33.06 19.08"></polygon><polygon class="cls-3" points="7.22 43.99 0 62.06 15.89 62.06 23.11 43.99 7.22 43.99"></polygon><polygon class="cls-4" points="24.7 40.01 31.47 23.05 15.58 23.05 8.81 40.01 24.7 40.01"></polygon></g></g></svg></div></a><div class="hidden lg:block lg:ml-6"><div class="hidden lg:ml-6 lg:flex"><a href="/tools/" class="mr-8 inline-flex items-center px-1 pt-1 border-b-2 border-blue-400 text-sm font-medium leading-10 text-gray-500 hover:text-gray-700 focus:outline-none focus:text-gray-700 transition duration-150 ease-in-out">Tools</a><div class="px-1 pt-1 border-b-2 border-green-400 focus:border-gray-300 transition duration-150 ease-in-out"><div class="relative" data-headlessui-state=""><button class="text-gray-500 group rounded-md inline-flex items-center focus:outline-none text-sm font-medium leading-10 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700" type="button" aria-expanded="false" data-headlessui-state=""><span>Learn</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="text-gray-400 ml-2 h-5 w-5 group-hover:text-gray-500"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg></button></div><div hidden="" style="position:fixed;top:1px;left:1px;width:1px;height:0;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0;display:none"></div></div><a href="/about/" class="ml-8 inline-flex items-center px-1 pt-1 border-b-2 border-red-400 text-sm font-medium leading-10 text-gray-500 hover:text-gray-700 focus:outline-none focus:text-gray-700 transition duration-150 ease-in-out">About</a></div></div></div><div class="hidden mt-4 md:flex md:flex-1 md:items-center md:justify-center md:px-2 lg:ml-6 lg:justify-end"><div class="relative w-1/2 text-gray-400 transition duration-200 focus-within:text-gray-600"><div class="absolute inset-y-0 left-0 flex items-center pointer-events-none" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="h-5 w-5 ml-2"><path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"></path></svg></div><input id="search-field" class="block w-full h-full pl-10 pr-3 py-3 text-sm border-gray-300 text-gray-900 placeholder-gray-500 rounded transition duration-200 focus:outline-none focus:ring-0 focus:border-gray-400" placeholder="Search" type="text"/></div><div class="hidden ml-6 md:flex items-center"><button class="whitespace-nowrap text-base font-medium text-gray-500 hover:text-gray-900">Sign in</button><button class="ml-6 whitespace-nowrap inline-flex items-center justify-center px-4 py-2 border border-transparent rounded-md shadow-sm text-base font-medium text-white bg-orange-500 hover:bg-orange-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500">Sign up</button></div></div><div class="flex items-center lg:hidden"><button class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out" aria-label="Main menu" aria-expanded="false"><svg class="block h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg><svg class="hidden h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg></button></div></div></div><div class="hidden lg:hidden"><div class="pt-2 pb-3"><a href="/tag/python" class="mt-1 block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out">Python</a><a href="/tag/javascript" class="mt-1 block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out">JavaScript</a><a href="/tag/java" class="mt-1 block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out">Java</a></div></div></nav><main><div class="flex items-stretch min-h-screen"><div class="mx-auto max-w-none lg:max-w-screen-xl px-4 sm:px-6 pb-6"><div class="grid grid-cols-12 sm:gap-x-2 lg:gap-x-3 pt-6"><div class="col-span-12 lg:col-span-3"><img class="object-cover shadow-lg rounded-lg h-60 w-60" src="//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg" alt="Scott Robinson"/><div class="inline-flex py-4"><a href="https://twitter.com/ScottWRobinson"><svg class="h-6 w-6 ml-2 text-gray-500 hover:text-twitter" fill="currentColor" viewBox="0 0 24 24"><path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84"></path></svg></a><a href="https://github.com/scottwrobinson"><svg class="h-6 w-6 ml-2 text-gray-500 hover:text-gray-900" fill="currentColor" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path></svg></a></div></div><div class="col-span-12 lg:col-span-7"><h1 class="my-1 text-3xl tracking-tight leading-10 font-extrabold text-gray-900 sm:leading-none sm:text-6xl lg:text-4xl xl:text-5xl">Scott Robinson</h1><div class="">Articles: <!-- -->524</div><div class="">Joined: <!-- -->May 11, 2015</div><div class="my-4"></div></div><div class="lg:col-span-1"></div></div><div class="mt-8 border-t border-gray-200"><h2 class="my-6 text-xl tracking-tight leading-10 font-extrabold text-gray-700 sm:leading-none sm:text-4xl lg:text-2xl xl:text-3xl">Recently published</h2><div class="grid gap-5 lg:grid-cols-3"><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/securing-your-email-sending-with-python-authentication-and-encryption/"><img class="h-48 w-full object-cover" src="/assets/images/logo-python.png" alt=""/></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/securing-your-email-sending-with-python-authentication-and-encryption/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Securing Your Email Sending With Python: Authentication and Encryption</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">Email encryption and authentication are modern security techniques that you can use to protect your emails and their content from unauthorized access. Everyone, from individuals to business owners, uses emails for official communication, which may contain sensitive information. Therefore, securing emails is important, especially when cyberattacks like phishing, smishing, etc....</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/ivan/"><img class="h-10 w-10 rounded-full" src="https://s3.amazonaws.com/s3.stackabuse.com/media/users/b9227b402289ab251e04427e15e2d4f6.jpg" alt="Ivan Djuric"/></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/ivan/" class="hover:underline">Ivan Djuric</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2024-09-19">Sep 19, 2024</time><span class="mx-1">·</span><span>19<!-- --> min read</span></div></div></div></div></div></div><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/using-proxies-in-web-scraping-all-you-need-to-know/"><div class="lazyload-wrapper "><div style="height:12rem" class="lazyload-placeholder"></div></div></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/using-proxies-in-web-scraping-all-you-need-to-know/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Using Proxies in Web Scraping – All You Need to Know</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">Web scraping typically refers to an automated process of collecting data from websites. On a high level, you&#x27;re essentially making a bot that visits a website, detects the data you&#x27;re interested in, and then stores it into some appropriate data structure, so you can easily analyze and access it later....</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/leonardo/"><div class="lazyload-wrapper "><div style="height:2.5rem" class="lazyload-placeholder"></div></div></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/leonardo/" class="hover:underline">Leonardo Rodriguez</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2024-09-12">Sep 12, 2024</time><span class="mx-1">·</span><span>24<!-- --> min read</span></div></div></div></div></div></div><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/building-custom-email-templates-with-html-and-css-in-python/"><div class="lazyload-wrapper "><div style="height:12rem" class="lazyload-placeholder"></div></div></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/building-custom-email-templates-with-html-and-css-in-python/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Building Custom Email Templates with HTML and CSS in Python</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">An HTML email utilizes HTML code for presentation. Its design is heavy and looks like a modern web page, rich with visual elements like images, videos, etc., to emphasize different parts of an email&#x27;s content. Building email templates tailored to your brand is useful for various email marketing purposes such...</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/ivan/"><div class="lazyload-wrapper "><div style="height:2.5rem" class="lazyload-placeholder"></div></div></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/ivan/" class="hover:underline">Ivan Djuric</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2024-08-20">Aug 20, 2024</time><span class="mx-1">·</span><span>19<!-- --> min read</span></div></div></div></div></div></div><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/gracefully-handling-third-party-api-failures/"><div class="lazyload-wrapper "><div style="height:12rem" class="lazyload-placeholder"></div></div></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/gracefully-handling-third-party-api-failures/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Gracefully Handling Third Party API Failures</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">Software isn&#x27;t what it used to be. That&#x27;s not necessarily a bad thing, but it does come with its own set of challenges. In the past, if you wanted to build a feature, you&#x27;d have to build it from scratch, without AI 😱 Fast forward from the dark ages of just...</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/scott/"><div class="lazyload-wrapper "><div style="height:2.5rem" class="lazyload-placeholder"></div></div></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/scott/" class="hover:underline">Scott Robinson</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2024-06-13">Jun 13, 2024</time><span class="mx-1">·</span><span>12<!-- --> min read</span></div></div></div></div></div></div><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/simplify-regular-expressions-with-regexpbuilderjs/"><div class="lazyload-wrapper "><div style="height:12rem" class="lazyload-placeholder"></div></div></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/simplify-regular-expressions-with-regexpbuilderjs/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Simplify Regular Expressions with RegExpBuilderJS</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">Regular expressions are on of the most powerful tools in a developer&#x27;s toolkit. But let&#x27;s be honest, regex kind of sucks to write. Not only is it hard to write, but it&#x27;s also hard to read and debug too. So how can we make it easier to use? In its...</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/scott/"><div class="lazyload-wrapper "><div style="height:2.5rem" class="lazyload-placeholder"></div></div></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/scott/" class="hover:underline">Scott Robinson</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2024-06-06">Jun 06, 2024</time><span class="mx-1">·</span><span>5<!-- --> min read</span></div></div></div></div></div></div><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/guide-to-strings-in-python/"><div class="lazyload-wrapper "><div style="height:12rem" class="lazyload-placeholder"></div></div></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/guide-to-strings-in-python/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Guide to Strings in Python</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">A string in Python is a sequence of characters. These characters can be letters, numbers, symbols, or whitespace, and they are enclosed within quotes. Python supports both single (&#x27; &#x27;) and double (&amp;quot; &amp;quot;) quotes to define a string, providing flexibility based on the coder&#x27;s preference or specific requirements of...</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/stamd/"><div class="lazyload-wrapper "><div style="height:2.5rem" class="lazyload-placeholder"></div></div></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/stamd/" class="hover:underline">Dimitrije Stamenic</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2024-01-25">Jan 25, 2024</time><span class="mx-1">·</span><span>111<!-- --> min read</span></div></div></div></div></div></div><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/behind-the-scenes-never-trust-user-input/"><div class="lazyload-wrapper "><div style="height:12rem" class="lazyload-placeholder"></div></div></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/behind-the-scenes-never-trust-user-input/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Behind the Scenes: Never Trust User Input</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">This article is the first in a series of posts I&#x27;m writing about running various SaaS products and websites for the last 8 years. I&#x27;ll be sharing some of the issues I&#x27;ve dealt with, lessons I&#x27;ve learned, mistakes I&#x27;ve made, and maybe a few things that went right. Let me...</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/scott/"><div class="lazyload-wrapper "><div style="height:2.5rem" class="lazyload-placeholder"></div></div></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/scott/" class="hover:underline">Scott Robinson</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2023-12-14">Dec 14, 2023</time><span class="mx-1">·</span><span>8<!-- --> min read</span></div></div></div></div></div></div><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/guide-to-heaps-in-python/"><div class="lazyload-wrapper "><div style="height:12rem" class="lazyload-placeholder"></div></div></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/guide-to-heaps-in-python/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Guide to Heaps in Python</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">In this guide, we&#x27;ll embark on a journey to understand heaps from the ground up. We&#x27;ll start by demystifying what heaps are and their inherent properties. From there, we&#x27;ll dive into Python&#x27;s own implementation of heaps, the heapq module, and explore its rich set of functionalities. So, if you&#x27;ve ever...</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/stamd/"><div class="lazyload-wrapper "><div style="height:2.5rem" class="lazyload-placeholder"></div></div></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/stamd/" class="hover:underline">Dimitrije Stamenic</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2023-11-15">Nov 15, 2023</time><span class="mx-1">·</span><span>19<!-- --> min read</span></div></div></div></div></div></div><div><div class="flex flex-col rounded-lg shadow-lg overflow-hidden"><div class="flex-shrink-0"><a href="/hash-tables-in-python/"><div class="lazyload-wrapper "><div style="height:12rem" class="lazyload-placeholder"></div></div></a></div><div class="flex-1 bg-white p-6 flex flex-col justify-between"><div class="flex-1"><p class="text-sm leading-5 font-medium text-primary">Article</p><a class="block hover:no-underline" href="/hash-tables-in-python/"><h3 class="mt-2 text-xl leading-7 font-semibold text-gray-900 hover:underline">Guide to Hash Tables in Python</h3><p class="mt-3 text-base leading-6 text-gray-500 break-words">While Python doesn&#x27;t have a built-in data structure explicitly called a &amp;quot;hash table&amp;quot;, it provides the dictionary, which is a form of a hash table. Python dictionaries are unordered collections of key-value pairs, where the key is unique and holds a corresponding value. Thanks to a process known...</p></a></div><div class="mt-6 flex items-center"><div class="flex-shrink-0"><a href="/author/stamd/"><div class="lazyload-wrapper "><div style="height:2.5rem" class="lazyload-placeholder"></div></div></a></div><div class="ml-3"><p class="text-sm leading-5 font-medium text-gray-900"><a href="/author/stamd/" class="hover:underline">Dimitrije Stamenic</a></p><div class="flex text-sm leading-5 text-gray-500"><time dateTime="2023-11-09">Nov 09, 2023</time><span class="mx-1">·</span><span>31<!-- --> min read</span></div></div></div></div></div></div></div><div class="mt-8 border-t border-gray-200 px-4 flex items-center justify-between sm:px-0"><div class="-mt-px w-0 flex-1 flex justify-end"><a class="border-t-2 border-transparent pt-4 pl-1 inline-flex items-center text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300" href="/author/scott/page/2/">Next<svg class="ml-3 h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg></a></div></div></div></div></div></main><div class="bg-white border-t border-gray-300"><div class="max-w-screen-xl mx-auto pt-12 pb-6 px-4 sm:px-6 md:flex md:items-center md:justify-between lg:px-8"><div class="flex justify-center md:order-2"><a href="https://twitter.com/stackabuse" target="_blank" rel="noreferrer noopener" class="text-gray-500 hover:text-twitter"><span class="sr-only">Twitter</span><svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24"><path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84"></path></svg></a><a href="https://github.com/stackabuse" target="_blank" rel="noreferrer noopener" class="ml-6 text-gray-500 hover:text-github"><span class="sr-only">GitHub</span><svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path></svg></a><a href="https://www.facebook.com/stackabuse" target="_blank" rel="noreferrer noopener" class="ml-6 text-gray-500 hover:text-facebook"><span class="sr-only">Facebook</span><svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z" clip-rule="evenodd"></path></svg></a></div><div class="mt-8 md:mt-0 md:order-1"><p class="text-center text-base leading-6 text-gray-500">© 2013-<!-- -->2025<!-- --> Stack Abuse. All rights reserved.</p><div class="text-sm"><a href="/about" class="pr-4 text-gray-500 border-r-2 border-grey-400 hover:no-underline hover:text-gray-600">About</a><a href="/disclosure" class="px-4 text-gray-500 border-r-2 border-grey-400 hover:no-underline hover:text-gray-600">Disclosure</a><a href="/privacy-policy" class="px-4 text-gray-500 border-r-2 border-grey-400 hover:no-underline hover:text-gray-600">Privacy</a><a href="/terms-of-service" class="pl-4 text-gray-500 hover:no-underline hover:text-gray-600">Terms</a><div id="ccpa" style="display:none;cursor:pointer">Do not share my Personal Information.</div></div></div></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"author":{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","contents":[{"id":2134,"title":"Securing Your Email Sending With Python: Authentication and Encryption","slug":"securing-your-email-sending-with-python-authentication-and-encryption","body_html":"\u003cp\u003eEmail encryption and authentication are modern security techniques that you can use to protect your emails and their content from unauthorized access.\u003c/p\u003e\n\u003cp\u003eEveryone, from individuals to business owners, uses emails for official communication, which may contain sensitive information. Therefore, securing emails is important, especially when cyberattacks like phishing, smishing, etc. are soaring high.\u003c/p\u003e\n\u003cp\u003eIn this article, I'll discuss how to send emails in Python securely using \u003cstrong\u003eemail encryption\u003c/strong\u003e and authentication.\u003c/p\u003e\n\u003ch2 id=\"settingupyourpythonenvironment\"\u003eSetting Up Your Python Environment\u003c/h2\u003e\n\u003cp\u003eBefore you start creating the code for sending emails, set up your Python environment first with the configurations and libraries you'll need.\u003c/p\u003e\n\u003cp\u003eYou can send emails in Python using:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eSimple Mail Transfer Protocol (SMTP):\u003c/strong\u003e This application-level protocol simplifies the process since Python offers an in-built library or module (\u003ccode\u003esmtplib\u003c/code\u003e) for sending emails. It's suitable for businesses of all sizes as well as individuals to automate \u003cstrong\u003esecure email sending in Python\u003c/strong\u003e. We're using the Gmail \u003cstrong\u003eSMTP service\u003c/strong\u003e in this article.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAn email API\u003c/strong\u003e: You can leverage a third-party API like Mailtrap Python SDK, SendGrid, Gmail API, etc., to dispatch emails in Python. This method offers more features and high email delivery speeds, although it requires some investment.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIn this tutorial, we're opting for the first choice - sending emails in Python using SMTP, facilitated by the \u003ccode\u003esmtplib\u003c/code\u003e library. This library uses the RFC 821 protocol and interacts with SMTP and mail servers to streamline email dispatch from your applications. Additionally, you should install packages to enable \u003cstrong\u003ePython email encryption\u003c/strong\u003e, authentication, and formatting.\u003c/p\u003e\n\u003ch3 id=\"step1installpython\"\u003eStep 1: Install Python\u003c/h3\u003e\n\u003cp\u003eInstall the Python programming language on your computer (Windows, macOS, Linux, etc.). You can visit the \u003ca href=\"https://www.python.org/downloads/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eofficial Python website\u003c/a\u003e and download and install it from there.\u003c/p\u003e\n\u003cp\u003eIf you've already installed it, run this code to verify it:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003epython --version\u003c/code\u003e\u003c/p\u003e\n\u003ch3 id=\"step2installnecessarymodulesandlibraries\"\u003eStep 2: Install Necessary Modules and Libraries\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esmtplib\u003c/code\u003e: This handles SMTP communications. Use the code below to import 'smtplib' and connect with your email server:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eemail\u003c/code\u003e module: This provides classes (Subject, To, From, etc.) to construct and parse emails. It also facilitates email encoding and decoding with Multipurpose Internet Mail Extensions (MIME).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eMIMEText\u003c/code\u003e: It's used for formatting your emails and supports sending emails with text and attachments like images, videos, etc. Import this using the code below:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e MIMEText\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eMIMEMultipart: Use this library to add attachments and text sections separately in your email.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e MIMEMultipart\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003essl\u003c/code\u003e: It provides Secure Sockets Layer (SSL) encryption.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"step3createagmailaccount\"\u003eStep 3: Create a Gmail Account\u003c/h3\u003e\n\u003cp\u003eTo send emails using the Gmail \u003ca href=\"https://mailtrap.io/smtp-service/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eSMTP email service\u003c/a\u003e, I recommend creating a test account to develop the code. Delete the account once you've tested the code.\u003c/p\u003e\n\u003cp\u003eThe reason is, you'll need to modify the security settings of your Gmail account to enable access from the Python code for sending emails. This might expose the login details, compromising security. In addition, it will flood your account with too many test emails.\u003c/p\u003e\n\u003cp\u003eSo, instead of using your own Gmail account, create a new one for creating and testing the code. Here's how to do this:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eCreate a fresh Gmail account\u003c/li\u003e\n\u003cli\u003eSet up your app password:\u003cbr\u003e\n\u003ccode\u003eGoogle Account \u0026gt; Security \u0026gt; Turn on 2-Step Verification \u0026gt; Security \u0026gt; Set up an App Password\u003c/code\u003e\u003cbr\u003e\nNext, define a name for the app password and click on \u0026quot;Generate\u0026quot;. You'll get a 16-digit password after following some instructions on the screen. Store the password safely.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eUse this password while sending emails in Python. Here, we're using Gmail SMTP, but if you want to use another mail service provider, follow the same process. Alternatively, contact your company's IT team to seek support in accessing your SMTP server.\u003c/p\u003e\n\u003ch2 id=\"emailauthenticationwithpython\"\u003eEmail Authentication With Python\u003c/h2\u003e\n\u003cp\u003eEmail authentication is a security mechanism that verifies the sender's identity, ensuring the emails from a domain are legitimate. If you have no email authentication mechanism in place, your emails might land in spam folders, or malicious actors can spoof or intercept them. This could affect your email delivery rates and the sender's reputation.\u003c/p\u003e\n\u003cp\u003eThis is the reason you must enable \u003cstrong\u003ePython email authentication\u003c/strong\u003e mechanisms and protocols, such as:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eSMTP authentication\u003c/strong\u003e: If you're sending emails using an SMTP server like Gmail SMTP, you can use this method of authentication. It verifies the sender's authenticity when sending emails via a specific mail server.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eSPF\u003c/strong\u003e: Stands for Sender Policy Framework and checks whether the IP address of the sending server is among\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eDKIM\u003c/strong\u003e: Stands for DomainKeys Identified Mail and is used to add a digital signature to emails to ensure no one can alter the email's content while it's in transmission. The receiver's server will then verify the digital signature. Thus, all your emails and their content stay secure and unaltered.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eDMARC\u003c/strong\u003e: Stands for Domain-based Message Authentication, Reporting, and Conformance. DMARC instructs mail servers what to do if an email fails authentication. In addition, it provides reports upon detecting any suspicious activities on your domain.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"howtoimplementemailauthenticationinpython\"\u003eHow to Implement Email Authentication in Python\u003c/h3\u003e\n\u003cp\u003eTo authenticate your email in Python using SMTP, the \u003ccode\u003esmtplib\u003c/code\u003e library is useful. Here's how \u003cstrong\u003ePython SMTP security\u003c/strong\u003e works:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\nserver = smtplib.SMTP(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;smtp.domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e587\u003c/span\u003e)\nserver.starttls() \u003cspan class=\"hljs-comment\"\u003e# Start TLS for secure connection\u003c/span\u003e\nserver.login(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_email@domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_password\u0026#x27;\u003c/span\u003e)\n\nmessage = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Subject: Test Email.\u0026quot;\u003c/span\u003e\nserver.sendmail(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_email@domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;receiver@domain2.com\u0026#x27;\u003c/span\u003e, message)\n\nserver.quit()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eImplementing email authentication will add an additional layer of security to your emails and protect them from attackers or from being marked as spam.\u003c/p\u003e\n\u003ch2 id=\"encryptingemailswithpython\"\u003eEncrypting Emails With Python\u003c/h2\u003e\n\u003cp\u003eEncrypting emails enables you to protect your email's content so that only authorized senders and receivers can access or view the content. \u003cstrong\u003eEncrypting emails with Python\u003c/strong\u003e is done using encryption techniques to encode the email message and transform it into a secure and unreadable format (also known as ciphertext).\u003c/p\u003e\n\u003cp\u003eThis way, email encryption secures the message from unauthorized access or attackers even if they intercept the email.\u003c/p\u003e\n\u003cp\u003eHere are different \u003ca href=\"https://mailtrap.io/blog/email-encryption/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003etypes of email encryption\u003c/a\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eSSL:\u003c/strong\u003e This stands for Secure Sockets Layer, one of the most popular and widely used encryption protocols. SSL ensures email confidentiality by encrypting data transmitted between the mail server and the client.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eTLS:\u003c/strong\u003e This stands for Transport Layer Security and is a common email encryption protocol today. Many consider it a great alternative to SSL. It encrypts the connection between an email client and the mail server to prevent anyone from intercepting the email during its transmission.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eE2EE:\u003c/strong\u003e This stands for end-to-end encryption, ensuring only the intended recipient with valid credentials can decrypt the email content and read it. It aims to prevent email interception and secure the message.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"howtoimplementemailencryptioninpython\"\u003eHow to Implement Email Encryption in Python\u003c/h3\u003e\n\u003cp\u003eIf your mail server requires SSL encryption, here's \u003ca href=\"https://stackabuse.com/how-to-send-an-email-with-boto-and-ses/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003ehow to send an email in Python\u003c/a\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e ssl\n\ncontext = ssl.create_default_context()\n\nserver = smtplib.SMTP_SSL(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;smtp.domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e465\u003c/span\u003e, context=context) \u003cspan class=\"hljs-comment\"\u003e# This is for SSL connections, requiring port number 465\u003c/span\u003e\nserver.login(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_email@domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_password\u0026#x27;\u003c/span\u003e)\n\nmessage = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Subject: SSL Encrypted Email.\u0026quot;\u003c/span\u003e\nserver.sendmail(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_email@domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;receiver@domain2.com\u0026#x27;\u003c/span\u003e, message)\n\nserver.quit()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eFor TLS connections\u003c/strong\u003e, you'll need the \u003ccode\u003esmtplib\u003c/code\u003e library:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\nserver = smtplib.SMTP(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;smtp.domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e587\u003c/span\u003e) \u003cspan class=\"hljs-comment\"\u003e# TLS requires 587 port number\u003c/span\u003e\nserver.starttls() \u003cspan class=\"hljs-comment\"\u003e# Start TLS encryption\u003c/span\u003e\nserver.login(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_email@domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_password\u0026#x27;\u003c/span\u003e)\n\nmessage = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Subject: TLS Encrypted Email.\u0026quot;\u003c/span\u003e\nserver.sendmail(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;my_email@domain1.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;receiver@domain2.com\u0026#x27;\u003c/span\u003e, message)\n\nserver.quit()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFor end-to-end encryption, you'll need more advanced libraries or tools such as GnuPG, OpenSSL, Signal Protocol, and more.\u003c/p\u003e\n\u003ch2 id=\"combiningauthenticationandencryption\"\u003eCombining Authentication and Encryption\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eEmail Security with Python\u003c/strong\u003e requires both encryption and authentication. This ensures that mail servers find the email legitimate and it stays safe from cyber attackers and unauthorized access during transmission. For email encryption, you can use either SSL or TLS and combine it with SMTP authentication to establish a robust email connection.\u003c/p\u003e\n\u003cp\u003eNow that you know how to enable email encryption and authentication in your emails, let's examine some complete code examples to understand how you can send secure emails in Python using Gmail SMTP and email encryption (SSL).\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eCode Examples\u003c/strong\u003e\u003c/p\u003e\n\u003ch3 id=\"1sendingaplaintextemail\"\u003e1. Sending a Plain Text Email\u003c/h3\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e email.mime.text \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e MIMEText\n\nsubject = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Plain Text Email\u0026quot;\u003c/span\u003e\nbody = \u003cspan class=\"hljs-string\"\u003e\u0026quot;This is a plain text email using Gmail SMTP and SSL.\u0026quot;\u003c/span\u003e\nsender = \u003cspan class=\"hljs-string\"\u003e\u0026quot;sender1@gmail.com\u0026quot;\u003c/span\u003e\nreceivers = [\u003cspan class=\"hljs-string\"\u003e\u0026quot;receiver1@gmail.com\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;receiver2@gmail.com\u0026quot;\u003c/span\u003e]\npassword = \u003cspan class=\"hljs-string\"\u003e\u0026quot;my_password\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003esend_email\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003esubject, body, sender, receivers, password\u003c/span\u003e):\u003c/span\u003e\n msg = MIMEText(body)\n\n msg[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Subject\u0026#x27;\u003c/span\u003e] = subject\n msg[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;From\u0026#x27;\u003c/span\u003e] = sender\n msg[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;To\u0026#x27;\u003c/span\u003e] = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;, \u0026#x27;\u003c/span\u003e.join(receivers)\n\n\u003cspan class=\"hljs-keyword\"\u003ewith\u003c/span\u003e smtplib.SMTP_SSL(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;smtp.gmail.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e465\u003c/span\u003e) \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e smtp_server:\n smtp_server.login(sender, password)\n smtp_server.sendmail(sender, receivers, msg.as_string()) \n\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The plain text email is sent successfully!\u0026quot;\u003c/span\u003e)\n\nsend_email(subject, body, sender, receivers, password)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eExplanation\u003c/strong\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003esender\u003c/code\u003e: This contains the sender's address.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ereceivers\u003c/code\u003e: This contains email addresses of receiver 1 and receiver 2.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003emsg\u003c/code\u003e: This is the content of the email.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esendmail()\u003c/code\u003e: This is the SMTP object's instance method. It takes three parameters - sender, receiver, and msg and sends the message.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ewith\u003c/code\u003e: This is a context manager that is used to properly close an SMTP connection once an email is sent.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMIMEText\u003c/code\u003e: This holds only plain text.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"2sendinganemailwithattachments\"\u003e2. Sending an Email with Attachments\u003c/h2\u003e\n\u003cp\u003eTo send an email in Python with attachments securely, you will need some additional libraries like MIMEBase and encoders. Here's the code for this case:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e email \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e encoders\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e email.mime.base \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e MIMEBase\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e email.mime.multipart \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e MIMEMultipart\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e email.mime.text \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e MIMEText\n\nsender = \u003cspan class=\"hljs-string\"\u003e\u0026quot;sender1@gmail.com\u0026quot;\u003c/span\u003e\npassword = \u003cspan class=\"hljs-string\"\u003e\u0026quot;my_password\u0026quot;\u003c/span\u003e\nreceiver = \u003cspan class=\"hljs-string\"\u003e\u0026quot;receiver1@gmail.com\u0026quot;\u003c/span\u003e\nsubject = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Email with Attachments\u0026quot;\u003c/span\u003e\nbody = \u003cspan class=\"hljs-string\"\u003e\u0026quot;This is an email with attachments created in Python using Gmail SMTP and SSL.\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-keyword\"\u003ewith\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eopen\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;attachment.txt\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;rb\u0026quot;\u003c/span\u003e) \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e attachment:\n part = MIMEBase(\u003cspan class=\"hljs-string\"\u003e\u0026quot;application\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;octet-stream\u0026quot;\u003c/span\u003e) \u003cspan class=\"hljs-comment\"\u003e# Adding the attachment to the email\u003c/span\u003e\n part.set_payload(attachment.read())\n \nencoders.encode_base64(part)\npart.add_header(\n \u003cspan class=\"hljs-string\"\u003e\u0026quot;Content-Disposition\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-comment\"\u003e# The header indicates that the file name is an attachment. \u003c/span\u003e\n \u003cspan class=\"hljs-string\"\u003ef\u0026quot;attachment; filename=\u0026#x27;attachment.txt\u0026#x27;\u0026quot;\u003c/span\u003e,\n)\n\nmessage = MIMEMultipart()\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Subject\u0026#x27;\u003c/span\u003e] = subject\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;From\u0026#x27;\u003c/span\u003e] = sender\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;To\u0026#x27;\u003c/span\u003e] = receiver\nhtml_part = MIMEText(body)\nmessage.attach(html_part) \u003cspan class=\"hljs-comment\"\u003e# To attach the file\u003c/span\u003e\nmessage.attach(part)\n\u003cspan class=\"hljs-keyword\"\u003ewith\u003c/span\u003e smtplib.SMTP_SSL(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;smtp.gmail.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e465\u003c/span\u003e) \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e server:\n server.login(sender, password)\n server.sendmail(sender, receiver, message.as_string())\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eExplanation:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eMIMEMultipart\u003c/code\u003e: This library allows you to add text and attachments both to an email separately.\u003c/li\u003e\n\u003cli\u003e'rb': It represents binary mode for the attachment to be opened and the content to be read.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMIMEBase\u003c/code\u003e: This object is applicable to any file type.\u003c/li\u003e\n\u003cli\u003eEncode and Base64: The file will be encoded in \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://stackabuse.com/encoding-and-decoding-base64-strings-in-python/\"\u003eBase64\u003c/a\u003e for safe email sending.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"sendinganhtmlemailinpython\"\u003eSending an HTML Email in Python\u003c/h3\u003e\n\u003cp\u003eTo send an HTML email in Python using Gmail SMTP, you need a class - MIMEText.\u003c/p\u003e\n\u003cp\u003eHere's the full code for \u003ca href=\"https://mailtrap.io/blog/python-send-html-email/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003ePython send HTML email\u003c/a\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e email.mime.text \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e MIMEText\n\nsender = \u003cspan class=\"hljs-string\"\u003e\u0026quot;sender1@gmail.com\u0026quot;\u003c/span\u003e\npassword = \u003cspan class=\"hljs-string\"\u003e\u0026quot;my_password\u0026quot;\u003c/span\u003e\n\nreceiver = \u003cspan class=\"hljs-string\"\u003e\u0026quot;receiver1@gmail.com\u0026quot;\u003c/span\u003e\nsubject = \u003cspan class=\"hljs-string\"\u003e\u0026quot;HTML Email in Python\u0026quot;\u003c/span\u003e\n\nbody = \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026quot;\u0026quot;\n\u0026lt;html\u0026gt;\n \u0026lt;body\u0026gt;\n \u0026lt;p\u0026gt;HTML email created in Python with SSL and Gmail SMTP.\u0026lt;/p\u0026gt;\n \u0026lt;/body\u0026gt;\n\u0026lt;/html\u0026gt;\n\u0026quot;\u0026quot;\u0026quot;\u003c/span\u003e\n\nmessage = MIMEText(body, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;html\u0026#x27;\u003c/span\u003e) \u003cspan class=\"hljs-comment\"\u003e# To attach the HTML content to the email\u003c/span\u003e\n\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Subject\u0026#x27;\u003c/span\u003e] = subject\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;From\u0026#x27;\u003c/span\u003e] = sender\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;To\u0026#x27;\u003c/span\u003e] = receiver\n\n\u003cspan class=\"hljs-keyword\"\u003ewith\u003c/span\u003e smtplib.SMTP_SSL(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;smtp.gmail.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e465\u003c/span\u003e) \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e server:\n server.login(sender, password)\n server.sendmail(sender, receiver, message.as_string())\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"testingyouremailwithauthenticationandencryption\"\u003eTesting Your Email With Authentication and Encryption\u003c/h2\u003e\n\u003cp\u003eTesting your emails before sending them to the recipients is important. It enables you to discover any issues or bugs in sending emails or with the formatting, content, etc.\u003c/p\u003e\n\u003cp\u003eThus, always test your emails on a staging server before delivering them to your target recipients, especially when sending emails in bulk. Testing emails provide the following advantages:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eEnsures the email sending functionality is working fine\u003c/li\u003e\n\u003cli\u003eEmails have proper formatting and no broken links or attachments\u003c/li\u003e\n\u003cli\u003ePrevents flooding the recipient's inbox with a large number of test emails\u003c/li\u003e\n\u003cli\u003eEnhances email deliverability and reduces spam rates\u003c/li\u003e\n\u003cli\u003eEnsures the email and its contents stay protected from attacks and unauthorized access\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eTo test this combined setup of sending emails in Python with authentication and encryption enabled, use an email testing server like Mailtrap Email Testing. This will capture all the SMTP traffic from the staging environment, and detect and debug your emails before sending them. It will also analyze the email content, validate CSS/HTML, and provide a spam score so you can improve your email sending.\u003c/p\u003e\n\u003cp\u003eTo get started:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eOpen \u003ca href=\"https://mailtrap.io/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eMailtrap Email Testing\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eGo to 'My Inbox'\u003c/li\u003e\n\u003cli\u003eClick on 'Show Credentials' to get your test credentials - login and password details\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eHere's the Full Code Example for Testing Your Emails:\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e socket \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e gaierror\n\nport = \u003cspan class=\"hljs-number\"\u003e2525\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e# Define the SMTP server separately\u003c/span\u003e\nsmtp_server = \u003cspan class=\"hljs-string\"\u003e\u0026quot;sandbox.smtp.mailtrap.io\u0026quot;\u003c/span\u003e\nlogin = \u003cspan class=\"hljs-string\"\u003e\u0026quot;xyz123\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e# Paste your Mailtrap login details\u003c/span\u003e\npassword = \u003cspan class=\"hljs-string\"\u003e\u0026quot;abc$$\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e# Paste your Mailtrap password\u003c/span\u003e\nsender = \u003cspan class=\"hljs-string\"\u003e\u0026quot;test_sender@test.com\u0026quot;\u003c/span\u003e\nreceiver = \u003cspan class=\"hljs-string\"\u003e\u0026quot;test_receiver@example.com\u0026quot;\u003c/span\u003e\n\nmessage = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;\u0026quot;\u0026quot;\\\nSubject: Hello There!\nTo: \u003cspan class=\"hljs-subst\"\u003e{receiver}\u003c/span\u003e\nFrom: \u003cspan class=\"hljs-subst\"\u003e{sender}\u003c/span\u003e\nThis is a test email.\u0026quot;\u0026quot;\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-keyword\"\u003etry\u003c/span\u003e:\n \u003cspan class=\"hljs-keyword\"\u003ewith\u003c/span\u003e smtplib.SMTP(smtp_server, port) \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e server: \u003cspan class=\"hljs-comment\"\u003e# Use Mailtrap-generated credentials for port, server name, login, and password\u003c/span\u003e\n server.login(login, password)\n server.sendmail(sender, receiver, message)\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Sent\u0026#x27;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-keyword\"\u003eexcept\u003c/span\u003e (gaierror, ConnectionRefusedError): \u003cspan class=\"hljs-comment\"\u003e# In case of errors\u003c/span\u003e\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Unable to connect to the server.\u0026#x27;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-keyword\"\u003eexcept\u003c/span\u003e smtplib.SMTPServerDisconnected:\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Server connection failed!\u0026#x27;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-keyword\"\u003eexcept\u003c/span\u003e smtplib.SMTPException \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e e:\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;SMTP error: \u0026#x27;\u003c/span\u003e + \u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e(e))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf there's no error, you should see this message in the receiver's inbox:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eThis is a test email.\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"bestpracticesforsecureemailsending\"\u003eBest Practices for Secure Email Sending\u003c/h2\u003e\n\u003cp\u003eConsider the below \u003cstrong\u003ePython email best practices\u003c/strong\u003e for secure email sending:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eProtect data\u003c/strong\u003e: Take appropriate security measures to protect your sensitive data such as SMTP credentials, API keys, etc. Store them in a secure, private place like config files or environment variables, ensuring no one can access them publicly.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eEncryption and authentication\u003c/strong\u003e: Always use email encryption and authentication so that only authorized individuals can access your emails and their content.\u003c/p\u003e\n\u003cp\u003eFor authentication, you can use advanced methods like API keys, two-factor authentication, single sign-on (SSO), etc. Similarly, use advanced encryption techniques like SSL, TLS, E2EE, etc.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eError handling\u003c/strong\u003e: Manage network issues, authentication errors, and other issues by handling errors effectively using \u003ccode\u003eexcept/try\u003c/code\u003e blocks in your code.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eRate-Limiting\u003c/strong\u003e: Maintain high email deliverability by rate-limiting the email sending functionality to prevent exceeding your service limits.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eValidate Emails\u003c/strong\u003e: \u003ca href=\"https://stackabuse.com/validate-email-addresses-in-python-with-email-validator/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eValidate email addresses\u003c/a\u003e from your list and remove invalid ones to enhance email deliverability and prevent your domain from getting marked as spam. You can use an \u003ca href=\"https://stackabuse.com/python-validate-email-address-with-regular-expressions-regex/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eemail validation tool\u003c/a\u003e to do this.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eEducate\u003c/strong\u003e: Keep your team updated with secure email practices and cybersecurity risks. Monitor your spam score and email deliverability rates, and work to improve them.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"wrappingup\"\u003eWrapping Up\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eSecure email sending with Python\u003c/strong\u003e using advanced email encryption methods like SSL, TLS, and end-to-end encryption, as well as authentication protocols and techniques such as SPF, DMARC, 2FA, and API keys.\u003c/p\u003e\n\u003cp\u003eBy combining these security measures, you can protect your confidential email information, improve email deliverability, and maintain trust with your target recipients. In this way, only individuals with appropriate credentials can access it. This will help prevent unauthorized access, data breaches, and other cybersecurity attacks.\u003c/p\u003e\n","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"read_time_min":19,"published_at":1726712953211,"created_at":1726711039615,"updated_at":1726712957181,"tags":[{"id":9,"name":"python","slug":"python","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1431358631000,"updated_at":1431358631000,"_pivot_content_id":2134,"_pivot_tag_id":9,"_pivot_sort_order":0},{"id":108,"name":"email","slug":"email","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1538359651000,"updated_at":1538359651000,"_pivot_content_id":2134,"_pivot_tag_id":108,"_pivot_sort_order":1}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2134,"_pivot_user_id":1,"_pivot_role":"editor","_pivot_sort_order":1},{"id":26126,"name":"Ivan Djuric","slug":"ivan","role_id":null,"img_profile":"https://s3.amazonaws.com/s3.stackabuse.com/media/users/b9227b402289ab251e04427e15e2d4f6.jpg","img_cover":null,"bio_html":"\u003cp\u003eI’m a Technical Content Writer with 5 years of background covering email-related topics in tight collaboration with software engineers and email marketers. I just love to research and share actionable insights with you about email sending, testing, deliverability improvements, and more. Happy to be your guide in the world of emails!\u003c/p\u003e\n","website":null,"location":null,"facebook":null,"twitter":null,"github":null,"created_at":1724257087195,"updated_at":1724257803744,"role":"contributor","_pivot_content_id":2134,"_pivot_user_id":26126,"_pivot_role":"author","_pivot_sort_order":0}],"_pivot_user_id":1,"_pivot_content_id":2134},{"id":2133,"title":"Using Proxies in Web Scraping – All You Need to Know","slug":"using-proxies-in-web-scraping-all-you-need-to-know","body_html":"\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cp\u003eWeb scraping typically refers to an \u003cem\u003eautomated process of collecting data from websites.\u003c/em\u003e On a high level, you're essentially making a bot that visits a website, detects the data you're interested in, and then stores it into some appropriate data structure, so you can easily analyze and access it later.\u003c/p\u003e\n\u003cp\u003eHowever, if you're concerned about your anonymity on the Internet, you should probably take a little more care when scraping the web. Since your IP address is public, a website owner could track it down and, potentially, block it.\u003c/p\u003e\n\u003cp\u003eSo, if you want to stay as anonymous as possible, and prevent being blocked from visiting a certain website, you should consider using proxies when scraping the web.\u003c/p\u003e\n\u003cp\u003eProxies, also referred to as \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://oxylabs.io/products/paid-proxy-servers\"\u003eproxy servers\u003c/a\u003e, are specialized servers that enable you not to directly access the websites you're scraping. Rather, you'll be \u003cem\u003erouting your scraping requests via a proxy server\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003eThat way, your IP address gets \u0026quot;hidden\u0026quot; behind the IP address of the proxy server you're using. This can help you both stay as anonymous as possible, as well as not being blocked, so you can keep scraping as long as you want.\u003c/p\u003e\n\u003cp\u003eIn this comprehensive guide, you'll get a grasp of the basics of web scraping and proxies, you'll see the actual, working example of scraping a website using proxies in \u003ca href=\"https://nodejs.org/en\" target=\"_blank\" rel=\"nofollow noopener\"\u003eNode.js\u003c/a\u003e. Afterward, we'll discuss why you might consider using existing scraping solutions (like \u003ca href=\"https://www.scraperapi.com/\"\u003eScraperAPI\u003c/a\u003e) over writing your own web scraper. At the end, we'll give you some tips on how to overcome some of the most common issues you might face when scraping the web.\u003c/p\u003e\n\u003ch2 id=\"webscraping\"\u003eWeb Scraping\u003c/h2\u003e\n\u003cp\u003eWeb scraping is the process of extracting data from websites. It automates what would otherwise be a manual process of gathering information, making the process less time-consuming and prone to errors.\u003c/p\u003e\n\u003cp\u003eThat way you can collect a large amount of data quickly and efficiently. Later, you can analyze, store, and use it.\u003c/p\u003e\n\u003cp\u003eThe primary reason you might scrape a website is to obtain data that is either unavailable through an existing API or too vast to collect manually.\u003c/p\u003e\n\u003cp\u003eIt's particularly useful when you need to extract information from multiple pages or when the data is spread across different websites.\u003c/p\u003e\n\u003cp\u003eThere are many real-world applications that utilize the power of web scraping in their business model. The majority of apps helping you track product prices and discounts, find cheapest flights and hotels, or even collect \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://coresignal.com/alternative-data/job-postings-data/\"\u003ejob posting data\u003c/a\u003e for job seekers, use the technique of web scraping to gather the data that provides you the value.\u003c/p\u003e\n\u003ch2 id=\"webproxies\"\u003eWeb Proxies\u003c/h2\u003e\n\u003cp\u003eImagine you're sending a request to a website. Usually, your request is sent from your machine (with your IP address) to the server that hosts a website you're trying to access. That means that the server \u0026quot;knows\u0026quot; your IP address and it can block you based on your geo-location, the amount of traffic you're sending to the website, and many more factors.\u003c/p\u003e\n\u003cp\u003eBut when you send a request through a proxy, it routes the request through another server, hiding your original IP address behind the IP address of the proxy server. This not only helps in maintaining anonymity but also plays a crucial role in avoiding IP blocking, which is a common issue in web scraping.\u003c/p\u003e\n\u003cp\u003eBy rotating through different IP addresses, proxies allow you to distribute your requests, making them appear as if they're coming from various users. This reduces the likelihood of getting blocked and increases the chances of successfully scraping the desired data.\u003c/p\u003e\n\u003ch3 id=\"typesofproxies\"\u003eTypes of Proxies\u003c/h3\u003e\n\u003cp\u003eTypically, there are four main types of proxy servers - \u003cem\u003edatacenter, residential, rotating, and mobile.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eEach of them has its pros and cons, and based on that, you'll use them for different purposes and at different costs.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eDatacenter proxies\u003c/strong\u003e are the most common and \u003cem\u003ecost-effective\u003c/em\u003e proxies, provided by third-party data centers. They offer \u003cem\u003ehigh speed and reliability\u003c/em\u003e but are more easily detectable and \u003cem\u003ecan be blocked by websites more frequently\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResidential proxies\u003c/strong\u003e route your requests through real residential IP addresses. Since they appear as ordinary user connections, they are \u003cem\u003eless likely to be blocked\u003c/em\u003e but are \u003cem\u003etypically more expensive\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eRotating proxies\u003c/strong\u003e automatically change the IP address after each request or after a set period. This is particularly \u003cem\u003euseful for large-scale scraping projects\u003c/em\u003e, as it \u003cem\u003esignificantly reduces the chances of being detected and blocked\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eMobile proxies\u003c/strong\u003e use IP addresses associated with mobile devices. They are \u003cem\u003ehighly effective for scraping mobile-optimized websites or apps\u003c/em\u003e and are \u003cem\u003eless likely to be blocked\u003c/em\u003e, but they typically come at a \u003cem\u003epremium cost\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eISP proxies\u003c/strong\u003e are a newer type that combines the reliability of datacenter proxies with the legitimacy of residential IPs. They use IP addresses from Internet Service Providers but are hosted in data centers, offering a balance between performance and detection avoidance.\u003c/p\u003e\n\u003ch2 id=\"examplewebscrapingproject\"\u003eExample Web Scraping Project\u003c/h2\u003e\n\u003cp\u003eLet's walk through a practical example of a web scraping project, and demonstrate how to set up a basic scraper, integrate proxies, and use a scraping service like \u003ca href=\"https://www.scraperapi.com?via=scott47\"\u003eScraperAPI\u003c/a\u003e.\u003c/p\u003e\n\u003ch3 id=\"settingup\"\u003eSetting up\u003c/h3\u003e\n\u003cp\u003eBefore you dive into the actual scraping process, it's essential to set up your development environment.\u003c/p\u003e\n\u003cp\u003eFor this example, we'll be using \u003ca href=\"https://nodejs.org/en\" target=\"_blank\" rel=\"nofollow noopener\"\u003eNode.js\u003c/a\u003e since it's well-suited for web scraping due to its asynchronous capabilities. We'll use \u003ca href=\"https://axios-http.com/\" target=\"_blank\" rel=\"nofollow noopener\"\u003eAxios\u003c/a\u003e for making HTTP requests, and \u003ca href=\"https://cheerio.js.org/\" target=\"_blank\" rel=\"nofollow noopener\"\u003eCheerio\u003c/a\u003e to parse and manipulate HTML (that's contained in the response of the HTTP request).\u003c/p\u003e\n\u003cp\u003eFirst, \u003cem\u003eensure you have Node.js installed\u003c/em\u003e on your system. If you don't have it, download and install it from \u003ca href=\"https://nodejs.org/en\" target=\"_blank\" rel=\"nofollow noopener\"\u003enodejs.org\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThen, create a new directory for your project and initialize it:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e$ mkdir my-web-scraping-project\n$ cd my-web-scraping-project\n$ npm init -y\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFinally, install Axios and Cheerio since they are necessary for you to implement your web scraping logic:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e$ npm install axios cheerio\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"simplewebscrapingscript\"\u003eSimple Web Scraping Script\u003c/h3\u003e\n\u003cp\u003eNow that your environment is set up, let's create a simple web scraping script. We'll scrape \u003ca href=\"https://quotes.toscrape.com/\" target=\"_blank\" rel=\"nofollow noopener\"\u003ea sample website\u003c/a\u003e to gather famous quotes and their authors.\u003c/p\u003e\n\u003cp\u003eSo, create a JavaScript file named \u003ccode\u003esample-scraper.js\u003c/code\u003e and write all the code inside of it. Import the packages you'll need to send HTTP requests and manipulate the HTML:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e axios = \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;axios\u0026#x27;\u003c/span\u003e);\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e cheerio = \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;cheerio\u0026#x27;\u003c/span\u003e);\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNext, create a wrapper function that will contain all the logic you need to scrape data from a web page. It accepts the URL of a website you want to scrape as an argument and returns all the quotes found on the page:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Function to scrape data from a webpage\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003easync\u003c/span\u003e \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003escrapeWebsite\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eurl\u003c/span\u003e) \u003c/span\u003e{\n \u003cspan class=\"hljs-keyword\"\u003etry\u003c/span\u003e {\n \u003cspan class=\"hljs-comment\"\u003e// Send a GET request to the webpage\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e response = \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e axios.get(url);\n \n \u003cspan class=\"hljs-comment\"\u003e// Load the HTML into cheerio\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e $ = cheerio.load(response.data);\n \n \u003cspan class=\"hljs-comment\"\u003e// Extract all elements with the class \u0026#x27;quote\u0026#x27;\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e quotes = [];\n $(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;div.quote\u0026#x27;\u003c/span\u003e).each(\u003cspan class=\"hljs-function\"\u003e(\u003cspan class=\"hljs-params\"\u003eindex, element\u003c/span\u003e) =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-comment\"\u003e// Extracting text from span with class \u0026#x27;text\u0026#x27;\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e quoteText = $(element).find(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;span.text\u0026#x27;\u003c/span\u003e).text().trim(); \n \u003cspan class=\"hljs-comment\"\u003e// Assuming there\u0026#x27;s a small tag for the author\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e author = $(element).find(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;small.author\u0026#x27;\u003c/span\u003e).text().trim(); \n quotes.push({ \u003cspan class=\"hljs-attr\"\u003equote\u003c/span\u003e: quoteText, \u003cspan class=\"hljs-attr\"\u003eauthor\u003c/span\u003e: author });\n });\n\n \u003cspan class=\"hljs-comment\"\u003e// Output the quotes\u003c/span\u003e\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Quotes found on the webpage:\u0026quot;\u003c/span\u003e);\n quotes.forEach(\u003cspan class=\"hljs-function\"\u003e(\u003cspan class=\"hljs-params\"\u003equote, index\u003c/span\u003e) =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${index + \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e}\u003c/span\u003e: \u0026quot;\u003cspan class=\"hljs-subst\"\u003e${quote.quote}\u003c/span\u003e\u0026quot; - \u003cspan class=\"hljs-subst\"\u003e${quote.author}\u003c/span\u003e`\u003c/span\u003e);\n });\n\n } \u003cspan class=\"hljs-keyword\"\u003ecatch\u003c/span\u003e (error) {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.error(\u003cspan class=\"hljs-string\"\u003e`An error occurred: \u003cspan class=\"hljs-subst\"\u003e${error.message}\u003c/span\u003e`\u003c/span\u003e);\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e All the quotes are stored in a separate \u003ccode\u003ediv\u003c/code\u003e element with a class of \u003ccode\u003equote\u003c/code\u003e. Each quote has its \u003cem\u003etext and author\u003c/em\u003e - text is stored under the \u003ccode\u003espan\u003c/code\u003e element with the class of \u003ccode\u003etext\u003c/code\u003e, and the author is within the \u003ccode\u003esmall\u003c/code\u003e element with the class of \u003ccode\u003eauthor\u003c/code\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eFinally, specify the URL of the website you want to scrape - in this case, \u003ccode\u003ehttps://quotes.toscrape.com\u003c/code\u003e, and call the \u003ccode\u003escrapeWebsite()\u003c/code\u003e function:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e// URL of the website you want to scrape\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e url = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;https://quotes.toscrape.com\u0026#x27;\u003c/span\u003e;\n\n\u003cspan class=\"hljs-comment\"\u003e// Call the function to scrape the website\u003c/span\u003e\nscrapeWebsite(url);\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAll that's left for you to do is to run the script from the terminal:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e$ node sample-scraper.js\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"integratingproxies\"\u003eIntegrating Proxies\u003c/h3\u003e\n\u003cp\u003eTo use a proxy with \u003ccode\u003eaxios\u003c/code\u003e, you specify the proxy settings in the request configuration. The \u003ccode\u003eaxios.get()\u003c/code\u003e method can include the \u003ccode\u003eproxy\u003c/code\u003e configuration, allowing the request to route through the specified proxy server. The \u003ccode\u003eproxy\u003c/code\u003e object contains the \u003cem\u003ehost, port, and optional authentication details\u003c/em\u003e for the proxy:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Send a GET request to the webpage with proxy configuration\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e response = \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e axios.get(url, {\n \u003cspan class=\"hljs-attr\"\u003eproxy\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ehost\u003c/span\u003e: proxy.host,\n \u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e: proxy.port,\n \u003cspan class=\"hljs-attr\"\u003eauth\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eusername\u003c/span\u003e: proxy.username, \u003cspan class=\"hljs-comment\"\u003e// Optional: Include if your proxy requires authentication\u003c/span\u003e\n \u003cspan class=\"hljs-attr\"\u003epassword\u003c/span\u003e: proxy.password, \u003cspan class=\"hljs-comment\"\u003e// Optional: Include if your proxy requires authentication\u003c/span\u003e\n },\n },\n});\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e You need to replace these placeholders with your actual proxy details.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eOther than this change, the entire script remains the same:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Function to scrape data from a webpage\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003easync\u003c/span\u003e \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003escrapeWebsite\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eurl\u003c/span\u003e) \u003c/span\u003e{\n \u003cspan class=\"hljs-keyword\"\u003etry\u003c/span\u003e {\n \u003cspan class=\"hljs-comment\"\u003e// Send a GET request to the webpage with proxy configuration\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e response = \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e axios.get(url, {\n \u003cspan class=\"hljs-attr\"\u003eproxy\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ehost\u003c/span\u003e: proxy.host,\n \u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e: proxy.port,\n \u003cspan class=\"hljs-attr\"\u003eauth\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eusername\u003c/span\u003e: proxy.username, \u003cspan class=\"hljs-comment\"\u003e// Optional: Include if your proxy requires authentication\u003c/span\u003e\n \u003cspan class=\"hljs-attr\"\u003epassword\u003c/span\u003e: proxy.password, \u003cspan class=\"hljs-comment\"\u003e// Optional: Include if your proxy requires authentication\u003c/span\u003e\n },\n },\n });\n \n \u003cspan class=\"hljs-comment\"\u003e// Load the HTML into cheerio\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e $ = cheerio.load(response.data);\n \n \u003cspan class=\"hljs-comment\"\u003e// Extract all elements with the class \u0026#x27;quote\u0026#x27;\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e quotes = [];\n $(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;div.quote\u0026#x27;\u003c/span\u003e).each(\u003cspan class=\"hljs-function\"\u003e(\u003cspan class=\"hljs-params\"\u003eindex, element\u003c/span\u003e) =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-comment\"\u003e// Extracting text from span with class \u0026#x27;text\u0026#x27;\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e quoteText = $(element).find(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;span.text\u0026#x27;\u003c/span\u003e).text().trim(); \n \u003cspan class=\"hljs-comment\"\u003e// Assuming there\u0026#x27;s a small tag for the author\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e author = $(element).find(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;small.author\u0026#x27;\u003c/span\u003e).text().trim(); \n quotes.push({ \u003cspan class=\"hljs-attr\"\u003equote\u003c/span\u003e: quoteText, \u003cspan class=\"hljs-attr\"\u003eauthor\u003c/span\u003e: author });\n });\n\n \u003cspan class=\"hljs-comment\"\u003e// Output the quotes\u003c/span\u003e\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Quotes found on the webpage:\u0026quot;\u003c/span\u003e);\n quotes.forEach(\u003cspan class=\"hljs-function\"\u003e(\u003cspan class=\"hljs-params\"\u003equote, index\u003c/span\u003e) =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${index + \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e}\u003c/span\u003e: \u0026quot;\u003cspan class=\"hljs-subst\"\u003e${quote.quote}\u003c/span\u003e\u0026quot; - \u003cspan class=\"hljs-subst\"\u003e${quote.author}\u003c/span\u003e`\u003c/span\u003e);\n });\n\n } \u003cspan class=\"hljs-keyword\"\u003ecatch\u003c/span\u003e (error) {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.error(\u003cspan class=\"hljs-string\"\u003e`An error occurred: \u003cspan class=\"hljs-subst\"\u003e${error.message}\u003c/span\u003e`\u003c/span\u003e);\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"usingheadlessbrowsersforadvancedscraping\"\u003eUsing Headless Browsers for Advanced Scraping\u003c/h3\u003e\n\u003cp\u003eFor websites with complex JavaScript interactions, you might need to use a headless browser instead of simple HTTP requests. Tools like Puppeteer or Playwright allow you to automate a real browser, execute JavaScript, and interact with dynamic content.\u003c/p\u003e\n\u003cp\u003eHere's a simple example using Puppeteer:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e puppeteer = \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;puppeteer\u0026#x27;\u003c/span\u003e);\n\n\u003cspan class=\"hljs-keyword\"\u003easync\u003c/span\u003e \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003escrapeWithPuppeteer\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eurl\u003c/span\u003e) \u003c/span\u003e{\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e browser = \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e puppeteer.launch();\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e page = \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e browser.newPage();\n \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e page.goto(url, { \u003cspan class=\"hljs-attr\"\u003ewaitUntil\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;networkidle2\u0026#x27;\u003c/span\u003e });\n \n \u003cspan class=\"hljs-comment\"\u003e// Extract data using page.evaluate\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e quotes = \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e page.evaluate(\u003cspan class=\"hljs-function\"\u003e() =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e results = [];\n \u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelectorAll(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;div.quote\u0026#x27;\u003c/span\u003e).forEach(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003equote\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n results.push({\n \u003cspan class=\"hljs-attr\"\u003etext\u003c/span\u003e: quote.querySelector(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;span.text\u0026#x27;\u003c/span\u003e).textContent,\n \u003cspan class=\"hljs-attr\"\u003eauthor\u003c/span\u003e: quote.querySelector(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;small.author\u0026#x27;\u003c/span\u003e).textContent\n });\n });\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e results;\n });\n \n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(quotes);\n \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e browser.close();\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHeadless browsers can also be configured to use proxies, making them powerful tools for scraping complex websites while maintaining anonymity.\u003c/p\u003e\n\u003ch3 id=\"integratingascrapingservice\"\u003eIntegrating a Scraping Service\u003c/h3\u003e\n\u003cp\u003eUsing a scraping service like \u003ca href=\"https://www.scraperapi.com?via=scott47\"\u003eScraperAPI\u003c/a\u003e offers several advantages over manual web scraping since it's designed to tackle all of the major problems you might face when scraping websites:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eAutomatically handles common web scraping obstacles\u003c/strong\u003e such as CAPTCHAs, JavaScript rendering, and IP blocks.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAutomatically handles proxies\u003c/strong\u003e - proxy configuration, rotation, and much more.\u003c/li\u003e\n\u003cli\u003eInstead of building your own scraping infrastructure, you can \u003cem\u003eleverage ScraperAPI's pre-built solutions\u003c/em\u003e. This \u003cstrong\u003esaves significant development time and resources\u003c/strong\u003e that can be better spent on analyzing the scraped data.\u003c/li\u003e\n\u003cli\u003eScraperAPI offers various customization options such as \u003cstrong\u003egeo-location targeting, custom headers, and asynchronous scraping\u003c/strong\u003e. You can personalize the service to suit your specific scraping needs.\u003c/li\u003e\n\u003cli\u003eUsing a scraping API like ScraperAPI is often \u003cstrong\u003emore cost-effective\u003c/strong\u003e than building and maintaining your own scraping infrastructure. The pricing is based on usage, allowing you to scale up or down as needed.\u003c/li\u003e\n\u003cli\u003eScraperAPI allows you to \u003cstrong\u003escale your scraping efforts\u003c/strong\u003e by handling millions of requests concurrently.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eTo \u003cstrong\u003eimplement the ScraperAPI proxy\u003c/strong\u003e into the scraping script you've created so far, there are just a few tweaks you need to make in the \u003ccode\u003eaxios\u003c/code\u003e configuration.\u003c/p\u003e\n\u003cp\u003eFirst of all, ensure you have created \u003ca href=\"https://dashboard.scraperapi.com/signup?via=scott47\"\u003ea free ScraperAPI account\u003c/a\u003e. That way, you'll have access to your API key, which will be necessary in the following steps.\u003c/p\u003e\n\u003cp\u003eOnce you get the API key, use it as a password in the \u003ccode\u003eaxios\u003c/code\u003e proxy configuration from the previous section:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Send a GET request to the webpage with ScraperAPI proxy configuration\u003c/span\u003e\naxios.get(url, {\n \u003cspan class=\"hljs-attr\"\u003emethod\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;GET\u0026#x27;\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eproxy\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ehost\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;proxy-server.scraperapi.com\u0026#x27;\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e8001\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eauth\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eusername\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;scraperapi\u0026#x27;\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003epassword\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;YOUR_API_KEY\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e// Paste your API key here\u003c/span\u003e\n },\n \u003cspan class=\"hljs-attr\"\u003eprotocol\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;http\u0026#x27;\u003c/span\u003e\n }\n});\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAnd, that's it, \u003cem\u003eall of your requests will be routed through the ScraperAPI proxy servers\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003eBut to use the full potential of a scraping service you'll have to configure it using the service's dashboard - ScraperAPI is no different here.\u003c/p\u003e\n\u003cp\u003eIt has a user-friendly \u003cstrong\u003edashboard\u003c/strong\u003e where you can \u003cem\u003eset up the web scraping process to best fit your needs\u003c/em\u003e. You can enable proxy or async mode, JavaScript rendering, set a region from where the requests will be sent, set your own HTTP headers, timeouts, and much more.\u003c/p\u003e\n\u003cp\u003eAnd the best thing is that ScraperAPI \u003cstrong\u003eautomatically generates a script\u003c/strong\u003e containing all of the scraper settings, so you can \u003cem\u003eeasily integrate the scraper into your codebase\u003c/em\u003e.\u003c/p\u003e\n\u003ch2 id=\"bestpracticesforusingproxiesinwebscraping\"\u003eBest Practices for Using Proxies in Web Scraping\u003c/h2\u003e\n\u003cp\u003eNot every proxy provider and its configuration are the same. So, it's important to know what proxy service to choose and how to configure it properly.\u003c/p\u003e\n\u003cp\u003eLet's take a look at some tips and tricks to help you with that!\u003c/p\u003e\n\u003ch3 id=\"rotateproxiesregularly\"\u003eRotate Proxies Regularly\u003c/h3\u003e\n\u003cp\u003eImplement a proxy rotation strategy that changes the IP address after a certain number of requests or at regular intervals. This approach can mimic human browsing behavior, making it less likely for websites to flag your activities as suspicious.\u003c/p\u003e\n\u003ch3 id=\"handleratelimits\"\u003eHandle Rate Limits\u003c/h3\u003e\n\u003cp\u003eMany websites enforce rate limits to prevent excessive scraping. To avoid hitting these limits, you can:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eIntroduce Delays\u003c/strong\u003e: Add random delays between requests to simulate human behavior.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor Response Codes\u003c/strong\u003e: Track HTTP response codes to detect when you are being rate-limited. If you receive a 429 (Too Many Requests) response, pause your scraping for a while before trying again.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eImplement Exponential Backoff\u003c/strong\u003e: Rather than using fixed delays, implement exponential backoff that increases wait time after each failed request, which is more effective at handling rate limits.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"usequalityproxies\"\u003eUse Quality Proxies\u003c/h3\u003e\n\u003cp\u003eChoosing high-quality proxies is crucial for successful web scraping. Quality proxies, especially residential ones, are \u003cstrong\u003eless likely to be detected and banned\u003c/strong\u003e by target websites. That's why it's crucial to understand \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://rayobyte.com/blog/how-to-use-residential-proxies/\"\u003ehow to use residential proxies\u003c/a\u003e for your business, enabling you to find valuable leads while avoiding website bans. Using a mix of high-quality proxies can significantly enhance your chances of successful scraping without interruptions.\u003c/p\u003e\n\u003cp\u003eQuality proxy services often provide \u003cstrong\u003ea wide range of IP addresses\u003c/strong\u003e from different regions, enabling you to bypass geo-restrictions and access localized content.\u003c/p\u003e\n\u003cp\u003eReliable proxy services can offer \u003cstrong\u003efaster response times and higher uptime\u003c/strong\u003e, which is essential when scraping large amounts of data.\u003c/p\u003e\n\u003cp\u003eAs your scraping needs grow, having access to a robust proxy service \u003cstrong\u003eallows you to scale your operations without the hassle of managing your own infrastructure\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eUsing a reputable proxy service often comes with \u003cstrong\u003ecustomer support and maintenance\u003c/strong\u003e, which can save you time and effort in troubleshooting issues related to proxies.\u003c/p\u003e\n\u003ch2 id=\"handlingcaptchasandotherchallenges\"\u003eHandling CAPTCHAs and Other Challenges\u003c/h2\u003e\n\u003cp\u003eCAPTCHAs and anti-bot mechanisms are some of the most common obstacles you'll encounter while scraping a web.\u003c/p\u003e\n\u003cp\u003eWebsites use \u003cstrong\u003eCAPTCHAs\u003c/strong\u003e to prevent automated access by trying to differentiate real humans and automated bots. They're achieving that by prompting the users to solve various kinds of puzzles, identify distorted objects, and so on. That can make it really difficult for you to automatically scrape data.\u003c/p\u003e\n\u003cp\u003eEven though there are many both manual and automated CAPTCHA solvers available online, the best strategy for handling CAPTCHAs is to avoid triggering them in the first place. Typically, they are triggered when non-human behavior is detected. For example, a large amount of traffic, sent from a single IP address, using the same HTTP configuration is definitely a red flag!\u003c/p\u003e\n\u003cp\u003eSo, when scraping a website, try mimicking human behavior as much as possible:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAdd delays between requests and spread them out as much as you can.\u003c/li\u003e\n\u003cli\u003eRegularly rotate between multiple IP addresses using a proxy service.\u003c/li\u003e\n\u003cli\u003eRandomize HTTP headers and user agents.\u003c/li\u003e\n\u003cli\u003eMaintain and use cookies appropriately, as many websites track user sessions.\u003c/li\u003e\n\u003cli\u003eConsider implementing browser fingerprint randomization to avoid tracking.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eBeyond CAPTCHAs, websites often use \u003cstrong\u003esophisticated anti-bot measures\u003c/strong\u003e to detect and block scraping.\u003c/p\u003e\n\u003cp\u003eSome websites use \u003cem\u003eJavaScript to detect bots\u003c/em\u003e. Tools like \u003ca href=\"https://pptr.dev/\" target=\"_blank\" rel=\"nofollow noopener\"\u003ePuppeteer\u003c/a\u003e can simulate a real browser environment, allowing your scraper to execute JavaScript and bypass these challenges.\u003c/p\u003e\n\u003cp\u003eWebsites sometimes add \u003cem\u003ehidden form fields or links that only bots will interact with\u003c/em\u003e. So, try avoiding clicking on hidden elements or filling out forms with invisible fields.\u003c/p\u003e\n\u003cp\u003eAdvanced anti-bot systems go as far as \u003cem\u003etracking user behavior, such as mouse movements or time spent on a page\u003c/em\u003e. Mimicking these behaviors using browser automation tools can help bypass these checks.\u003c/p\u003e\n\u003cp\u003eBut the simplest and most efficient way to handle CAPTCHAs and anti-bot measures will definitely be to use a service like \u003ca href=\"https://www.scraperapi.com/blog/bypass-amazon-captchas/?via=scott47\"\u003eScraperAPI\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eSending your scraping requests through ScraperAPI's API will ensure you have \u003cstrong\u003ethe best chance of not being blocked\u003c/strong\u003e. When the API receives the request, it uses advanced machine learning techniques to determine the best request configuration to prevent triggering CAPTCHAs and other anti-bot measures.\u003c/p\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eAs websites became more sophisticated in their anti-scraping measures, the use of proxies has become increasingly important in maintaining your scraping project successful.\u003c/p\u003e\n\u003cp\u003eProxies help you maintain anonymity, prevent IP blocking, and enable you to scale your scraping efforts without getting obstructed by rate limits or geo-restrictions.\u003c/p\u003e\n\u003cp\u003eIn this guide, we've explored the fundamentals of web scraping and the \u003cem\u003ecrucial role that proxies play in this process\u003c/em\u003e. We've discussed how proxies can help maintain anonymity, avoid IP blocks, and distribute requests to mimic natural user behavior. We've also covered the different types of proxies available, each with its own strengths and ideal use cases.\u003c/p\u003e\n\u003cp\u003eWe demonstrated how to set up a basic web scraper and integrate proxies into your scraping script. We also explored the benefits of using a dedicated scraping service like ScraperAPI, which can simplify many of the challenges associated with web scraping at scale.\u003c/p\u003e\n\u003cp\u003eIn the end, we covered the importance of carefully choosing the right type of proxy, rotating them regularly, handling rate limits, and leveraging scraping services when necessary. That way, you can ensure that your web scraping projects will be efficient, reliable, and sustainable.\u003c/p\u003e\n\u003cp\u003eRemember that while web scraping can be a powerful data collection technique, it should always be done responsibly and ethically, with respect for website terms of service and legal considerations.\u003c/p\u003e\n","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"read_time_min":24,"published_at":1726147380000,"created_at":1724870601378,"updated_at":1743471588504,"tags":[{"id":48,"name":"node","slug":"node","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1437348872000,"updated_at":1437348872000,"_pivot_content_id":2133,"_pivot_tag_id":48,"_pivot_sort_order":0},{"id":74,"name":"web scraping","slug":"web-scraping","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1506351575000,"updated_at":1506351575000,"_pivot_content_id":2133,"_pivot_tag_id":74,"_pivot_sort_order":1}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2133,"_pivot_user_id":1,"_pivot_role":"editor","_pivot_sort_order":0},{"id":26156,"name":"Leonardo Rodriguez","slug":"leonardo","role_id":null,"img_profile":"https://s3.amazonaws.com/s3.stackabuse.com/media/users/8c2fb030986b5f431bcdbf3029575fac.jpeg","img_cover":null,"bio_html":"\u003cp\u003eLeo is a technical content writer based in Italy with experience in Python and Node.js. He’s currently working at saas.group as a content marketing manager and is the lead writer for ScraperAPI.\u003c/p\u003e\n","website":null,"location":null,"facebook":null,"twitter":null,"github":null,"created_at":1726665337276,"updated_at":1726751567932,"role":"contributor","_pivot_content_id":2133,"_pivot_user_id":26156,"_pivot_role":"author","_pivot_sort_order":1}],"_pivot_user_id":1,"_pivot_content_id":2133},{"id":2132,"title":"Building Custom Email Templates with HTML and CSS in Python","slug":"building-custom-email-templates-with-html-and-css-in-python","body_html":"\u003cp\u003eAn HTML email utilizes HTML code for presentation. Its design is heavy and looks like a modern web page, rich with visual elements like images, videos, etc., to emphasize different parts of an email's content.\u003c/p\u003e\n\u003cp\u003eBuilding email templates tailored to your brand is useful for various email marketing purposes such as welcoming new customers, order confirmation, and so on. Email template customization allows you to save time by not having to create emails from scratch each time. You can also include an \u003ca href=\"https://mailtrap.io/blog/mailto-links-explained/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eemail link in HTML\u003c/a\u003e to automatically compose emails in your email client.\u003c/p\u003e\n\u003cp\u003eIn this step-by-step guide, you'll learn how to build an HTML email template, add a CSS email design to it, and send it to your target audience.\u003c/p\u003e\n\u003ch2 id=\"settingupyourtemplatedirectoryandjinja2\"\u003eSetting Up Your Template Directory and Jinja2\u003c/h2\u003e\n\u003cp\u003eFollow the steps below to set up your HTML email template directory and Jinja2 for Python email automation:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eCreate a Template Directory\u003c/strong\u003e: To hold your HTML email templates, you will need to set up a template directory inside your project module. Let's name this directory - \u003ccode\u003ehtml_emailtemp\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eInstall Jinja2\u003c/strong\u003e: Jinja is a popular templating engine for Python that developers use to create configuration files, HTML documents, etc. Jinja2 is its latest version. It lets you create dynamic content via loops, blocks, variables, etc. It's used in various Python projects, like building websites and microservices, automating emails with Python, and more.\u003c/p\u003e\n\u003cp\u003eUse this command to install Jinja2 on your computer:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003epip install jinja2\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"creatinganhtmlemailtemplate\"\u003eCreating an HTML Email Template\u003c/h2\u003e\n\u003cp\u003eTo create an \u003ca href=\"https://mailtrap.io/blog/html-email/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eHTML email\u003c/a\u003e template, let's understand how to code your email step by step. If you want to modify your templates, you can do it easily by following the steps below:\u003c/p\u003e\n\u003ch3 id=\"step1structurehtml\"\u003eStep 1: Structure HTML\u003c/h3\u003e\n\u003cp\u003eA basic email will have a proper structure - a header, a body, and a footer.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHeader\u003c/strong\u003e: Used for branding purposes (in emails, at least)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBody\u003c/strong\u003e: It will house the main text or content of the email\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFooter\u003c/strong\u003e: It's at the end of the email if you want to add more links, information, or call-to-actions (CTA)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eBegin by creating your HTML structure, keeping it simple since email clients are less compatible than web browsers. For example, using tables is preferable for custom email layouts.\u003c/p\u003e\n\u003cp\u003eHere's how you can create a basic HTML mail with a defined structure:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;!DOCTYPE \u003cspan class=\"hljs-meta-keyword\"\u003ehtml\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ehtml\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003elang\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;en\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ehead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emeta\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003echarset\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;UTF-8\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emeta\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ename\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;viewport\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003econtent\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;width=device-width, initial-scale=1\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003eHTML Email Template\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003estyle\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003etype\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;text/css\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"css\"\u003e\n \u003cspan class=\"hljs-comment\"\u003e/* Add your CSS here */\u003c/span\u003e\n \u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003estyle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ehead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebody\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;100%\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ealign\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;center\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;600\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-comment\"\u003e\u0026lt;!-- Header --\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;background-color: #1c3f60; color: #ffffff; text-align: center; padding: 20px;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eh1\u003c/span\u003e\u0026gt;\u003c/span\u003eYour order is confirmed\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eh1\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-comment\"\u003e\u0026lt;!-- Body --\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;padding: 20px; font-size: 16px; line-height: 1.6; color:#ffffff;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003eThe estimated delivery date is 22nd August 2024.\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-comment\"\u003e\u0026lt;!-- Footer --\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;background-color: #ff6100; color: #000000; text-align: center; padding: 20px;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003eFor additional help, contact us at support@domain.com\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebody\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ehtml\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eExplanation:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e\u0026lt;!DOCTYPE html\u0026gt;\u003c/code\u003e: This declares HTML as your document type.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e\u0026lt;html\u0026gt;\u003c/code\u003e: This is an HTML page's root element.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e\u0026lt;head\u0026gt;\u003c/code\u003e: This stores the document's metadata, like CSS styles.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e\u0026lt;style\u0026gt;\u003c/code\u003e: CSS styles are defined here.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e\u0026lt;body\u0026gt;\u003c/code\u003e: This stores your email's main content.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e\u0026lt;table\u0026gt;\u003c/code\u003e: This tag defines the email layout, giving it a tabular structure with cells and rows, which makes rendering easier for email clients.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e\u0026lt;tr\u0026gt;\u003c/code\u003e: This tag defines the table's row, allowing vertical content stacking.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e\u0026lt;td\u0026gt;\u003c/code\u003e: This tag is used to define a cell inside a row. It contains content like images, text, buttons, etc.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"step2structureyouremail\"\u003eStep 2: Structure Your Email\u003c/h3\u003e\n\u003cp\u003eNow, let's create the structure of your HTML email. To ensure it's compatible with different email clients, use tables to generate a custom email layout, instead of CSS.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;100%\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ealign\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;center\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;600\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;border: 1px solid #1c3f60; padding: 20px;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ealign\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;center\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eh1\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;color: #7ed957;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003eHi, Jon!\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eh1\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;font-size: 16px; color: #ffde59;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003eThank you for being our valuable customer!\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"stylingtheemailwithcss\"\u003eStyling the Email with CSS\u003c/h2\u003e\n\u003cp\u003eOnce you've defined your email structure, let's start designing emails with HTML and CSS:\u003c/p\u003e\n\u003ch3 id=\"inlinecss\"\u003eInline CSS\u003c/h3\u003e\n\u003cp\u003eUse inline CSS to ensure different email clients render CSS accurately and preserve the intended aesthetics of your email style.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;font-size: 16px; color: blue;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003eStyled paragraph.\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"adjustingstyle\"\u003eAdjusting Style\u003c/h3\u003e\n\u003cp\u003eUsers might use different devices and screen sizes to view your email. Therefore, it's necessary to adapt the style to suit various screen sizes. In this case, we'll use media queries to achieve this goal and facilitate responsive email design.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003estyle\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003etype\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;text/css\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"css\"\u003e\n \u003cspan class=\"hljs-keyword\"\u003e@media\u003c/span\u003e screen \u003cspan class=\"hljs-keyword\"\u003eand\u003c/span\u003e (\u003cspan class=\"hljs-attribute\"\u003emax-width\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e600px\u003c/span\u003e) {\n \u003cspan class=\"hljs-selector-class\"\u003e.container\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003ewidth\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e100%\u003c/span\u003e \u003cspan class=\"hljs-meta\"\u003e!important\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003epadding\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e10px\u003c/span\u003e \u003cspan class=\"hljs-meta\"\u003e!important\u003c/span\u003e;\n }\n }\n\u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003estyle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eclass\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;container\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;600\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-comment\"\u003e\u0026lt;!-- Content --\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eExplanation:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e@media screen and (max-width: 600px) {....}\u003c/code\u003e: This is a media query that targets device screens of up to 600 pixels, ensuring the style applies only to these devices, such as tablets and smartphones.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ewidth: 100% !important;\u003c/code\u003e: This style changes the width of the table - .container. The code instructs that the table width be set to full screen, not 600px.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e!important\u003c/code\u003e: This rule overrides other styles that may conflict with it.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003epadding: 10px !important;\u003c/code\u003e: Inside the .container table, a padding of 10px is added to the table.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"addingctabuttonandlinks\"\u003eAdding CTA Button and Links\u003c/h3\u003e\n\u003cp\u003eHere, we are adding a call to action (CTA) link at the button - \u0026quot;Get a 30-day free trial\u0026quot; that points to this page - \u003ccode\u003ehttps://www.mydomain.com\u003c/code\u003e.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;margin: auto;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ealign\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;center\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;background-color: #8c52ff; padding: 10px 20px; border-radius: 5px;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ehref\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;https://www.mydomain.com\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003etarget\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;_blank\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;color: #ffffff; text-decoration: none; font-weight: bold;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003eGet a 30-day free trial\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eLet's Now Look at the Complete HTML Email Template:\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;!DOCTYPE \u003cspan class=\"hljs-meta-keyword\"\u003ehtml\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ehtml\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003elang\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;en\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ehead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emeta\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003echarset\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;UTF-8\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emeta\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ename\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;viewport\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003econtent\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;width=device-width, initial-scale=1\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003eHTML Email Template\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003estyle\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003etype\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;text/css\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"css\"\u003e\n \u003cspan class=\"hljs-comment\"\u003e/* Adding the CSS */\u003c/span\u003e\n \n \u003cspan class=\"hljs-selector-tag\"\u003ebody\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003emargin\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003epadding\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003ebackground-color\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#f4f4f4\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003efont-family\u003c/span\u003e: Arial, sans-serif;\n }\n \n \u003cspan class=\"hljs-selector-tag\"\u003etable\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003eborder-collapse\u003c/span\u003e: collapse;\n }\n \n \u003cspan class=\"hljs-selector-class\"\u003e.mailcontainer\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003ewidth\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e100%\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003emax-width\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e600px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003emargin\u003c/span\u003e: auto;\n \u003cspan class=\"hljs-attribute\"\u003ebackground-color\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#ffffff\u003c/span\u003e;\n }\n \n \u003cspan class=\"hljs-selector-class\"\u003e.header\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003ebackground-color\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#1c3f60\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003ecolor\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#ffffff\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003etext-align\u003c/span\u003e: center;\n \u003cspan class=\"hljs-attribute\"\u003epadding\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e20px\u003c/span\u003e;\n }\n \n \u003cspan class=\"hljs-selector-class\"\u003e.body\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003epadding\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e20px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003efont-size\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e16px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003eline-height\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e1.6\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003ebackground-color\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#1c3f60\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003ecolor\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#7ed957\u003c/span\u003e;\n }\n \n \u003cspan class=\"hljs-selector-class\"\u003e.footer\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003ebackground-color\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#ff6100\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003ecolor\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#000000\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003etext-align\u003c/span\u003e: center;\n \u003cspan class=\"hljs-attribute\"\u003epadding\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e20px\u003c/span\u003e;\n }\n \n \u003cspan class=\"hljs-selector-class\"\u003e.cta\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003ebackground-color\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#8c52ff\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003epadding\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e10px\u003c/span\u003e \u003cspan class=\"hljs-number\"\u003e20px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003eborder-radius\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e5px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003ecolor\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e#ffffff\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003etext-decoration\u003c/span\u003e: none;\n \u003cspan class=\"hljs-attribute\"\u003efont-weight\u003c/span\u003e: bold;\n }\n \n \u003cspan class=\"hljs-keyword\"\u003e@media\u003c/span\u003e screen \u003cspan class=\"hljs-keyword\"\u003eand\u003c/span\u003e (\u003cspan class=\"hljs-attribute\"\u003emax-width\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e600px\u003c/span\u003e) {\n \u003cspan class=\"hljs-selector-class\"\u003e.container\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003ewidth\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e100%\u003c/span\u003e \u003cspan class=\"hljs-meta\"\u003e!important\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003epadding\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e10px\u003c/span\u003e \u003cspan class=\"hljs-meta\"\u003e!important\u003c/span\u003e;\n }\n }\n \u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003estyle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ehead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebody\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;100%\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ealign\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;center\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eclass\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;container\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;600\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n \u003cspan class=\"hljs-comment\"\u003e\u0026lt;!-- Header --\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eclass\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;header\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eh1\u003c/span\u003e\u0026gt;\u003c/span\u003eYour order is confirmed\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eh1\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n \u003cspan class=\"hljs-comment\"\u003e\u0026lt;!-- Body --\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eclass\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;body\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003eThe estimated delivery date is 22nd August 2024.\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;font-size: 16px; color: blue;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003eStyled paragraph.\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;100%\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;border: 1px solid #1c3f60; padding: 20px;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ealign\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;center\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eh1\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;color: #7ed957;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003eHi, Jon!\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eh1\u003c/span\u003e\u0026gt;\u003c/span\u003e \n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;font-size: 16px; color: #ffde59;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003eThank you for being our valuable customer!\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellpadding\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ecellspacing\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;0\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;margin: auto;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ealign\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;center\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;background-color: #8c52ff; padding: 10px 20px; border-radius: 5px;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ehref\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;https://www.mydomain.com\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003etarget\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;_blank\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003erel\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;noopener noreferrer\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;color: #ffffff; text-decoration: none; font-weight: bold;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003eGet a 30-day free trial\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n \u003cspan class=\"hljs-comment\"\u003e\u0026lt;!-- Footer --\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;background-color: #ff6100; color: #000000; text-align: center; padding: 20px;\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003eFor additional help, contact us at support@domain.com\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ep\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etd\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etr\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etable\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebody\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ehtml\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eExplanation:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e.mailcontainer\u003c/code\u003e: This is a class that you can use to style your email content's main section. It's given a set width, margin, border, and color.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e.header\u003c/code\u003e, \u003ccode\u003e.footer\u003c/code\u003e, \u003ccode\u003e.body\u003c/code\u003e: These are classes used to style your email's header, footer, and body, respectively.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e.cta\u003c/code\u003e: This class allows you to style your buttons, such as CTA buttons, with a specified color, border design, padding, etc.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"bringingeverythingtogetherwithjinja2\"\u003eBringing Everything Together With Jinja2\u003c/h2\u003e\n\u003cp\u003eHaving created our HTML template, it's now time to bring everything together using the Jinja2 templating engine.\u003c/p\u003e\n\u003ch3 id=\"importprojectmodules\"\u003eImport Project Modules\u003c/h3\u003e\n\u003cp\u003eYou've already set up your template directory - \u003ccode\u003ehtml_emailtemp\u003c/code\u003e. Now you can find and render templates using code. But before you do that, import the relevant project modules using the code below:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e jinja2 \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Environment, PackageLoader, select_autoescape\n\nenv = Environment(loader=PackageLoader(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;email_project\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;html_emailtemp\u0026#x27;\u003c/span\u003e), autoescape=select_autoescape([\u003cspan class=\"hljs-string\"\u003e\u0026#x27;html\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;xml\u0026#x27;\u003c/span\u003e]))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eExplanation\u003c/strong\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eEnvironment: Jinja2 utilizes a central object, the template Environment. Its instances store global objects and configurations, and load your email templates from a file.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ePackageLoader\u003c/code\u003e: This configures Jinja2 to load email templates.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eautoescape\u003c/code\u003e: To mitigate security threats such as cross-site scripting (XSS) attacks and protect your code, you can escape values (that are passed to the email template) while rendering HTML using the command \u003ccode\u003eautoescape\u003c/code\u003e. Or, you can validate user inputs to reject malicious code.\u003c/p\u003e\n\u003cp\u003eFor security, \u003ccode\u003eautoescape\u003c/code\u003e is set to \u003ccode\u003eTrue\u003c/code\u003e to enable escaping values. If you turn it to \u003ccode\u003eFalse\u003c/code\u003e, Jinja2 won't be able to escape values, and XSS attacks may occur. To enable autoescape, set \u003ccode\u003eautoescape\u003c/code\u003e to \u003ccode\u003eTrue\u003c/code\u003e:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eenv = Environment(loader=PackageLoader(\u0026quot;myapp\u0026quot;), autoescape=True)\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"loadyourtemplate\"\u003eLoad Your Template\u003c/h3\u003e\n\u003cp\u003eOnce done, a template environment will be created with a template loader to find email templates created inside your project module's template folder.\u003c/p\u003e\n\u003cp\u003eNext, load your HTML email template using the method - \u003ccode\u003eget_template()\u003c/code\u003e. This function will return your loaded template. It also offers several benefits such as enabling email template inheritance, so you can reuse the template in multiple scenarios.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003etemplate1 = env.get_template(\u0026quot;myemailtemplate.html\u0026quot;)\u003c/code\u003e\u003c/p\u003e\n\u003ch3 id=\"renderthetemplate\"\u003eRender the Template\u003c/h3\u003e\n\u003cp\u003eTo render your email template, use the method - \u003ccode\u003erender()\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ehtml1 = template1.render()\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eAs these HTML email templates are dynamic, you can pass keyworded arguments (kwargs) with Jinja2 to the \u003ccode\u003erender\u003c/code\u003e function. The kwargs will then be passed to your email template. Here's how you can render your templates using the destined user's name - \u0026quot;Jon Doe\u0026quot; - in your email.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ehtml1 = template1.render(name=\u0026quot;Jon Doe\u0026quot;)\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eLet's look at the complete code for this section:\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e jinja2 \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Environment, PackageLoader, select_autoescape\n\nenv = Environment(loader=PackageLoader(\u003cspan class=\"hljs-string\"\u003e\u0026quot;email_project\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;html_emailtemp\u0026quot;\u003c/span\u003e),\n autoescape=select_autoescape([\u003cspan class=\"hljs-string\"\u003e\u0026quot;html\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;xml\u0026quot;\u003c/span\u003e]))\n\ntemplate1 = env.get_template(\u003cspan class=\"hljs-string\"\u003e\u0026quot;myemailtemplate.html\u0026quot;\u003c/span\u003e)\nhtml1 = template1.render()\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"sendingtheemail\"\u003eSending the Email\u003c/h2\u003e\n\u003cp\u003eTo send an email, you can use the application-level, straightforward protocol - Simple Mail Transfer Protocol (SMTP). This protocol streamlines the email sending process and determines how to format, send, and encrypt your emails between the source and destination mail servers.\u003c/p\u003e\n\u003cp\u003eIn this instance, we'll send emails in Python via SMTP since Python offers a built-in module for email sending. To send emails, Python provides a library, 'smtplib', to facilitate effortless interaction with the SMTP protocol.\u003c/p\u003e\n\u003cp\u003eTo get started:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eInstall 'smtplib'\u003c/strong\u003e: Ensure you have installed Python on your system. Now, import 'smtplib' to set up connectivity with the mail server.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eimport smtplib\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eDefine your HTML parameter\u003c/strong\u003e: Define your HTML parameter for the mail object where you'll keep your HTML template. It will instruct email clients to render the template.\u003c/p\u003e\n\u003cp\u003eHere's the full code for this section:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e smtplib\n\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e email.mime.text \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e MIMEText \u003cspan class=\"hljs-comment\"\u003e# MIMEText is a class from the email package \u003c/span\u003e\n\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e jinja2 \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Template \u003cspan class=\"hljs-comment\"\u003e# Let\u0026#x27;s use Template class for our HTML template \u003c/span\u003e\n\nsender = \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026lt;a href=\u0026#x27;mailto:sender1@gmail.com\u0026#x27; target=\u0026#x27;_blank\u0026#x27; rel=\u0026#x27;noopener noreferrer\u0026#x27;\u0026gt;sender1@gmail.com\u0026lt;/a\u0026gt;\u0026quot;\u003c/span\u003e\n\nrecipient = \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026lt;a href=\u0026#x27;mailto:recipient1@gmail.com\u0026#x27; target=\u0026#x27;_blank\u0026#x27; rel=\u0026#x27;noopener noreferrer\u0026#x27;\u0026gt;recipient1@gmail.com\u0026lt;/a\u0026gt;\u0026quot;\u003c/span\u003e\n\nsubject = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Your order is confirmed!\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-keyword\"\u003ewith\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eopen\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;myemailtemplate.html\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;r\u0026#x27;\u003c/span\u003e) \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e f:\n template1 = Template(f.read())\n\n\u003cspan class=\"hljs-comment\"\u003e# Enter the HTML template\u003c/span\u003e\n\nhtml_emailtemp = \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026quot;\u0026quot;\n\u0026lt;!DOCTYPE html\u0026gt;\n\u0026lt;html lang=\u0026#x27;en\u0026#x27;\u0026gt;\n\u0026lt;head\u0026gt;\n \u0026lt;meta charset=\u0026#x27;UTF-8\u0026#x27;\u0026gt;\n \u0026lt;meta name=\u0026#x27;viewport\u0026#x27; content=\u0026#x27;width=device-width, initial-scale=1\u0026#x27;\u0026gt;\n\n \u0026lt;title\u0026gt;HTML Email Template\u0026lt;/title\u0026gt;\n\n \u0026lt;style type=\u0026#x27;text/css\u0026#x27;\u0026gt; # Adding the CSS\n body { margin: 0; padding: 0; background-color: #f4f4f4; font-family: Arial, sans-serif; }\n table { border-collapse: collapse; }\n .mailcontainer { width: 100%; max-width: 600px; margin: auto; background-color: #ffffff; }\n .header { background-color: #1c3f60; color: #ffffff; text-align: center; padding: 20px; }\n .body { padding: 20px; font-size: 16px; line-height: 1.6; background-color: #1c3f60; color: #7ed957; }\n .footer { background-color: #ff6100; color: #000000; text-align: center; padding: 20px; }\n .cta { background-color: #8c52ff; padding: 10px 20px; border-radius: 5px; color: #ffffff; text-decoration: none; font-weight: bold; }\n\n @media screen and (max-width: 600px) {\n .container {\n width: 100% !important;\n padding: 10px !important;\n }\n }\n \u0026lt;/style\u0026gt;\n\u0026lt;/head\u0026gt;\n\u0026lt;body\u0026gt;\n \u0026lt;table width=\u0026#x27;100%\u0026#x27; cellpadding=\u0026#x27;0\u0026#x27; cellspacing=\u0026#x27;0\u0026#x27;\u0026gt;\n \u0026lt;tr\u0026gt;\n \u0026lt;td align=\u0026#x27;center\u0026#x27;\u0026gt;\n \u0026lt;table class=\u0026#x27;container\u0026#x27; width=\u0026#x27;600\u0026#x27; cellpadding=\u0026#x27;0\u0026#x27; cellspacing=\u0026#x27;0\u0026#x27;\u0026gt;\n \u0026lt;!-- Header --\u0026gt;\n \u0026lt;tr\u0026gt;\n \u0026lt;td class=\u0026#x27;header\u0026#x27;\u0026gt;\n \u0026lt;h1\u0026gt;Your order is confirmed\u0026lt;/h1\u0026gt;\n \u0026lt;/td\u0026gt;\n \u0026lt;/tr\u0026gt;\n \u0026lt;!-- Body --\u0026gt;\n \u0026lt;tr\u0026gt;\n \u0026lt;td class=\u0026#x27;body\u0026#x27;\u0026gt;\n \u0026lt;p\u0026gt;The estimated delivery date is 22nd August 2024.\u0026lt;/p\u0026gt;\n \u0026lt;p style=\u0026#x27;font-size: 16px; color: blue;\u0026#x27;\u0026gt;Styled paragraph.\u0026lt;/p\u0026gt;\n \u0026lt;table width=\u0026#x27;100%\u0026#x27; cellpadding=\u0026#x27;0\u0026#x27; cellspacing=\u0026#x27;0\u0026#x27; style=\u0026#x27;border: 1px solid #1c3f60; padding: 20px;\u0026#x27;\u0026gt;\n \u0026lt;tr\u0026gt;\n \u0026lt;td align=\u0026#x27;center\u0026#x27;\u0026gt;\n \u0026lt;h1 style=\u0026#x27;color: #7ed957;\u0026#x27;\u0026gt;Hi, Jane!\u0026lt;/h1\u0026gt; \n \u0026lt;p style=\u0026#x27;font-size: 16px; color: #ffde59;\u0026#x27;\u0026gt;\n Thank you for being our valuable customer!\n \u0026lt;/p\u0026gt;\n \u0026lt;/td\u0026gt;\n \u0026lt;/tr\u0026gt;\n \u0026lt;/table\u0026gt;\n \u0026lt;table cellpadding=\u0026#x27;0\u0026#x27; cellspacing=\u0026#x27;0\u0026#x27; style=\u0026#x27;margin: auto;\u0026#x27;\u0026gt;\n \u0026lt;tr\u0026gt;\n \u0026lt;td align=\u0026#x27;center\u0026#x27; style=\u0026#x27;background-color: #8c52ff; padding: 10px 20px; border-radius: 5px;\u0026#x27;\u0026gt;\n \u0026lt;a href=\u0026#x27;https://www.mydomain.com\u0026#x27; target=\u0026#x27;_blank\u0026#x27; rel=\u0026#x27;noopener noreferrer\u0026#x27; style=\u0026#x27;color: #ffffff; text-decoration: none; font-weight: bold;\u0026#x27;\u0026gt;Get a 30-day free trial\u0026lt;/a\u0026gt;\n \u0026lt;/td\u0026gt;\n \u0026lt;/tr\u0026gt;\n \u0026lt;/table\u0026gt;\n \u0026lt;/td\u0026gt;\n \u0026lt;/tr\u0026gt;\n \u0026lt;!-- Footer --\u0026gt;\n \u0026lt;tr\u0026gt;\n \u0026lt;td style=\u0026#x27;background-color: #ff6100; color: #000000; text-align: center; padding: 20px;\u0026#x27;\u0026gt;\n \u0026lt;p\u0026gt;For additional help, contact us at support@domain.com\u0026lt;/p\u0026gt;\n \u0026lt;/td\u0026gt;\n \u0026lt;/tr\u0026gt;\n \u0026lt;/table\u0026gt;\n \u0026lt;/td\u0026gt;\n \u0026lt;/tr\u0026gt;\n \u0026lt;/table\u0026gt;\n\u0026lt;/body\u0026gt;\n\n\u0026lt;/html\u0026gt;\n\u0026quot;\u0026quot;\u0026quot;\u003c/span\u003e\n\ntemplate1 = Template(html_emailtemp)\nhtml1 = template1.render(name=\u003cspan class=\"hljs-string\"\u003e\u0026quot;Jon Doe\u0026quot;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-comment\"\u003e# Attach your MIMEText objects for HTML\u003c/span\u003e\n\nmessage = MIMEText(html1, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;html\u0026#x27;\u003c/span\u003e)\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Subject\u0026#x27;\u003c/span\u003e] = subject\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;From\u0026#x27;\u003c/span\u003e] = sender\nmessage[\u003cspan class=\"hljs-string\"\u003e\u0026#x27;To\u0026#x27;\u003c/span\u003e] = recipient\n\n\u003cspan class=\"hljs-comment\"\u003e# Send the HTML email\u003c/span\u003e\n\n\u003cspan class=\"hljs-keyword\"\u003ewith\u003c/span\u003e smtplib.SMTP_SSL(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;smtp.gmail.com\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e465\u003c/span\u003e) \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e server:\n server.login(username, password)\n server.sendmail(sender, recipient, message.as_string())\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eExplanation:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003esender\u003c/code\u003e: The sender's email address\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003erecipient\u003c/code\u003e: The recipient's email address\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003efrom email.mime.text import MIMEText\u003c/code\u003e: This is used to import the class MIMEText, enabling you to attach your HTML template in the email.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esmtplib.SMTP_SSL('smtp.gmail.com', 465) as server:\u003c/code\u003e: This establishes a connection with your email provider's (Gmail's) SMTP server using port 465. If you are using another SMTP provider, use their domain name, such as smtp.domain.com, with an appropriate port number. The connection is secured with SSL.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eserver.login(username, password)\u003c/code\u003e: This function allows you to log in to the email server using your username and password.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eserver.sendemail(sender, recipient, message.as_string())\u003c/code\u003e: This command sends the HTML email.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"testing\"\u003eTesting\u003c/h3\u003e\n\u003cp\u003eBefore sending your HTML email, test it to understand how different email clients render CSS and HTML. Testing tools like Email on Acid, Litmus, etc. can assist you.\u003c/p\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eTo build custom email templates with HTML and CSS in Python, follow the above instructions. First, begin structuring your HTML email template, style emails with CSS, and then send them to your recipients. Always check your email template's compatibility with different email clients and ensure to keep your HTML simple using tables. Adding an \u003ca href=\"https://stackabuse.com/python-specific-design-patterns/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eemail link in HTML\u003c/a\u003e will also allow you to compose an email automatically in your email client and send it to a specific email address.\u003c/p\u003e\n","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"read_time_min":19,"published_at":1724180684567,"created_at":1724173213441,"updated_at":1724257697915,"tags":[{"id":9,"name":"python","slug":"python","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1431358631000,"updated_at":1431358631000,"_pivot_content_id":2132,"_pivot_tag_id":9,"_pivot_sort_order":0},{"id":108,"name":"email","slug":"email","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1538359651000,"updated_at":1538359651000,"_pivot_content_id":2132,"_pivot_tag_id":108,"_pivot_sort_order":1}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2132,"_pivot_user_id":1,"_pivot_role":"editor","_pivot_sort_order":0},{"id":26126,"name":"Ivan Djuric","slug":"ivan","role_id":null,"img_profile":"https://s3.amazonaws.com/s3.stackabuse.com/media/users/b9227b402289ab251e04427e15e2d4f6.jpg","img_cover":null,"bio_html":"\u003cp\u003eI’m a Technical Content Writer with 5 years of background covering email-related topics in tight collaboration with software engineers and email marketers. I just love to research and share actionable insights with you about email sending, testing, deliverability improvements, and more. Happy to be your guide in the world of emails!\u003c/p\u003e\n","website":null,"location":null,"facebook":null,"twitter":null,"github":null,"created_at":1724257087195,"updated_at":1724257803744,"role":"contributor","_pivot_content_id":2132,"_pivot_user_id":26126,"_pivot_role":"author","_pivot_sort_order":1}],"_pivot_user_id":1,"_pivot_content_id":2132},{"id":2129,"title":"Gracefully Handling Third Party API Failures","slug":"gracefully-handling-third-party-api-failures","body_html":"\u003cp\u003eSoftware isn't what it used to be. That's not necessarily a bad thing, but it does come with its own set of challenges. In the past, if you wanted to build a feature, you'd have to build it from scratch, \u003cstrong\u003ewithout AI\u003c/strong\u003e 😱 Fast forward from the dark ages of just a few years ago, and we have a plethora of third party APIs at our disposal that can help us build features faster and more efficiently than before.\u003c/p\u003e\n\u003ch2 id=\"theprevalenceofthirdpartyapis\"\u003eThe Prevalence of Third Party APIs\u003c/h2\u003e\n\u003cp\u003eAs software developers, we often go back and forth between \u0026quot;I can build all of this myself\u0026quot; and \u0026quot;I need to outsource \u003cem\u003eeverything\u003c/em\u003e\u0026quot; so we can deploy our app faster. Nowadays there really seems to be an API for just about everything:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAuth\u003c/li\u003e\n\u003cli\u003ePayments\u003c/li\u003e\n\u003cli\u003eAI\u003c/li\u003e\n\u003cli\u003eSMS\u003c/li\u003e\n\u003cli\u003eInfrastructure\u003c/li\u003e\n\u003cli\u003eWeather\u003c/li\u003e\n\u003cli\u003eTranslation\u003c/li\u003e\n\u003cli\u003eThe list goes on... (and on...)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIf it's something your app needs, there's a good chance there's an API for it. In fact, Rapid API, a popular API marketplace/hub, has over 50,000 APIs listed on their platform. 283 of those are for weather alone! There are even 4 different APIs for \u003cem\u003eDisc Golf\u003c/em\u003e 😳 But I digress...\u003c/p\u003e\n\u003cp\u003eWhile we've done a great job of abstracting away the complexity of building apps and new features, we've also introduced a new set of problems: what happens when the API goes down?\u003c/p\u003e\n\u003ch2 id=\"handlingapidowntime\"\u003eHandling API Down Time\u003c/h2\u003e\n\u003cp\u003eWhen you're building an app that relies on third party dependencies, you're essentially building a distributed system. You have your app, and you have the external resource you're calling. If the API goes down, your app is likely to be affected. How much it's affected depends on what the API does for you. So how do you handle this? There are a few strategies you can employ:\u003c/p\u003e\n\u003ch3 id=\"retrymechanism\"\u003eRetry Mechanism\u003c/h3\u003e\n\u003cp\u003eOne of the simplest ways to handle an API failure is to just retry the request. After all, this is the low-hanging fruit of error handling. If the API call failed, it might just be a busy server that dropped your request. If you retry it, it might go through. This is a good strategy for transient errors\u003c/p\u003e\n\u003cp\u003eOpenAI's APIs, for example, are extremely popular and have a limited number of GPUs to service requests. So it's highly likely that delaying and retrying a few seconds later will work (depending on the error they sent back, of course).\u003c/p\u003e\n\u003cp\u003eThis can be done in a few different ways:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eExponential backoff: Retry the request after a certain amount of time, and increase that time exponentially with each retry.\u003c/li\u003e\n\u003cli\u003eFixed backoff: Retry the request after a certain amount of time, and keep that time constant with each retry.\u003c/li\u003e\n\u003cli\u003eRandom backoff: Retry the request after a random amount of time, and keep that time random with each retry.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eYou can also try varying the number of retries you attempt. Each of these configurations will depend on the API you're calling and if there are other strategies in place to handle the error.\u003c/p\u003e\n\u003cp\u003eHere is a very simple retry mechanism in JavaScript:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e delay = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003ems\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003ePromise\u003c/span\u003e(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003efulfill\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-built_in\"\u003esetTimeout\u003c/span\u003e(fulfill, ms);\n });\n};\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e callWithRetry = \u003cspan class=\"hljs-keyword\"\u003easync\u003c/span\u003e (fn, {validate, retries=\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-attr\"\u003edelay\u003c/span\u003e: delayMs=\u003cspan class=\"hljs-number\"\u003e2000\u003c/span\u003e, logger}={}) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003elet\u003c/span\u003e res = \u003cspan class=\"hljs-literal\"\u003enull\u003c/span\u003e;\n \u003cspan class=\"hljs-keyword\"\u003elet\u003c/span\u003e err = \u003cspan class=\"hljs-literal\"\u003enull\u003c/span\u003e;\n \u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e (\u003cspan class=\"hljs-keyword\"\u003elet\u003c/span\u003e i = \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e; i \u0026lt; retries; i++) {\n \u003cspan class=\"hljs-keyword\"\u003etry\u003c/span\u003e {\n res = \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e fn();\n \u003cspan class=\"hljs-keyword\"\u003ebreak\u003c/span\u003e;\n } \u003cspan class=\"hljs-keyword\"\u003ecatch\u003c/span\u003e (e) {\n err = e;\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (!validate || validate(e)) {\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (logger) logger.error(\u003cspan class=\"hljs-string\"\u003e`Error calling fn: \u003cspan class=\"hljs-subst\"\u003e${e.message}\u003c/span\u003e (retry \u003cspan class=\"hljs-subst\"\u003e${i + \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e}\u003c/span\u003e of \u003cspan class=\"hljs-subst\"\u003e${retries}\u003c/span\u003e)`\u003c/span\u003e);\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (i \u0026lt; retries - \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e) \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e delay(delayMs);\n }\n }\n }\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (err) \u003cspan class=\"hljs-keyword\"\u003ethrow\u003c/span\u003e err;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e res;\n};\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf the API you're accessing has a rate limit and your calls have exceeded that limit, then employing a retry strategy can be a good way to handle that. To tell if you're being rate limited, you can check the response headers for one or more of the following:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eX-RateLimit-Limit\u003c/code\u003e: The maximum number of requests you can make in a given time period.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eX-RateLimit-Remaining\u003c/code\u003e: The number of requests you have left in the current time period.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eX-RateLimit-Reset\u003c/code\u003e: The time at which the rate limit will reset.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eBut the retry strategy is not a silver bullet, of course. If the API is down for an extended period of time, you'll just be hammering it with requests that will never go through, getting you nowhere. So what else can you do?\u003c/p\u003e\n\u003ch3 id=\"circuitbreakerpattern\"\u003eCircuit Breaker Pattern\u003c/h3\u003e\n\u003cp\u003eThe Circuit Breaker Pattern is a design pattern that can help you gracefully handle failures in distributed systems. It's a pattern that's been around for a while, and it's still relevant today. The idea is that you have a \u0026quot;circuit breaker\u0026quot; that monitors the state of the API you're calling. If the API is down, the circuit breaker will \u0026quot;trip\u0026quot; and stop sending requests to the API. This can help prevent your app from wasting time and resources on a service that's not available.\u003c/p\u003e\n\u003cp\u003eWhen the circuit breaker trips, you can do a few things:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eReturn a cached response\u003c/li\u003e\n\u003cli\u003eReturn a default response\u003c/li\u003e\n\u003cli\u003eReturn an error\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eHere's a simple implementation of a circuit breaker in JavaScript:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eCircuitBreaker\u003c/span\u003e \u003c/span\u003e{\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-title\"\u003econstructor\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003e{failureThreshold=\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, successThreshold=\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e, timeout=\u003cspan class=\"hljs-number\"\u003e5000\u003c/span\u003e}={}\u003c/span\u003e)\u003c/span\u003e {\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.failureThreshold = failureThreshold;\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.successThreshold = successThreshold;\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.timeout = timeout;\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.state = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;CLOSED\u0026#x27;\u003c/span\u003e;\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.failureCount = \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e;\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.successCount = \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e;\n }\n\n \u003cspan class=\"hljs-keyword\"\u003easync\u003c/span\u003e \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-title\"\u003ecall\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003efn\u003c/span\u003e)\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (\u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.state === \u003cspan class=\"hljs-string\"\u003e\u0026#x27;OPEN\u0026#x27;\u003c/span\u003e) {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.handleOpenState();\n }\n\n \u003cspan class=\"hljs-keyword\"\u003etry\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e res = \u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e fn();\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.successCount++;\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (\u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.successCount \u0026gt;= \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.successThreshold) {\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.successCount = \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e;\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.failureCount = \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e;\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.state = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;CLOSED\u0026#x27;\u003c/span\u003e;\n }\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e res;\n } \u003cspan class=\"hljs-keyword\"\u003ecatch\u003c/span\u003e (e) {\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.failureCount++;\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (\u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.failureCount \u0026gt;= \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.failureThreshold) {\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.state = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;OPEN\u0026#x27;\u003c/span\u003e;\n \u003cspan class=\"hljs-built_in\"\u003esetTimeout\u003c/span\u003e(\u003cspan class=\"hljs-function\"\u003e() =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.state = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;HALF_OPEN\u0026#x27;\u003c/span\u003e;\n }, \u003cspan class=\"hljs-built_in\"\u003ethis\u003c/span\u003e.timeout);\n }\n \u003cspan class=\"hljs-keyword\"\u003ethrow\u003c/span\u003e e;\n }\n }\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-title\"\u003ehandleOpenState\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003e\u003c/span\u003e)\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003ethrow\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eError\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Circuit is open\u0026#x27;\u003c/span\u003e);\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this case, the open state will return a generic error, but you could easily modify it to return a cached response or a default response.\u003c/p\u003e\n\u003ch3 id=\"gracefuldegradation\"\u003eGraceful Degradation\u003c/h3\u003e\n\u003cp\u003eRegardless of whether or not you use the previous error handling strategies, the most important thing is to ensure that your app can still function when the API is down and communicate issues with the user. This is known as \u0026quot;graceful degradation.\u0026quot; This means that your app should still be able to provide some level of service to the user, even if the API is down, and even if that just means you return an error to the end caller.\u003c/p\u003e\n\u003cp\u003eWhether your service itself is an API, web app, mobile device, or something else, you should always have a fallback plan in place for when your third party dependencies are down. This could be as simple as returning a 503 status code, or as complex as returning a cached response, a default response, or a detailed error.\u003c/p\u003e\n\u003cp\u003eBoth the UI and transport layer should communicate these issues to the user so they can take action as necessary. What's more frustrating as an end user? An app that doesn't work and doesn't tell you why, or an app that doesn't work but tells you why and what you can do about it?\u003c/p\u003e\n\u003ch2 id=\"monitoringandalerting\"\u003eMonitoring and Alerting\u003c/h2\u003e\n\u003cp\u003eFinally, it's important to monitor the health of the APIs you're calling. If you're using a third party API, you're at the mercy of that API's uptime. If it goes down, you need to know about it. You can use a service like \u003ca target=\"_blank\" rel=\"noopener\" href=\"https://pingbot.dev/\"\u003ePing Bot\u003c/a\u003e to monitor the health of the API and alert you if it goes down.\u003c/p\u003e\n\u003cp\u003eHandling all of the error cases of a downed API can be difficult to do in testing and integration, so reviewing an API's past incidents and monitoring current incidents can help you understand both how reliable the resource is and where your app may fall short in handling those errors.\u003c/p\u003e\n\u003cimg alt=\"OpenAI's uptime and recent incidents\" src=\"https://s3.stackabuse.com/media/articles/gracefully-handling-third-party-api-failures.png\" /\u003e\n\u003cp\u003eWith Ping Bot's \u003ca target=\"_blank\" rel=\"noopener\" href=\"https://pingbot.dev/features/monitoring\"\u003euptime monitoring\u003c/a\u003e, you can see the current status and also look back at the historical uptime and details of your dependency's downtime, which can help you determine why your own app may have failed.\u003c/p\u003e\n\u003cp\u003eYou can also set up alerts to notify you when the API goes down, so you can take action as soon as it happens. Have Ping Bot send alerts to your email, Slack, Discord, or webhook to automatically alert your team and servers when an API goes down.\u003c/p\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eThird party APIs are a great way to build features quickly and efficiently, but they come with their own set of challenges. When the API goes down, your app is likely to be affected. By employing a retry mechanism, circuit breaker pattern, and graceful degradation, you can ensure that your app can still function when the API is down. Monitoring and alerting can help you stay on top of the health of the APIs you're calling, so you can take action as soon as they go down.\u003c/p\u003e\n","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"read_time_min":12,"published_at":1718311859058,"created_at":1718311619738,"updated_at":1718312121086,"tags":[{"id":85,"name":"devops","slug":"devops","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1516885886000,"updated_at":1516885886000,"_pivot_content_id":2129,"_pivot_tag_id":85,"_pivot_sort_order":0},{"id":156,"name":"api","slug":"api","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1575060469000,"updated_at":1575060469000,"_pivot_content_id":2129,"_pivot_tag_id":156,"_pivot_sort_order":1}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2129,"_pivot_user_id":1,"_pivot_role":"author","_pivot_sort_order":1}],"_pivot_user_id":1,"_pivot_content_id":2129},{"id":2128,"title":"Simplify Regular Expressions with RegExpBuilderJS","slug":"simplify-regular-expressions-with-regexpbuilderjs","body_html":"\u003cp\u003eRegular expressions are on of the most powerful tools in a developer's toolkit. But let's be honest, regex kind of sucks to write. Not only is it hard to write, but it's also hard to read and debug too. So how can we make it easier to use?\u003c/p\u003e\n\u003cp\u003eIn its traditional form, regex defines powerful string patterns in a very compact statement. One trade-off we can make is to use a more verbose syntax that is easier to read and write. This is the purpose of a package like \u003ccode\u003eregexpbuilderjs\u003c/code\u003e.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003eThe \u003ccode\u003eregexpbuilderjs\u003c/code\u003e package is actually a port of the popular PHP package, \u003ca rel=\"nofollow noreferrer\" target=\"_blank\" href=\"https://github.com/gherkins/regexpbuilderphp/wiki#eitherfindregexpbuilder\"\u003eregexpbuilderphp\u003c/a\u003e. The \u003ccode\u003eregexpbuilderphp\u003c/code\u003e package itself is a port of an old JS package, \u003ccode\u003eregexpbuilder\u003c/code\u003e, which now seems to be gone. This new package is meant to continue the work of the original \u003ccode\u003eregexpbuilder\u003c/code\u003e package.\u003c/p\u003e\n\u003cp\u003eAll credit goes to \u003ca rel=\"nofollow noopener\" target=\"_blank\" href=\"https://github.com/thebinarysearchtree\"\u003eAndrew Jones\u003c/a\u003e for creating the original JS version and \u003ca rel=\"nofollow noopener\" target=\"_blank\" href=\"https://github.com/gherkins\"\u003eMax Girkens\u003c/a\u003e for the PHP port.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch2 id=\"installation\"\u003eInstallation\u003c/h2\u003e\n\u003cp\u003eTo install the package, you can use npm:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-meta\"\u003e$\u003c/span\u003e\u003cspan class=\"bash\"\u003e npm install regexpbuilderjs\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"usage\"\u003eUsage\u003c/h2\u003e\n\u003cp\u003eHere's a simple example of how you can use the package:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e RegExpBuilder = \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;regexpbuilderjs\u0026#x27;\u003c/span\u003e);\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e builder = \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e RegExpBuilder();\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e regEx = builder\n .startOfLine()\n .exactly(\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e)\n .of(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;S\u0026#x27;\u003c/span\u003e)\n .getRegExp();\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow let's break this down a bit. The \u003ccode\u003eRegExpBuilder\u003c/code\u003e class is the main class that you'll be using to build your regular expressions. You can start by creating a new instance of this class and chain methods together to create your regex:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003estartOfLine()\u003c/code\u003e: This method adds the \u003ccode\u003e^\u003c/code\u003e character to the regex, which matches the start of a line.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eexactly(1)\u003c/code\u003e: This method adds the \u003ccode\u003e{1}\u003c/code\u003e quantifier to the regex, which matches exactly one occurrence of a given character or group.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eof('S')\u003c/code\u003e: This method adds the \u003ccode\u003eS\u003c/code\u003e character to the regex.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003egetRegExp()\u003c/code\u003e: This method returns the final \u003ccode\u003eRegExp\u003c/code\u003e object that you can use to match strings.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWith this, you can match strings like \u0026quot;Scott\u0026quot;, \u0026quot;Soccer\u0026quot;, or \u0026quot;S418401\u0026quot;.\u003c/p\u003e\n\u003cp\u003eThis is great and all, but this is probably a regex string you could come up with on your own and not struggle too much to read. So now let's see a more complex example:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e builder = \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e RegExpBuilder();\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e regExp = builder\n .startOfInput()\n .exactly(\u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e).digits()\n .then(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;_\u0026#x27;\u003c/span\u003e)\n .exactly(\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e).digits()\n .then(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;_\u0026#x27;\u003c/span\u003e)\n .min(\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e).max(\u003cspan class=\"hljs-number\"\u003e10\u003c/span\u003e).letters()\n .then(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;.\u0026#x27;\u003c/span\u003e)\n .anyOf([\u003cspan class=\"hljs-string\"\u003e\u0026#x27;png\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;jpg\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;gif\u0026#x27;\u003c/span\u003e])\n .endOfInput()\n .getRegExp();\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis regex is meant to match filenames, which may look like:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e2020_10_hund.jpg\u003c/li\u003e\n\u003cli\u003e2030_11_katze.png\u003c/li\u003e\n\u003cli\u003e4000_99_maus.gif\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSome interesting parts of this regex is that we can specify type of strings (i.e. \u003ccode\u003edigits()\u003c/code\u003e), min and max occurrences of a character or group (i.e. \u003ccode\u003emin(3).max(10)\u003c/code\u003e), and a list of possible values (i.e. \u003ccode\u003eanyOf(['png', 'jpg', 'gif'])\u003c/code\u003e).\u003c/p\u003e\n\u003cp\u003eFor a full list of methods you can use to build your regex, you can check out the \u003ca rel=\"noopener\" target=\"_blank\" href=\"https://github.com/scottwrobinson/regexpbuilderjs?tab=readme-ov-file#documentation\"\u003edocumentation\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThis is just a small taste of what you can do with \u003ccode\u003eregexpbuilderjs\u003c/code\u003e. The package is very powerful and can help you build complex regular expressions in a more readable and maintainable way.\u003c/p\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eComments, questions, and suggestions are always welcome! If you have any feedback on how this could work better, feel free to \u003ca target=\"_blank\" href=\"https://twitter.com/ScottWRobinson\"\u003ereach out on X\u003c/a\u003e. In the meantime, you can check out the repo on \u003ca target=\"_blank\" href=\"https://github.com/scottwrobinson/regexpbuilderjs\"\u003eGitHub\u003c/a\u003e and give it a star while you're at it.\u003c/p\u003e\n","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"read_time_min":5,"published_at":1717699045389,"created_at":1717698906805,"updated_at":1717699130504,"tags":[{"id":39,"name":"regex","slug":"regex","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1431360680000,"updated_at":1431360680000,"_pivot_content_id":2128,"_pivot_tag_id":39,"_pivot_sort_order":0},{"id":45,"name":"javascript","slug":"javascript","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1432589001000,"updated_at":1432589001000,"_pivot_content_id":2128,"_pivot_tag_id":45,"_pivot_sort_order":1},{"id":48,"name":"node","slug":"node","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1437348872000,"updated_at":1437348872000,"_pivot_content_id":2128,"_pivot_tag_id":48,"_pivot_sort_order":2}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2128,"_pivot_user_id":1,"_pivot_role":"author","_pivot_sort_order":1}],"_pivot_user_id":1,"_pivot_content_id":2128},{"id":2126,"title":"Guide to Strings in Python","slug":"guide-to-strings-in-python","body_html":"\u003cp\u003e\u003cem\u003eA string in Python is a sequence of characters\u003c/em\u003e. These characters can be letters, numbers, symbols, or whitespace, and they are enclosed within quotes. Python supports both single (\u003ccode\u003e' '\u003c/code\u003e) and double (\u003ccode\u003e\u0026quot; \u0026quot;\u003c/code\u003e) quotes to define a string, providing flexibility based on the coder's preference or specific requirements of the application.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eMore specifically, strings in Python are arrays of bytes representing Unicode characters.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cem\u003eCreating a string\u003c/em\u003e is pretty straightforward. You can assign a sequence of characters to a variable, and Python treats it as a string. For example:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003emy_string = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, World!\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis creates a new string containing \u0026quot;Hello, World!\u0026quot;. Once a string is created, you can access its elements using \u003cem\u003eindexing\u003c/em\u003e (same as accessing elements of a list) and perform various operations like concatenation (joining two strings) and replication (repeating a string a certain number of times).\u003c/p\u003e\n\u003cp\u003eHowever, it's important to remember that \u003cstrong\u003estrings in Python are immutable\u003c/strong\u003e. This immutability means that \u003cem\u003eonce you create a string, you cannot change its content\u003c/em\u003e. Attempting to alter an individual character in a string will result in an error. While this might seem like a limitation at first, it has several benefits, including improved performance and reliability in Python applications. To modify a string, you would typically create a new string based on modifications of the original.\u003c/p\u003e\n\u003cp\u003ePython provides a \u003cem\u003ewealth of methods to work with strings\u003c/em\u003e, making string manipulation one of the language's strong suits. These \u003cem\u003ebuilt-in methods\u003c/em\u003e allow you to perform common tasks like changing the case of a string, stripping whitespace, checking for substrings, and much more, all with simple, easy-to-understand syntax, which we'll discuss later in this article.\u003c/p\u003e\n\u003cp\u003eAs you dive deeper into Python, you'll encounter more advanced string techniques. These include \u003cem\u003eformatting strings\u003c/em\u003e for output, working with \u003cem\u003esubstrings\u003c/em\u003e, and handling special characters. Python's string formatting capabilities, especially with the introduction of \u003cem\u003ef-Strings\u003c/em\u003e in Python 3.6, allow for cleaner and more readable code. Substring operations, including slicing and finding, are essential for text analysis and manipulation.\u003c/p\u003e\n\u003cp\u003eMoreover, strings play nicely with other data types in Python, such as lists. You can convert a string into a list of characters, split a string based on a specific delimiter, or join a collection of strings into a single string. These operations are particularly useful when dealing with data input and output or when parsing text files.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIn this article, we'll explore these aspects of strings in Python, providing practical examples to illustrate how to effectively work with strings. By the end, you'll have a solid foundation in string manipulation, setting you up for more advanced Python programming tasks.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"basicstringoperators\"\u003eBasic String Operators\u003c/h2\u003e\n\u003cp\u003eStrings are one of the most commonly used data types in Python, employed in diverse scenarios from user input processing to data manipulation. This section will explore the fundamental operations you can perform with strings in Python.\u003c/p\u003e\n\u003ch3 id=\"creatingstrings\"\u003eCreating Strings\u003c/h3\u003e\n\u003cp\u003eIn Python, you can create strings by enclosing a sequence of characters within single, double, or even triple quotes (for multiline strings). For example, \u003ccode\u003esimple_string = 'Hello'\u003c/code\u003e and \u003ccode\u003eanother_string = \u0026quot;World\u0026quot;\u003c/code\u003e are both valid string declarations. Triple quotes, using \u003ccode\u003e'''\u003c/code\u003e or \u003ccode\u003e\u0026quot;\u0026quot;\u0026quot;\u003c/code\u003e, allow strings to span multiple lines, which is particularly useful for complex strings or documentation.\u003c/p\u003e\n\u003cp\u003eThe \u003cem\u003esimplest way\u003c/em\u003e to create a string in Python is by \u003cstrong\u003eenclosing characters in single (\u003ccode\u003e'\u003c/code\u003e) or double (\u003ccode\u003e\u0026quot;\u003c/code\u003e) quotes\u003c/strong\u003e.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Python treats single and double quotes identically\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eThis method is straightforward and is commonly used for creating short, uncomplicated strings:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Using single quotes\u003c/span\u003e\ngreeting = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;Hello, world!\u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Using double quotes\u003c/span\u003e\ntitle = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python Programming\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFor strings that \u003cem\u003espan multiple lines\u003c/em\u003e, \u003cstrong\u003etriple quotes\u003c/strong\u003e (\u003ccode\u003e'''\u003c/code\u003e or \u003ccode\u003e\u0026quot;\u0026quot;\u0026quot;\u003c/code\u003e) are the perfect tool. They allow the string to extend over several lines, preserving line breaks and white spaces:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Using triple quotes\u003c/span\u003e\nmulti_line_string = \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026quot;\u0026quot;This is a\nmulti-line string\nin Python.\u0026quot;\u0026quot;\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSometimes, you might need to \u003cem\u003einclude special characters in your strings\u003c/em\u003e, like newlines (\u003ccode\u003e\\n\u003c/code\u003e), tabs (\u003ccode\u003e\\t\u003c/code\u003e), or even a quote character. This is where \u003cstrong\u003eescape characters\u003c/strong\u003e come into play, allowing you to include these special characters in your strings:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# String with escape characters\u003c/span\u003e\nescaped_string = \u003cspan class=\"hljs-string\"\u003e\u0026quot;He said, \\\u0026quot;Python is amazing!\\\u0026quot;\\nAnd I couldn\u0026#x27;t agree more.\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003ePrinting the \u003ccode\u003eescaped_string\u003c/code\u003e will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eHe said, \u0026quot;Python is amazing!\u0026quot;\nAnd I couldn\u0026#x27;t agree more.\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"accessingandindexingstrings\"\u003eAccessing and Indexing Strings\u003c/h3\u003e\n\u003cp\u003eOnce a string is created, Python allows you to access its individual characters using indexing. Each character in a string has an index, starting from 0 for the first character.\u003c/p\u003e\n\u003cp\u003eFor instance, in the string \u003ccode\u003es = \u0026quot;Python\u0026quot;\u003c/code\u003e, the character at index 0 is 'P'. Python also supports negative indexing, where -1 refers to the last character, -2 to the second-last, and so on. This feature makes it easy to access the string from the end.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Python does not have a character data type. Instead, a single character is simply a string with a length of one.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch4 id=\"accessingcharactersusingindexing\"\u003eAccessing Characters Using Indexing\u003c/h4\u003e\n\u003cp\u003eAs we stated above, the indexing starts at 0 for the first character. You can access individual characters in a string by using square brackets \u003ccode\u003e[]\u003c/code\u003e along with the index:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Example string\u003c/span\u003e\nstring = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Stack Abuse\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Accessing the first character\u003c/span\u003e\nfirst_char = string[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;S\u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Accessing the third character\u003c/span\u003e\nthird_char = string[\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;t\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"negativeindexing\"\u003eNegative Indexing\u003c/h4\u003e\n\u003cp\u003ePython also supports negative indexing. In this scheme, -1 refers to the last character, -2 to the second last, and so on. This is useful for accessing characters from the end of the string:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Accessing the last character\u003c/span\u003e\nlast_char = string[-\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;e\u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Accessing the second last character\u003c/span\u003e\nsecond_last_char = string[-\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;s\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"stringconcatenationandreplication\"\u003eString Concatenation and Replication\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eConcatenation\u003c/strong\u003e is the process of \u003cem\u003ejoining two or more strings together\u003c/em\u003e. In Python, this is most commonly done using the \u003ccode\u003e+\u003c/code\u003e operator. When you use \u003ccode\u003e+\u003c/code\u003e between strings, Python returns a new string that is a combination of the operands:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Example of string concatenation\u003c/span\u003e\nfirst_name = \u003cspan class=\"hljs-string\"\u003e\u0026quot;John\u0026quot;\u003c/span\u003e\nlast_name = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Doe\u0026quot;\u003c/span\u003e\nfull_name = first_name + \u003cspan class=\"hljs-string\"\u003e\u0026quot; \u0026quot;\u003c/span\u003e + last_name \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;John Doe\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e The \u003ccode\u003e+\u003c/code\u003e operator can only be used with other strings. Attempting to concatenate a string with a non-string type (like an integer or a list) will result in a \u003ccode\u003eTypeError\u003c/code\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eFor a more robust solution, especially when dealing with different data types, you can use the \u003ccode\u003estr.join()\u003c/code\u003e method or formatted string literals (f-strings):\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Using join() method\u003c/span\u003e\nwords = [\u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;world\u0026quot;\u003c/span\u003e]\nsentence = \u003cspan class=\"hljs-string\"\u003e\u0026quot; \u0026quot;\u003c/span\u003e.join(words) \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;Hello world\u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Using an f-string\u003c/span\u003e\nage = \u003cspan class=\"hljs-number\"\u003e30\u003c/span\u003e\ngreeting = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;I am \u003cspan class=\"hljs-subst\"\u003e{age}\u003c/span\u003e years old.\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;I am 30 years old.\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e We'll discuss these methods in more details later in this article.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003e\u003cstrong\u003eReplication\u003c/strong\u003e, on the other hand, is another useful operation in Python. It allows you to \u003cem\u003erepeat a string a specified number of times\u003c/em\u003e. This is achieved using the \u003ccode\u003e*\u003c/code\u003e operator. The operand on the left is the string to be repeated, and the operand on the right is the number of times it should be repeated:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Replicating a string\u003c/span\u003e\nlaugh = \u003cspan class=\"hljs-string\"\u003e\u0026quot;ha\u0026quot;\u003c/span\u003e\nrepeated_laugh = laugh * \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;hahaha\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eString replication is particularly useful when you need to create a string with a repeating pattern. It’s a concise way to produce long strings without having to type them out manually.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e While concatenating or replicating strings with operators like \u003ccode\u003e+\u003c/code\u003e and \u003ccode\u003e*\u003c/code\u003e is convenient for small-scale operations, it’s important to be aware of \u003cem\u003eperformance implications\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003eFor concatenating a \u003cem\u003elarge number of strings\u003c/em\u003e, using \u003ccode\u003ejoin()\u003c/code\u003e is generally \u003cem\u003emore efficient\u003c/em\u003e as it allocates memory for the new string only once.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"slicingstrings\"\u003eSlicing Strings\u003c/h3\u003e\n\u003cp\u003eSlicing is a powerful feature in Python that allows you to extract a part of a string, enabling you to obtain substrings. This section will guide you through the basics of slicing strings in Python, including its syntax and some practical examples.\u003c/p\u003e\n\u003cp\u003eThe \u003cstrong\u003eslicing syntax\u003c/strong\u003e in Python can be summarized as \u003ccode\u003e[start:stop:step]\u003c/code\u003e, where:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003estart\u003c/code\u003e is the index where the slice begins (inclusive).\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003estop\u003c/code\u003e is the index where the slice ends (exclusive).\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003estep\u003c/code\u003e is the number of indices to move forward after each iteration. If omitted, the default value is 1.\u003c/li\u003e\n\u003c/ul\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Using slicing with indices out of the string's range is safe since Python will handle it gracefully without throwing an error.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eTo put that into practice, let's take a look at an example. To slice the string \u003ccode\u003e\u0026quot;Hello, Stack Abuse!\u0026quot;\u003c/code\u003e, you specify the start and stop indices within square brackets following the string or variable name. For example, you can extract the first 5 characters by passing \u003ccode\u003e0\u003c/code\u003e as a \u003ccode\u003estart\u003c/code\u003e and \u003ccode\u003e5\u003c/code\u003e as a \u003ccode\u003estop\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, Stack Abuse!\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Extracting \u0026#x27;Hello\u0026#x27;\u003c/span\u003e\ngreeting = text[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e:\u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;Hello\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Remember that Python strings are immutable, so slicing a string creates a new string.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eIf you \u003cstrong\u003eomit the \u003ccode\u003estart\u003c/code\u003e index\u003c/strong\u003e, Python will start the slice from the beginning of the string. Similarly, \u003cstrong\u003eomitting the \u003ccode\u003estop\u003c/code\u003e index\u003c/strong\u003e will slice all the way to the end:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# From the beginning to the 7th character\u003c/span\u003e\nto_python = text[:\u003cspan class=\"hljs-number\"\u003e7\u003c/span\u003e] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;Hello, \u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Slicing from the 7th character to the end\u003c/span\u003e\nfrom_python = text[\u003cspan class=\"hljs-number\"\u003e7\u003c/span\u003e:] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;Stack Abuse!\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eYou can also use \u003cstrong\u003enegative indexing\u003c/strong\u003e here. This is particularly useful for \u003cem\u003eslicing from the end of a string\u003c/em\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Slicing the last 6 characters\u003c/span\u003e\nslice_from_end = text[-\u003cspan class=\"hljs-number\"\u003e6\u003c/span\u003e:] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;Abuse!\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eThe \u003ccode\u003estep\u003c/code\u003e parameter\u003c/strong\u003e allows you to include characters within the slice at regular intervals. This can be used for various creative purposes like string reversal:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Every second character in the string\u003c/span\u003e\nevery_second = text[::\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;Hlo tc bs!\u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Reversing a string using slicing\u003c/span\u003e\nreversed_text = text[::-\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e] \u003cspan class=\"hljs-comment\"\u003e# \u0026#x27;!esubA kcatS ,olleH\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"stringimmutability\"\u003eString Immutability\u003c/h2\u003e\n\u003cp\u003eString immutability is a fundamental concept in Python, one that has significant implications for how strings are handled and manipulated within the language.\u003c/p\u003e\n\u003ch3 id=\"whatisstringimmutability\"\u003eWhat is String Immutability?\u003c/h3\u003e\n\u003cp\u003eIn Python, strings are immutable, meaning once a string is created, it cannot be altered. This might seem counterintuitive, especially for those coming from languages where string modification is common. In Python, when we think we are modifying a string, what we are actually doing is creating a new string.\u003c/p\u003e\n\u003cp\u003eFor example, consider the following scenario:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003es = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello\u0026quot;\u003c/span\u003e\ns[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e] = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Y\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAttempting to execute this code will result in a \u003ccode\u003eTypeError\u003c/code\u003e because it tries to change an element of the string, which is not allowed due to immutability.\u003c/p\u003e\n\u003ch3 id=\"whyarestringsimmutable\"\u003eWhy are Strings Immutable?\u003c/h3\u003e\n\u003cp\u003eThe immutability of strings in Python offers several advantages:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSecurity:\u003c/strong\u003e Since strings cannot be changed, they are \u003cem\u003esafe from being altered through unintended side-effects\u003c/em\u003e, which is crucial when strings are used to handle things like database queries or system commands.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePerformance:\u003c/strong\u003e Immutability allows Python to make \u003cem\u003eoptimizations under-the-hood\u003c/em\u003e. Since a string cannot change, Python can allocate memory more efficiently and perform optimizations related to memory management.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHashing:\u003c/strong\u003e Strings are often used as keys in dictionaries. Immutability makes strings hashable, maintaining the integrity of the hash value. If strings were mutable, their hash value could change, leading to incorrect behavior in data structures that rely on hashing, like dictionaries and sets.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"howtomodifyastringinpython\"\u003eHow to \u0026quot;Modify\u0026quot; a String in Python?\u003c/h3\u003e\n\u003cp\u003eSince strings cannot be altered in place, \u0026quot;modifying\u0026quot; a string usually involves \u003cem\u003ecreating a new string that reflects the desired changes\u003c/em\u003e. Here are common ways to achieve this:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eConcatenation:\u003c/strong\u003e Using \u003ccode\u003e+\u003c/code\u003e to create a new string with additional characters.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSlicing and Rebuilding:\u003c/strong\u003e Extract parts of the original string and combine them with other strings.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eString Methods:\u003c/strong\u003e Many built-in string methods return new strings with the changes applied, such as \u003ccode\u003e.replace()\u003c/code\u003e, \u003ccode\u003e.upper()\u003c/code\u003e, and \u003ccode\u003e.lower()\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor example:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003es = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello\u0026quot;\u003c/span\u003e\nnew_s = s[\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e:] \u003cspan class=\"hljs-comment\"\u003e# new_s is now \u0026#x27;ello\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, the \u003ccode\u003enew_s\u003c/code\u003e is a new string created from a substring of \u003ccode\u003es\u003c/code\u003e, whilst he original string \u003ccode\u003es\u003c/code\u003e remains unchanged.\u003c/p\u003e\n\u003ch2 id=\"commonstringmethods\"\u003eCommon String Methods\u003c/h2\u003e\n\u003cp\u003ePython's string type is equipped with a multitude of useful methods that make string manipulation effortless and intuitive. Being familiar with these methods is essential for efficient and elegant string handling. Let's take a look at a comprehensive overview of common string methods in Python:\u003c/p\u003e\n\u003ch3 id=\"upperandlowermethods\"\u003e\u003cem\u003eupper()\u003c/em\u003e and \u003cem\u003elower()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cp\u003eThese methods are used to convert all lowercase characters in a string to uppercase or lowercase, respectively.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e These method are particularly useful in scenarios where case uniformity is required, such as in case-insensitive user inputs or data normalization processes or for comparison purposes, such as in search functionalities where the case of the input should not affect the outcome.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eFor example, say you need to convert the user's input to upper case:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003euser_input = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello!\u0026quot;\u003c/span\u003e\nuppercase_input = user_input.upper()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(uppercase_input) \u003cspan class=\"hljs-comment\"\u003e# Output: HELLO!\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this example, \u003ccode\u003eupper()\u003c/code\u003e is called on the string \u003ccode\u003euser_input\u003c/code\u003e, converting all lowercase letters to uppercase, resulting in \u003ccode\u003eHELLO!\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eContrasting \u003ccode\u003eupper()\u003c/code\u003e, the \u003ccode\u003elower()\u003c/code\u003e method transforms all uppercase characters in a string to lowercase. Like \u003ccode\u003eupper()\u003c/code\u003e, it takes no parameters and returns a new string with \u003cem\u003eall uppercase characters converted to lowercase\u003c/em\u003e. For example:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003euser_input = \u003cspan class=\"hljs-string\"\u003e\u0026quot;HeLLo!\u0026quot;\u003c/span\u003e\nlowercase_input = text.lower()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(lowercase_input) \u003cspan class=\"hljs-comment\"\u003e# Output: hello!\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003elower()\u003c/code\u003e converts all uppercase letters in \u003ccode\u003etext\u003c/code\u003e to lowercase, resulting in \u003ccode\u003ehello!\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"capitalizeandtitlemethods\"\u003e\u003cem\u003ecapitalize()\u003c/em\u003e and \u003cem\u003etitle()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003ecapitalize()\u003c/code\u003e method is used to \u003cem\u003econvert the first character of a string to uppercase\u003c/em\u003e while making all other characters in the string lowercase. This method is particularly useful in standardizing the format of user-generated input, such as names or titles, ensuring that they follow a consistent capitalization pattern:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;python programming\u0026quot;\u003c/span\u003e\ncapitalized_text = text.capitalize()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(capitalized_text) \u003cspan class=\"hljs-comment\"\u003e# Output: Python programming\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this example, \u003ccode\u003ecapitalize()\u003c/code\u003e is applied to the string \u003ccode\u003etext\u003c/code\u003e. It converts the first character \u003ccode\u003ep\u003c/code\u003e to uppercase and all other characters to lowercase, resulting in \u003ccode\u003ePython programming\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eWhile \u003ccode\u003ecapitalize()\u003c/code\u003e focuses on the first character of the entire string, \u003ccode\u003etitle()\u003c/code\u003e takes it a step further by \u003cem\u003ecapitalizing the first letter of every word in the string\u003c/em\u003e. This method is particularly useful in formatting titles, headings, or any text where each word needs to start with an uppercase letter:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;python programming basics\u0026quot;\u003c/span\u003e\ntitle_text = text.title()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(title_text) \u003cspan class=\"hljs-comment\"\u003e# Output: Python Programming Basics\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003etitle()\u003c/code\u003e is used to convert the first character of each word in \u003ccode\u003etext\u003c/code\u003e to uppercase, resulting in \u003ccode\u003ePython Programming Basics\u003c/code\u003e.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e The \u003ccode\u003etitle()\u003c/code\u003e method capitalizes the first letter of \u003cstrong\u003eall words\u003c/strong\u003e in a sentence. Trying to capitalize the sentence \u0026quot;he's the best programmer\u0026quot; will result in \u0026quot;He'S The Best Programmer\u0026quot;, which is probably not what you'd want.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eTo properly convert a sentence to some standardized title case, you'd need to create a custom function!\u003c/em\u003e\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"striprstripandlstripmethods\"\u003e\u003cem\u003estrip()\u003c/em\u003e, \u003cem\u003erstrip()\u003c/em\u003e, and \u003cem\u003elstrip()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003estrip()\u003c/code\u003e method is used to \u003cem\u003eremove leading and trailing whitespaces\u003c/em\u003e from a string. This includes spaces, tabs, newlines, or any combination thereof:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot; Hello World! \u0026quot;\u003c/span\u003e\nstripped_text = text.strip()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(stripped_text) \u003cspan class=\"hljs-comment\"\u003e# Output: Hello World!\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWhile \u003ccode\u003estrip()\u003c/code\u003e removes whitespace from both ends, \u003ccode\u003erstrip()\u003c/code\u003e specifically targets the trailing end (right side) of the string:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello World! \\n\u0026quot;\u003c/span\u003e\nrstrip_text = text.rstrip()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(rstrip_text) \u003cspan class=\"hljs-comment\"\u003e# Output: Hello World!\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003erstrip()\u003c/code\u003e is used to remove the trailing spaces and the newline character from \u003ccode\u003etext\u003c/code\u003e, leaving \u003ccode\u003eHello World!\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eConversely, \u003ccode\u003elstrip()\u003c/code\u003e focuses on the leading end (left side) of the string:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot; Hello World!\u0026quot;\u003c/span\u003e\nlstrip_text = text.lstrip()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(lstrip_text) \u003cspan class=\"hljs-comment\"\u003e# Output: Hello World!\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAll-in-all, \u003ccode\u003estrip()\u003c/code\u003e, \u003ccode\u003erstrip()\u003c/code\u003e, and \u003ccode\u003elstrip()\u003c/code\u003e are powerful methods for whitespace management in Python strings. Their ability to clean and format strings by removing unwanted spaces makes them indispensable in a wide range of applications, from data cleaning to user interface design.\u003c/p\u003e\n\u003ch3 id=\"thesplitmethod\"\u003eThe \u003cem\u003esplit()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003esplit()\u003c/code\u003e method breaks up a string at each occurrence of a specified separator and returns a \u003cem\u003elist of the substrings\u003c/em\u003e. The separator can be any string, and if it's not specified, the method defaults to splitting at whitespace.\u003c/p\u003e\n\u003cp\u003eFirst of all, let's take a look at its syntax:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003estring.split(separator=\u003cspan class=\"hljs-literal\"\u003eNone\u003c/span\u003e, maxsplit=-\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, the \u003ccode\u003eseparator\u003c/code\u003e is the string at which the splits are to be made. If omitted or \u003ccode\u003eNone\u003c/code\u003e, the method splits at whitespace. On the other hand, \u003ccode\u003emaxsplit\u003c/code\u003e is an optional parameter specifying the maximum number of splits. The default value \u003ccode\u003e-1\u003c/code\u003e means no limit.\u003c/p\u003e\n\u003cp\u003eFor example, let's simply split a sentence into its words:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Computer science is fun\u0026quot;\u003c/span\u003e\nsplit_text = text.split()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(split_text) \u003cspan class=\"hljs-comment\"\u003e# Output: [\u0026#x27;Computer\u0026#x27;, \u0026#x27;science\u0026#x27;, \u0026#x27;is\u0026#x27;, \u0026#x27;fun\u0026#x27;]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAs we stated before, you can \u003cstrong\u003especify a custom separator\u003c/strong\u003e to tailor the splitting process to your specific needs. This feature is particularly useful when dealing with structured text data, like CSV files or log entries:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python,Java,C++\u0026quot;\u003c/span\u003e\nsplit_text = text.split(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;,\u0026#x27;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(split_text) \u003cspan class=\"hljs-comment\"\u003e# Output: [\u0026#x27;Python\u0026#x27;, \u0026#x27;Java\u0026#x27;, \u0026#x27;C++\u0026#x27;]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003esplit()\u003c/code\u003e uses a comma \u003ccode\u003e,\u003c/code\u003e as the separator to split the string into different programming languages.\u003c/p\u003e\n\u003ch4 id=\"controllingthenumberofsplits\"\u003eControlling the Number of Splits\u003c/h4\u003e\n\u003cp\u003eThe \u003ccode\u003emaxsplit\u003c/code\u003e parameter allows you to control the number of splits performed on the string. This can be useful when you only need to split a part of the string and want to keep the rest intact:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;one two three four\u0026quot;\u003c/span\u003e\nsplit_text = text.split(\u003cspan class=\"hljs-string\"\u003e\u0026#x27; \u0026#x27;\u003c/span\u003e, maxsplit=\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(split_text) \u003cspan class=\"hljs-comment\"\u003e# Output: [\u0026#x27;one\u0026#x27;, \u0026#x27;two\u0026#x27;, \u0026#x27;three four\u0026#x27;]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this case, \u003ccode\u003esplit()\u003c/code\u003e only performs two splits at the first two spaces, resulting in a list with three elements.\u003c/p\u003e\n\u003ch3 id=\"thejoinmethod\"\u003eThe \u003cem\u003ejoin()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eSo far, we've seen a lot of Python's extensive string manipulation capabilities. Among these, the \u003ccode\u003ejoin()\u003c/code\u003e method stands out as a particularly powerful tool for \u003cem\u003econstructing strings from iterables like lists or tuples\u003c/em\u003e.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe \u003ccode\u003ejoin()\u003c/code\u003e method is the \u003cem\u003einverse of the \u003ccode\u003esplit()\u003c/code\u003e method\u003c/em\u003e, enabling the concatenation of a sequence of strings into a single string, with a specified separator.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe \u003ccode\u003ejoin()\u003c/code\u003e method takes an iterable (like a list or tuple) as a parameter and concatenates its elements into a single string, separated by the string on which \u003ccode\u003ejoin()\u003c/code\u003e is called. It has a fairly simple syntax:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eseparator.join(iterable)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe \u003ccode\u003eseparator\u003c/code\u003e is the string that is placed between each element of the iterable during concatenation and the \u003ccode\u003eiterable\u003c/code\u003e is the collection of strings to be joined.\u003c/p\u003e\n\u003cp\u003eFor example, let's reconstruct the sentence we split in the previous section using the \u003ccode\u003esplit()\u003c/code\u003e method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003esplit_text = [\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Computer\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;science\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;is\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;fun\u0026#x27;\u003c/span\u003e]\ntext = \u003cspan class=\"hljs-string\"\u003e\u0026#x27; \u0026#x27;\u003c/span\u003e.join(words)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(sentence) \u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;Computer science is fun\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this example, the \u003ccode\u003ejoin()\u003c/code\u003e method is used with a space \u003ccode\u003e' '\u003c/code\u003e as the separator to concatenate the list of words into a sentence.\u003c/p\u003e\n\u003cp\u003eThe \u003cstrong\u003eflexibility of choosing any string as a separator\u003c/strong\u003e makes \u003ccode\u003ejoin()\u003c/code\u003e incredibly versatile. It can be used to construct strings with specific formatting, like CSV lines, or to add specific separators, like newlines or commas:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003elanguages = [\u003cspan class=\"hljs-string\"\u003e\u0026quot;Python\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;Java\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;C++\u0026quot;\u003c/span\u003e]\ncsv_line = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;,\u0026#x27;\u003c/span\u003e.join(languages)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(csv_line) \u003cspan class=\"hljs-comment\"\u003e# Output: Python,Java,C++\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003ejoin()\u003c/code\u003e is used with a comma \u003ccode\u003e,\u003c/code\u003e to create a string that resembles a line in a CSV file.\u003c/p\u003e\n\u003ch4 id=\"efficiencyofthejoin\"\u003eEfficiency of the \u003cem\u003ejoin()\u003c/em\u003e\u003c/h4\u003e\n\u003cp\u003eOne of the key advantages of \u003ccode\u003ejoin()\u003c/code\u003e is its efficiency, especially when compared to string concatenation using the \u003ccode\u003e+\u003c/code\u003e operator. When dealing with large numbers of strings, \u003ccode\u003ejoin()\u003c/code\u003e is significantly more performant and is the preferred method in Python for concatenating multiple strings.\u003c/p\u003e\n\u003ch3 id=\"thereplacemethod\"\u003eThe \u003cem\u003ereplace()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003ereplace()\u003c/code\u003e method replaces occurrences of a specified substring (\u003ccode\u003eold\u003c/code\u003e) with another substring (\u003ccode\u003enew\u003c/code\u003e). It can be used to replace all occurrences or a specified number of occurrences, making it highly adaptable for various text manipulation needs.\u003c/p\u003e\n\u003cp\u003eTake a look at its syntax:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003estring.replace(old, new[, count])\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eold\u003c/code\u003e is the substring that needs to be replaced.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003enew\u003c/code\u003e is the substring that will replace the \u003ccode\u003eold\u003c/code\u003e substring.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecount\u003c/code\u003e is an optional parameter specifying the number of replacements to be made. If omitted, all occurrences of the \u003ccode\u003eold\u003c/code\u003e substring are replaced.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor example, let's change the word \u0026quot;World\u0026quot; to \u0026quot;Stack Abuse\u0026quot; in the string \u0026quot;Hello, World\u0026quot;:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, World\u0026quot;\u003c/span\u003e\nreplaced_text = text.replace(\u003cspan class=\"hljs-string\"\u003e\u0026quot;World\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;Stack Abuse\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(replaced_text) \u003cspan class=\"hljs-comment\"\u003e# Output: Hello, Stack Abuse\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe previously mentioned \u003ccode\u003ecount\u003c/code\u003e parameter allows for more controlled replacements. It limits the number of times the \u003ccode\u003eold\u003c/code\u003e substring is replaced by the \u003ccode\u003enew\u003c/code\u003e substring:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;cats and dogs and birds and fish\u0026quot;\u003c/span\u003e\nreplaced_text = text.replace(\u003cspan class=\"hljs-string\"\u003e\u0026quot;and\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026amp;\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(replaced_text) \u003cspan class=\"hljs-comment\"\u003e# Output: cats \u0026amp; dogs \u0026amp; birds and fish\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003ereplace()\u003c/code\u003e is used to replace the first two occurrences of \u003ccode\u003e\u0026quot;and\u0026quot;\u003c/code\u003e with \u003ccode\u003e\u0026quot;\u0026amp;\u0026quot;\u003c/code\u003e, leaving the third occurrence unchanged.\u003c/p\u003e\n\u003ch3 id=\"findandrfindmethods\"\u003e\u003cem\u003efind()\u003c/em\u003e and \u003cem\u003erfind()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cp\u003eThese methods return the lowest index in the string where the substring \u003ccode\u003esub\u003c/code\u003e is found. \u003ccode\u003erfind()\u003c/code\u003e searches for the substring from the end of the string.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e These methods are particularly useful when the presence of the substring is uncertain, and you wish to \u003cem\u003eavoid handling exceptions\u003c/em\u003e. Also, the return value of \u003ccode\u003e-1\u003c/code\u003e can be used in conditional statements to execute different code paths based on the presence or absence of a substring.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003ePython's string manipulation suite includes the \u003ccode\u003efind()\u003c/code\u003e and \u003ccode\u003erfind()\u003c/code\u003e methods, which are crucial for locating substrings within a string. Similar to \u003ccode\u003eindex()\u003c/code\u003e and \u003ccode\u003erindex()\u003c/code\u003e, these methods search for a substring but differ in their response when the substring is not found. Understanding these methods is essential for tasks like text analysis, data extraction, and general string processing.\u003c/p\u003e\n\u003ch3 id=\"thefindmethod\"\u003eThe \u003ccode\u003efind()\u003c/code\u003e Method\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003efind()\u003c/code\u003e method returns \u003cem\u003ethe lowest index of the substring if it is found in the string\u003c/em\u003e. Unlike \u003ccode\u003eindex()\u003c/code\u003e, it returns \u003ccode\u003e-1\u003c/code\u003e if the substring is not found, making it a safer option for situations where the substring might not be present.\u003c/p\u003e\n\u003cp\u003eIt follows a simple syntax with one mandatory and two optional parameters:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003estring.find(sub[, start[, end]])\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003esub\u003c/code\u003e is the substring to be searched within the string.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003estart\u003c/code\u003e and \u003ccode\u003eend\u003c/code\u003e are optional parameters specifying the range within the string where the search should occur.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor example, let's take a look at a string that contains multiple instances of the substring \u0026quot;is\u0026quot;:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python is fun, just as JavaScript is\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow, let's locate the first occurrence of the substring \u003ccode\u003e\u0026quot;is\u0026quot;\u003c/code\u003e in the \u003ccode\u003etext\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003efind_position = text.find(\u003cspan class=\"hljs-string\"\u003e\u0026quot;is\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(find_position) \u003cspan class=\"hljs-comment\"\u003e# Output: 7\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this example, \u003ccode\u003efind()\u003c/code\u003e locates the substring \u003ccode\u003e\u0026quot;is\u0026quot;\u003c/code\u003e in \u003ccode\u003etext\u003c/code\u003e and returns the starting index of the first occurrence, which is \u003ccode\u003e7\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eWhile \u003ccode\u003efind()\u003c/code\u003e searches from the beginning of the string, \u003ccode\u003erfind()\u003c/code\u003e searches from the end. It returns the highest index where the specified substring is found or \u003ccode\u003e-1\u003c/code\u003e if the substring is not found:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python is fun, just as JavaScript is\u0026quot;\u003c/span\u003e\nrfind_position = text.rfind(\u003cspan class=\"hljs-string\"\u003e\u0026quot;is\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(rfind_position) \u003cspan class=\"hljs-comment\"\u003e# Output: 34\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003erfind()\u003c/code\u003e locates the last occurrence of \u003ccode\u003e\u0026quot;is\u0026quot;\u003c/code\u003e in \u003ccode\u003etext\u003c/code\u003e and returns its starting index, which is \u003ccode\u003e34\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"indexandrindexmethods\"\u003e\u003cem\u003eindex()\u003c/em\u003e and \u003cem\u003erindex()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cp\u003eThe \u003cstrong\u003e\u003ccode\u003eindex()\u003c/code\u003e method\u003c/strong\u003e is used to find the first occurrence of a specified value within a string. It's a straightforward way to locate a substring in a larger string. It has pretty much the same syntax as the \u003ccode\u003efind()\u003c/code\u003e method we discussed earlier:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003estring.index(sub[, start[, end]])\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe \u003ccode\u003esub\u003c/code\u003e ids the substring to search for in the string. The \u003ccode\u003estart\u003c/code\u003e is an optional parameter that represents the starting index within the string where the search begins and the \u003ccode\u003eend\u003c/code\u003e is another optional parameter representing the ending index within the string where the search ends.\u003c/p\u003e\n\u003cp\u003eLet's take a look at the example we used to illustrate the \u003ccode\u003efind()\u003c/code\u003e method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python is fun, just as JavaScript is\u0026quot;\u003c/span\u003e\nresult = text.index(\u003cspan class=\"hljs-string\"\u003e\u0026quot;is\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Substring found at index:\u0026quot;\u003c/span\u003e, result)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAs you can see, the output will be the same as when using the \u003ccode\u003efind()\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eSubstring found at index: 7\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e The key difference between \u003ccode\u003efind()/rfind()\u003c/code\u003e and \u003ccode\u003eindex()/rindex()\u003c/code\u003e lies in their handling of substrings that are not found. While \u003ccode\u003eindex()\u003c/code\u003e and \u003ccode\u003erindex()\u003c/code\u003e raise a \u003ccode\u003eValueError\u003c/code\u003e, \u003ccode\u003efind()\u003c/code\u003e and \u003ccode\u003erfind()\u003c/code\u003e return \u003ccode\u003e-1\u003c/code\u003e, which can be more convenient in scenarios where the absence of a substring is a common and non-exceptional case.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eWhile \u003ccode\u003eindex()\u003c/code\u003e searches from the beginning of the string, \u003cstrong\u003e\u003ccode\u003erindex()\u003c/code\u003e\u003c/strong\u003e serves a similar purpose but starts the search from the end of the string (similar to \u003ccode\u003erfind()\u003c/code\u003e). It finds the last occurrence of the specified substring:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python is fun, just as JavaScript is\u0026quot;\u003c/span\u003e\nresult = text.index(\u003cspan class=\"hljs-string\"\u003e\u0026quot;is\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Last occurrence of \u0026#x27;is\u0026#x27; is at index:\u0026quot;\u003c/span\u003e, result)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eLast occurrence of \u0026#x27;is\u0026#x27; is at index: 34\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"startswithandendswithmethods\"\u003e\u003cem\u003estartswith()\u003c/em\u003e and \u003cem\u003eendswith()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cblockquote\u003e\n\u003cp\u003eReturn \u003ccode\u003eTrue\u003c/code\u003e if the string starts or ends with the specified prefix or suffix, respectively.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cstrong\u003eThe \u003ccode\u003estartswith()\u003c/code\u003e method\u003c/strong\u003e is used to check if a string starts with a specified substring. It's a straightforward and efficient way to perform this check. As usual, let's first check out the syntax before we illustrate the usage of the method in a practical example:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e.startswith(prefix[, start[, end]])\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eprefix\u003c/code\u003e: The substring that you want to check for at the beginning of the string.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003estart\u003c/code\u003e (optional): The starting index within the string where the check begins.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eend\u003c/code\u003e (optional): The ending index within the string where the check ends.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor example, let's check if the file name starts with the word \u003ccode\u003eexample\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003efilename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;example-file.txt\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e filename.startswith(\u003cspan class=\"hljs-string\"\u003e\u0026quot;example\u0026quot;\u003c/span\u003e):\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The filename starts with \u0026#x27;example\u0026#x27;.\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, since the \u003ccode\u003efilename\u003c/code\u003e starts with the word \u003ccode\u003eexample\u003c/code\u003e, you'll get the message printed out:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eThe filename starts with \u0026#x27;example\u0026#x27;.\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eOn the other hand, \u003cstrong\u003ethe \u003ccode\u003eendswith()\u003c/code\u003e method\u003c/strong\u003e checks if a string ends with a specified substring:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003efilename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;example-report.pdf\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e filename.endswith(\u003cspan class=\"hljs-string\"\u003e\u0026quot;.pdf\u0026quot;\u003c/span\u003e):\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The file is a PDF document.\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSince the \u003ccode\u003efilename\u003c/code\u003e is, indeed, the PDF file, you'll get the following output:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eThe file is a PDF document.\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Here, it's important to note that both methods \u003cstrong\u003eare case-sensitive\u003c/strong\u003e. For case-insensitive checks, the string should first be converted to a common case (either lower or upper) using \u003ccode\u003elower()\u003c/code\u003e or \u003ccode\u003eupper()\u003c/code\u003e methods.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cblockquote\u003e\n\u003cp\u003eAs you saw in the previous examples, both \u003ccode\u003estartswith()\u003c/code\u003e and \u003ccode\u003eendswith()\u003c/code\u003e are commonly used in conditional statements to guide the flow of a program based on the presence or absence of specific prefixes or suffixes in strings.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"thecountmethod\"\u003eThe \u003cem\u003ecount()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003ecount()\u003c/code\u003e method is used to count the number of occurrences of a substring in a given string. The syntax of the \u003ccode\u003ecount()\u003c/code\u003e method is:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003estr.count(sub[, start[, end]])\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWhere:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003esub\u003c/code\u003e is the substring for which the count is required.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003estart\u003c/code\u003e (optional) is the starting index from where the count begins.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eend\u003c/code\u003e (optional) is the ending index where the count ends.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe return value is the number of occurrences of \u003ccode\u003esub\u003c/code\u003e in the range \u003ccode\u003estart\u003c/code\u003e to \u003ccode\u003eend\u003c/code\u003e.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eFor example, consider a simple scenario where you need to count the occurrences of a word in a sentence:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python is amazing. Python is simple. Python is powerful.\u0026quot;\u003c/span\u003e\ncount = text.count(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Python\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Python appears\u0026quot;\u003c/span\u003e, count, \u003cspan class=\"hljs-string\"\u003e\u0026quot;times\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will confirm that the word \u0026quot;Python\u0026quot; appears 3 times in the sting \u003ccode\u003etext\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ePython appears 3 times\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Like most string methods in Python, \u003ccode\u003ecount()\u003c/code\u003e is case-sensitive. For case-insensitive counts, convert the string and the substring to a common case using \u003ccode\u003elower()\u003c/code\u003e or \u003ccode\u003eupper()\u003c/code\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eIf you don't need to search an entire string, the \u003ccode\u003estart\u003c/code\u003e and \u003ccode\u003eend\u003c/code\u003e parameters are useful for narrowing down the search within a specific part:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003equote = \u003cspan class=\"hljs-string\"\u003e\u0026quot;To be, or not to be, that is the question.\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-comment\"\u003e# Count occurrences of \u0026#x27;be\u0026#x27; in the substring from index 10 to 30\u003c/span\u003e\ncount = quote.count(\u003cspan class=\"hljs-string\"\u003e\u0026quot;be\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e10\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e30\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026#x27;be\u0026#x27; appears\u0026quot;\u003c/span\u003e, count, \u003cspan class=\"hljs-string\"\u003e\u0026quot;times between index 10 and 30\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e The method counts non-overlapping occurrences. This means that in the string \u0026quot;ababa\u0026quot;, the count for the substring \u0026quot;aba\u0026quot; will be 1, not 2.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"isalphaisdigitisnumericandisalnummethods\"\u003e\u003cem\u003eisalpha()\u003c/em\u003e, \u003cem\u003eisdigit()\u003c/em\u003e, \u003cem\u003eisnumeric()\u003c/em\u003e, and \u003cem\u003eisalnum()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cp\u003ePython string methods offer a variety of ways to inspect and categorize string content. Among these, the \u003ccode\u003eisalpha()\u003c/code\u003e, \u003ccode\u003eisdigit()\u003c/code\u003e, \u003ccode\u003eisnumeric()\u003c/code\u003e, and \u003ccode\u003eisalnum()\u003c/code\u003e methods are commonly used for checking the character composition of strings.\u003c/p\u003e\n\u003cp\u003eFirst of all, let's discuss the \u003cstrong\u003e\u003ccode\u003eisalpha()\u003c/code\u003e method\u003c/strong\u003e. You can use it to check whether all characters in a string are alphabetic (i.e., letters of the alphabet):\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eword = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e word.isalpha():\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The string contains only letters.\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis method returns \u003ccode\u003eTrue\u003c/code\u003e if all characters in the string are alphabetic and there is at least one character. Otherwise, it returns \u003ccode\u003eFalse\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eThe second method to discuss is the \u003cstrong\u003e\u003ccode\u003eisdigit()\u003c/code\u003e method\u003c/strong\u003e, it checks if all characters in the string are digits:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003enumber = \u003cspan class=\"hljs-string\"\u003e\u0026quot;12345\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e number.isdigit():\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The string contains only digits.\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe \u003cstrong\u003e\u003ccode\u003eisnumeric()\u003c/code\u003e method\u003c/strong\u003e is similar to \u003ccode\u003eisdigit()\u003c/code\u003e, but it also considers numeric characters that are not digits in the strict sense, such as superscript digits, fractions, Roman numerals, and characters from other numeric systems:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003enum = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Ⅴ\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e# Roman numeral for 5\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e num.isnumeric():\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The string contains numeric characters.\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eLast, but not least, the \u003cstrong\u003e\u003ccode\u003eisalnum()\u003c/code\u003e method\u003c/strong\u003e checks if the string consists only of alphanumeric characters (i.e., letters and digits):\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003estring = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python3\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e string.isalnum():\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The string is alphanumeric.\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e The \u003ccode\u003eisalnum()\u003c/code\u003e method does not consider special characters or whitespaces.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"theisspacemethod\"\u003eThe \u003cem\u003eisspace()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003eisspace()\u003c/code\u003e method is designed to check whether a string consists only of whitespace characters. It returns \u003ccode\u003eTrue\u003c/code\u003e if all characters in the string are whitespace characters and there is at least one character. If the string is empty or contains any non-whitespace characters, it returns \u003ccode\u003eFalse\u003c/code\u003e.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e \u003cem\u003eWhitespace characters\u003c/em\u003e include spaces (\u003ccode\u003e \u003c/code\u003e), tabs (\u003ccode\u003e\\t\u003c/code\u003e), newlines (\u003ccode\u003e\\n\u003c/code\u003e), and similar space-like characters that are often used to format text.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eThe syntax of the \u003ccode\u003eisspace()\u003c/code\u003e method is pretty straightforward:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e.isspace()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eTo illustrate the usage of the \u003ccode\u003eisspace()\u003c/code\u003e method, consider an example where you might need to check if a string is purely whitespace:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot; \\t\\n \u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e text.isspace():\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The string contains only whitespace characters.\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWhen validating user inputs in forms or command-line interfaces, checking for strings that contain only whitespace helps in ensuring meaningful input is provided.\u003c/p\u003e\n\u003c/blockquote\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eRemember:\u003c/strong\u003e The \u003ccode\u003eisspace()\u003c/code\u003e returns \u003ccode\u003eFalse\u003c/code\u003e for empty strings. If your application requires checking for both empty strings and strings with only whitespace, you'll need to combine checks.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"theformatmethod\"\u003eThe \u003cem\u003eformat()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003e_format()\u003c/code\u003e method, introduced in Python 3, provides a versatile approach to string formatting. It allows for the insertion of variables into string placeholders, offering more readability and flexibility compared to the older \u003ccode\u003e%\u003c/code\u003e formatting. In this section, we'll take a brief overview of the method, and we'll discuss it in more details in later sections.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003eformat()\u003c/code\u003e method works by replacing curly-brace \u003ccode\u003e{}\u003c/code\u003e placeholders within the string with parameters provided to the method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-string\"\u003e\u0026quot;string with {} placeholders\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(values)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFor example, assume you need to insert username and age into a preformatted string. The \u003ccode\u003eformat()\u003c/code\u003e method comes in handy:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e\nage = \u003cspan class=\"hljs-number\"\u003e30\u003c/span\u003e\ngreeting = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, my name is {} and I am {} years old.\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(name, age)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(greeting)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eHello, my name is Alice and I am 30 years old.\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe \u003ccode\u003eformat()\u003c/code\u003e method supports a variety of advanced features, such as named parameters, formatting numbers, aligning text, and so on, but we'll discuss them later in the \u0026quot;\u0026quot; section.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe \u003ccode\u003eformat()\u003c/code\u003e method is ideal for creating strings with dynamic content, such as user input, results from computations, or data from databases. It can also help you internationalize your application since it separates the template from the data.\u003c/p\u003e\n\u003ch3 id=\"centerljustandrjustmethods\"\u003e\u003cem\u003ecenter()\u003c/em\u003e, \u003cem\u003eljust()\u003c/em\u003e, and \u003cem\u003erjust()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cp\u003ePython's string methods include various functions for aligning text. The \u003ccode\u003ecenter()\u003c/code\u003e, \u003ccode\u003eljust()\u003c/code\u003e, and \u003ccode\u003erjust()\u003c/code\u003e methods are particularly useful for formatting strings in a fixed width field. These methods are commonly used in creating text-based user interfaces, reports, and for ensuring uniformity in the visual presentation of strings.\u003c/p\u003e\n\u003cp\u003eThe \u003cstrong\u003e\u003ccode\u003ecenter()\u003c/code\u003e method\u003c/strong\u003e centers a string in a field of a specified width:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e.center(width[, fillchar])\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere the \u003ccode\u003ewidth\u003c/code\u003e parameter represents the total width of the string, including the original string and the (optional) \u003ccode\u003efillchar\u003c/code\u003e parameter represents the character used to fill in the space (defaults to a space if not provided).\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Ensure the width specified is greater than the length of the original string to see the effect of these methods.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eFor example, simply printing text using \u003ccode\u003eprint(\u0026quot;Sample text\u0026quot;)\u003c/code\u003e will result in:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eSample text\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eBut if you wanted to center the text over the field of, say, 20 characters, you'd have to use the \u003ccode\u003ecenter()\u003c/code\u003e method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etitle = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Sample text\u0026quot;\u003c/span\u003e\ncentered_title = title.center(\u003cspan class=\"hljs-number\"\u003e20\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;-\u0026#x27;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(centered_title)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will result in:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e----Sample text-----\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSimilarly, the \u003ccode\u003eljust()\u003c/code\u003e and \u003ccode\u003erjust()\u003c/code\u003e methods will align text to the left and right, padding it with a specified character (or space by default) on the right or left, respectively:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# ljust()\u003c/span\u003e\nname = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e\nleft_aligned = name.ljust(\u003cspan class=\"hljs-number\"\u003e10\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;*\u0026#x27;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(left_aligned)\n\n\u003cspan class=\"hljs-comment\"\u003e# rjust()\u003c/span\u003e\namount = \u003cspan class=\"hljs-string\"\u003e\u0026quot;100\u0026quot;\u003c/span\u003e\nright_aligned = amount.rjust(\u003cspan class=\"hljs-number\"\u003e10\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;0\u0026#x27;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(right_aligned)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eAlice*****\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFor the \u003ccode\u003eljust()\u003c/code\u003e and:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e0000000100\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFor the \u003ccode\u003erjust()\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eUsing these methods can help you align text in columns when displaying data in tabular format. Also, it is pretty useful in text-based user interfaces, these methods help maintain a structured and visually appealing layout.\u003c/p\u003e\n\u003ch3 id=\"thezfillmethod\"\u003eThe \u003cem\u003ezfill()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003ezfill()\u003c/code\u003e method adds zeros (\u003ccode\u003e0\u003c/code\u003e) at the beginning of the string, until it reaches the specified length. If the original string is already equal to or longer than the specified length, \u003ccode\u003ezfill()\u003c/code\u003e returns the original string.\u003c/p\u003e\n\u003cp\u003eThe basic syntax of the \u003ccode\u003e_zfill()\u003c/code\u003e method is:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e.zfill(width)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWhere the \u003ccode\u003ewidth\u003c/code\u003e is the desired length of the string after padding with zeros.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Choose a width that accommodates the longest anticipated string to avoid unexpected results.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eHere’s how you can use the \u003ccode\u003ezfill()\u003c/code\u003e method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003enumber = \u003cspan class=\"hljs-string\"\u003e\u0026quot;50\u0026quot;\u003c/span\u003e\nformatted_number = number.zfill(\u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_number)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will output \u003ccode\u003e00050\u003c/code\u003e, padding the original string \u003ccode\u003e\u0026quot;50\u0026quot;\u003c/code\u003e with three zeros to achieve a length of 5.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe method can also be used on non-numeric strings, though its primary use case is with numbers. In that case, convert them to strings before applying \u003ccode\u003e_zfill()\u003c/code\u003e. For example, use \u003ccode\u003estr(42).zfill(5)\u003c/code\u003e.\u003c/p\u003e\n\u003c/blockquote\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e If the string starts with a sign prefix (\u003ccode\u003e+\u003c/code\u003e or \u003ccode\u003e-\u003c/code\u003e), the zeros are added after the sign. For example, \u003ccode\u003e\u0026quot;-42\u0026quot;.zfill(5)\u003c/code\u003e results in \u003ccode\u003e\u0026quot;-0042\u0026quot;\u003c/code\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch4 id=\"theswapcasemethod\"\u003eThe \u003cem\u003eswapcase()\u003c/em\u003e Method\u003c/h4\u003e\n\u003cp\u003eThe \u003ccode\u003eswapcase()\u003c/code\u003e method iterates through each character in the string, \u003cem\u003echanging each uppercase character to lowercase and each lowercase character to uppercase\u003c/em\u003e.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIt leaves characters that are neither (like digits or symbols) unchanged.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eTake a quick look at an example to demonstrate the \u003ccode\u003eswapcase()\u003c/code\u003e method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python is FUN!\u0026quot;\u003c/span\u003e\nswapped_text = text.swapcase()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(swapped_text)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will output \u003ccode\u003e\u0026quot;pYTHON IS fun!\u0026quot;\u003c/code\u003e, with all uppercase letters converted to lowercase and vice versa.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eWarning:\u003c/strong\u003e In some languages, the concept of case may not apply as it does in English, or the rules might be different. Be cautious when using \u003ccode\u003e_swapcase()\u003c/code\u003e with internationalized text.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"thepartitionandrpartitionmethods\"\u003eThe \u003cem\u003epartition()\u003c/em\u003e and \u003cem\u003erpartition()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003epartition()\u003c/code\u003e and \u003ccode\u003erpartition()\u003c/code\u003e methods split a string into three parts: the part before the separator, the separator itself, and the part after the separator. The \u003ccode\u003epartition()\u003c/code\u003e searches a string from the beginning, and the \u003ccode\u003erpartition()\u003c/code\u003e starts searching from the end of the string:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Syntax of the partition() and rpartition() methods\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e.partition(separator)\n\u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e.rpartition(separator)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, the \u003ccode\u003eseparator\u003c/code\u003e parameter is the string at which the split will occur.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eBoth methods are handy when you need to check if a separator exists in a string and then process the parts accordingly.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eTo illustrate the difference between these two methods, let's take a look at the following string and how these methods are processing it::\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python:Programming:Language\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFirst, let's take a look at the \u003ccode\u003epartition()\u003c/code\u003e method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003epart = text.partition(\u003cspan class=\"hljs-string\"\u003e\u0026quot;:\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(part)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will output \u003ccode\u003e('Python', ':', 'Programming:Language')\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eNow, notice how the output differs when we're using the \u003ccode\u003erpartition()\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003er_part = text.rpartition(\u003cspan class=\"hljs-string\"\u003e\u0026quot;:\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(r_part)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will output \u003ccode\u003e('Python:Programming', ':', 'Language')\u003c/code\u003e.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNo Separator Found\u003c/strong\u003e: If the separator is not found, \u003ccode\u003epartition()\u003c/code\u003e returns the original string as the first part of the tuple, while \u003ccode\u003erpartition()\u003c/code\u003e returns it as the last part.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"theencodemethod\"\u003eThe \u003cem\u003eencode()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eDealing with different character encodings is a common requirement, especially when working with text data from various sources or interacting with external systems. The \u003ccode\u003eencode()\u003c/code\u003e method is designed to help you out in these scenarios. It converts a string into a bytes object using a specified encoding, such as UTF-8, which is essential for data storage, transmission, and processing in different formats.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe \u003ccode\u003eencode()\u003c/code\u003e method encodes the string using the specified encoding scheme. The most common encoding is UTF-8, but Python supports many others, like ASCII, Latin-1, and so on.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe \u003ccode\u003eencode()\u003c/code\u003e simply accepts two parameters, \u003ccode\u003eencoding\u003c/code\u003e and \u003ccode\u003eerrors\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e.encode(encoding=\u003cspan class=\"hljs-string\"\u003e\u0026quot;utf-8\u0026quot;\u003c/span\u003e, errors=\u003cspan class=\"hljs-string\"\u003e\u0026quot;strict\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003eencoding\u003c/code\u003e specifies the encoding to be used for encoding the string and \u003ccode\u003eerrors\u003c/code\u003e determines the response when the encoding conversion fails.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Common values for the \u003ccode\u003eerrors\u003c/code\u003e parameter are \u003ccode\u003e'strict'\u003c/code\u003e, \u003ccode\u003e'ignore'\u003c/code\u003e, and \u003ccode\u003e'replace'\u003c/code\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eHere's an example of converting a string to bytes using UTF-8 encoding:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python Programming\u0026quot;\u003c/span\u003e\nencoded_text = text.encode() \u003cspan class=\"hljs-comment\"\u003e# Default is UTF-8\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(encoded_text)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will output something like \u003ccode\u003eb'Python Programming'\u003c/code\u003e, representing the byte representation of the string.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e In Python, byte strings (b-strings) are sequences of bytes. Unlike regular strings, which are used to represent text and consist of characters, byte strings are raw data represented in bytes.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch4 id=\"errorhandling\"\u003eError Handling\u003c/h4\u003e\n\u003cp\u003eThe \u003ccode\u003eerrors\u003c/code\u003e parameter defines how to handle errors during encoding:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003e'strict'\u003c/code\u003e\u003c/strong\u003e: Raises a \u003ccode\u003eUnicodeEncodeError\u003c/code\u003e on failure (default behavior).\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003e'ignore'\u003c/code\u003e\u003c/strong\u003e: Ignores characters that cannot be encoded.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003e'replace'\u003c/code\u003e\u003c/strong\u003e: Replaces unencodable characters with a replacement marker, such as \u003ccode\u003e?\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003eChoose an error handling strategy that suits your application. In most cases, \u003ccode\u003e'strict'\u003c/code\u003e is preferable to avoid data loss or corruption.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"theexpandtabsmethod\"\u003eThe \u003cem\u003eexpandtabs()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eThis method is often overlooked but can be incredibly useful when dealing with strings containing tab characters (\u003ccode\u003e\\t\u003c/code\u003e).\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003eexpandtabs()\u003c/code\u003e method is used to replace tab characters (\u003ccode\u003e\\t\u003c/code\u003e) in a string with the appropriate number of spaces. This is especially useful in formatting output in a readable way, particularly when dealing with strings that come from or are intended for output in a console or a text file.\u003c/p\u003e\n\u003cp\u003eLet's take a quick look at it's syntaxt:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003estr\u003c/span\u003e.expandtabs(tabsize=\u003cspan class=\"hljs-number\"\u003e8\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003etabsize\u003c/code\u003e is an optional argument. If it's not specified, Python defaults to a tab size of 8 spaces. This means that every tab character in the string will be replaced by eight spaces. However, you can customize this to any number of spaces that fits your needs.\u003c/p\u003e\n\u003cp\u003eFor example, say you want to replace tabs with 4 spaces:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Name\\tAge\\tCity\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(text.expandtabs(\u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eName Age City\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"islowerisupperandistitlemethods\"\u003e\u003cem\u003eislower()\u003c/em\u003e, \u003cem\u003eisupper()\u003c/em\u003e, and \u003cem\u003eistitle()\u003c/em\u003e Methods\u003c/h3\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThese methods check if the string is in lowercase, uppercase, or title case, respectively.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eislower()\u003c/code\u003e\u003c/strong\u003e is a string method used to check if all characters in the string are lowercase. It returns \u003ccode\u003eTrue\u003c/code\u003e if all characters are lowercase and there is at least one cased character, otherwise, it returns \u003ccode\u003eFalse\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ea = \u003cspan class=\"hljs-string\"\u003e\u0026quot;hello world\u0026quot;\u003c/span\u003e\nb = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello World\u0026quot;\u003c/span\u003e\nc = \u003cspan class=\"hljs-string\"\u003e\u0026quot;hello World!\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(a.islower()) \u003cspan class=\"hljs-comment\"\u003e# Output: True\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(b.islower()) \u003cspan class=\"hljs-comment\"\u003e# Output: False\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(c.islower()) \u003cspan class=\"hljs-comment\"\u003e# Output: False\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn contrast, \u003cstrong\u003e\u003ccode\u003eisupper()\u003c/code\u003e\u003c/strong\u003e checks if all cased characters in a string are uppercase. It returns \u003ccode\u003eTrue\u003c/code\u003e if all cased characters are uppercase and there is at least one cased character, otherwise, \u003ccode\u003eFalse\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ea = \u003cspan class=\"hljs-string\"\u003e\u0026quot;HELLO WORLD\u0026quot;\u003c/span\u003e\nb = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello World\u0026quot;\u003c/span\u003e\nc = \u003cspan class=\"hljs-string\"\u003e\u0026quot;HELLO world!\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(a.isupper()) \u003cspan class=\"hljs-comment\"\u003e# Output: True\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(b.isupper()) \u003cspan class=\"hljs-comment\"\u003e# Output: False\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(c.isupper()) \u003cspan class=\"hljs-comment\"\u003e# Output: False\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFinally, the \u003ccode\u003eistitle()\u003c/code\u003e method checks if the string is titled. A string is considered titlecased if all words in the string start with an uppercase character and the rest of the characters in the word are lowercase:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ea = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello World\u0026quot;\u003c/span\u003e\nb = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello world\u0026quot;\u003c/span\u003e\nc = \u003cspan class=\"hljs-string\"\u003e\u0026quot;HELLO WORLD\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(a.istitle()) \u003cspan class=\"hljs-comment\"\u003e# Output: True\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(b.istitle()) \u003cspan class=\"hljs-comment\"\u003e# Output: False\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(c.istitle()) \u003cspan class=\"hljs-comment\"\u003e# Output: False\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"thecasefoldmethod\"\u003eThe \u003cem\u003ecasefold()\u003c/em\u003e Method\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003ecasefold()\u003c/code\u003e method is used for case-insensitive string matching. It is similar to the \u003ccode\u003elower()\u003c/code\u003e method but more aggressive. The \u003ccode\u003ecasefold()\u003c/code\u003e method removes all case distinctions present in a string. It is used for caseless matching, meaning it effectively ignores cases when comparing two strings.\u003c/p\u003e\n\u003cp\u003eA classic example where \u003ccode\u003ecasefold()\u003c/code\u003e matches two strings while \u003ccode\u003elower()\u003c/code\u003e doesn't involves characters from languages that have more complex case rules than English. One such scenario is with the German letter \u0026quot;ß\u0026quot;, which is a lowercase letter. Its uppercase equivalent is \u0026quot;SS\u0026quot;.\u003c/p\u003e\n\u003cp\u003eTo illustrate this, consider two strings, one containing \u0026quot;ß\u0026quot; and the other containing \u0026quot;SS\u0026quot;:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003estr1 = \u003cspan class=\"hljs-string\"\u003e\u0026quot;straße\u0026quot;\u003c/span\u003e\nstr2 = \u003cspan class=\"hljs-string\"\u003e\u0026quot;STRASSE\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow, let's apply both \u003ccode\u003elower()\u003c/code\u003e and \u003ccode\u003ecasefold()\u003c/code\u003e methods and compare the results:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Using `lower()`:\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(str1.lower() == str2.lower()) \u003cspan class=\"hljs-comment\"\u003e# Output: False\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this case, \u003ccode\u003elower()\u003c/code\u003e simply converts all characters in \u003ccode\u003estr2\u003c/code\u003e to lowercase, resulting in \u003ccode\u003e\u0026quot;strasse\u0026quot;\u003c/code\u003e. However, \u003ccode\u003e\u0026quot;strasse\u0026quot;\u003c/code\u003e is not equal to \u003ccode\u003e\u0026quot;straße\u0026quot;\u003c/code\u003e, so the comparison yields \u003ccode\u003eFalse\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eNow, let's compare that to how the \u003ccode\u003ecasefold()\u003c/code\u003e method: handles this scenario:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Using `casefold()`:\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(str1.casefold() == str2.casefold()) \u003cspan class=\"hljs-comment\"\u003e# Output: True\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003ecasefold()\u003c/code\u003e converts \u0026quot;ß\u0026quot; in \u003ccode\u003estr1\u003c/code\u003e to \u0026quot;ss\u0026quot;, making it \u003ccode\u003e\u0026quot;strasse\u0026quot;\u003c/code\u003e. This matches with \u003ccode\u003estr2\u003c/code\u003e after \u003ccode\u003ecasefold()\u003c/code\u003e, which also results in \u003ccode\u003e\u0026quot;strasse\u0026quot;\u003c/code\u003e. Therefore, the comparison yields \u003ccode\u003eTrue\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"formattingstringsinpython\"\u003eFormatting Strings in Python\u003c/h2\u003e\n\u003cp\u003eString formatting is an essential aspect of programming in Python, offering a powerful way to create and manipulate strings dynamically. It's a technique used to construct strings by dynamically inserting variables or expressions into placeholders within a string template.\u003c/p\u003e\n\u003cp\u003eString formatting in Python has evolved significantly over time, providing developers with more intuitive and efficient ways to handle strings. The oldest method of string formatting in Python, borrowed from C is the \u003cstrong\u003e\u003ccode\u003e%\u003c/code\u003e Operator\u003c/strong\u003e (printf-style String Formatting). It uses the \u003ccode\u003e%\u003c/code\u003e operator to replace placeholders with values. While this method is still in use, it is less preferred due to its verbosity and complexity in handling complex formats.\u003c/p\u003e\n\u003cp\u003eThe first advancement was introduced in Python 2.6 in the form of \u003cstrong\u003e\u003ccode\u003estr.format()\u003c/code\u003e method\u003c/strong\u003e. This method offered a more powerful and flexible way of formatting strings. It uses curly braces \u003ccode\u003e{}\u003c/code\u003e as placeholders which can include detailed formatting instructions. It also introduced the support for \u003cem\u003epositional and keyword arguments\u003c/em\u003e, making the string formatting more readable and maintainable.\u003c/p\u003e\n\u003cp\u003eFinally, Python 3.6 introduced a more concise and readable way to format strings in the form of \u003cstrong\u003eformatted string literals\u003c/strong\u003e, or \u003cstrong\u003ef-strings\u003c/strong\u003e in short. They allow for \u003cem\u003einline expressions\u003c/em\u003e, which are evaluated at runtime.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWith f-strings, the syntax is more straightforward, and the code is generally faster than the other methods.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"basicstringformattingtechniques\"\u003eBasic String Formatting Techniques\u003c/h3\u003e\n\u003cp\u003eNow that you understand the evolution of the string formatting techniques in Python, let's dive deeper into each of them. In this section, we'll quickly go over the \u003ccode\u003e%\u003c/code\u003e operator and the \u003ccode\u003estr.format()\u003c/code\u003e method, and, in the end, we'll dive into the f-strings.\u003c/p\u003e\n\u003ch4 id=\"theoperator\"\u003eThe \u003ccode\u003e%\u003c/code\u003e Operator\u003c/h4\u003e\n\u003cp\u003eThe \u003ccode\u003e%\u003c/code\u003e operator, often referred to as the \u003cem\u003eprintf-style string formatting\u003c/em\u003e, is one of the oldest string formatting techniques in Python. It's inspired by the C programming language:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;John\u0026quot;\u003c/span\u003e\nage = \u003cspan class=\"hljs-number\"\u003e36\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Name: %s, Age: %d\u0026quot;\u003c/span\u003e % (name, age))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eName: John, Age: 36\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAs in C, \u003ccode\u003e%s\u003c/code\u003e is used for strings, \u003ccode\u003e%d\u003c/code\u003e or \u003ccode\u003e%i\u003c/code\u003e for integers, and \u003ccode\u003e%f\u003c/code\u003e for floating-point numbers.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis string formatting method can be less intuitive and harder to read, it's also less flexible compared to newer methods.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch4 id=\"thestrformatmethod\"\u003eThe \u003ccode\u003estr.format()\u003c/code\u003e Method\u003c/h4\u003e\n\u003cp\u003eAs we said in the previous sections, at its core, \u003ccode\u003estr.format()\u003c/code\u003e is designed to inject values into string placeholders, defined by curly braces \u003ccode\u003e{}\u003c/code\u003e. The method takes any number of parameters and positions them into the placeholders in the order they are given. Here's a basic example:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Bob\u0026quot;\u003c/span\u003e\nage = \u003cspan class=\"hljs-number\"\u003e25\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Name: {}, Age: {}\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(name, age))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis code will output: \u003ccode\u003eName: Bob, Age: 25\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003estr.format()\u003c/code\u003e becomes more powerful with \u003cstrong\u003epositional and keyword arguments\u003c/strong\u003e. Positional arguments are placed in order according to their position (starting from 0, sure thing):\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etemplate = \u003cspan class=\"hljs-string\"\u003e\u0026quot;{1} is a {0}.\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(template.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;programming language\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python\u0026quot;\u003c/span\u003e))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSince the \u0026quot;Python\u0026quot; is the second argument of the \u003ccode\u003eformat()\u003c/code\u003e method, it replaces the \u003ccode\u003e{1}\u003c/code\u003e and the first argument replaces the \u003ccode\u003e{0}\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ePython is a programming language.\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eKeyword arguments\u003c/strong\u003e, on the other hand, add a layer of readability by allowing you to assign values to named placeholders:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etemplate = \u003cspan class=\"hljs-string\"\u003e\u0026quot;{language} is a {description}.\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(template.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(language=\u003cspan class=\"hljs-string\"\u003e\u0026quot;Python\u0026quot;\u003c/span\u003e, description=\u003cspan class=\"hljs-string\"\u003e\u0026quot;programming language\u0026quot;\u003c/span\u003e))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will also output: \u003ccode\u003ePython is a programming language.\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eOne of the most compelling features of \u003ccode\u003estr.format()\u003c/code\u003e is its \u003cstrong\u003eformatting capabilities\u003c/strong\u003e. You can control \u003cem\u003enumber formatting\u003c/em\u003e, \u003cem\u003ealignment\u003c/em\u003e, \u003cem\u003ewidth\u003c/em\u003e, and more. First, let's format a decimal number so it has only two decimal points:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Formatting numbers\u003c/span\u003e\nnum = \u003cspan class=\"hljs-number\"\u003e123.456793\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Formatted number: {:.2f}\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(num))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, the \u003ccode\u003eformat()\u003c/code\u003e formats the number with six decimal places down to two:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e`Formatted number: 123.46\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow, let's take a look at how to align text using the \u003ccode\u003efomrat()\u003c/code\u003e method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Aligning text\u003c/span\u003e\ntext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Align me\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Left: {:\u0026lt;10} | Right: {:\u0026gt;10} | Center: {:^10}\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(text, text, text))\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eUsing the curly braces syntax of the \u003ccode\u003eformat()\u003c/code\u003e method, we aligned text in fields of length \u003ccode\u003e10\u003c/code\u003e. We used \u003ccode\u003e:\u0026lt;\u003c/code\u003e to align left, \u003ccode\u003e:\u0026gt;\u003c/code\u003e to align right, and \u003ccode\u003e:^\u003c/code\u003e to center text:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eLeft: Align me | Right: Align me | Center: Align me \n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eFor more complex formatting needs\u003c/strong\u003e, \u003ccode\u003estr.format()\u003c/code\u003e can handle \u003cem\u003enested fields\u003c/em\u003e, \u003cem\u003eobject attributes\u003c/em\u003e, and even \u003cem\u003edictionary keys\u003c/em\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Nested fields\u003c/span\u003e\npoint = (\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e8\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;X: {0[0]} | Y: {0[1]}\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(point))\n\u003cspan class=\"hljs-comment\"\u003e# \u0026gt; Output: \u0026#x27;X: 2 | Y: 8\u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Object attributes\u003c/span\u003e\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eDog\u003c/span\u003e:\u003c/span\u003e\n breed = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Beagle\u0026quot;\u003c/span\u003e\n name = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Buddy\u0026quot;\u003c/span\u003e\n\ndog = Dog()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Meet {0.name}, the {0.breed}.\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(dog))\n\u003cspan class=\"hljs-comment\"\u003e# \u0026gt; Output: \u0026#x27;Meet Buddy, the Beagle.\u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Dictionary keys\u003c/span\u003e\ninfo = {\u003cspan class=\"hljs-string\"\u003e\u0026#x27;name\u0026#x27;\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;Alice\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;age\u0026#x27;\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e30\u003c/span\u003e}\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Name: {name} | Age: {age}\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(**info))\n\u003cspan class=\"hljs-comment\"\u003e# \u0026gt; Output: \u0026#x27;Name: Alice | Age: 30\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"introductiontofstrings\"\u003eIntroduction to f-strings\u003c/h4\u003e\n\u003cp\u003eTo create an f-string, prefix your string literal with \u003ccode\u003ef\u003c/code\u003e or \u003ccode\u003eF\u003c/code\u003e before the opening quote. This signals Python to parse any \u003ccode\u003e{}\u003c/code\u003e curly braces and the expressions they contain:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Charlie\u0026quot;\u003c/span\u003e\ngreeting = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Hello, \u003cspan class=\"hljs-subst\"\u003e{name}\u003c/span\u003e!\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(greeting)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eOutput: \u003ccode\u003eHello, Charlie!\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eOne of the key strengths of f-strings is their ability to \u003cstrong\u003eevaluate expressions inline\u003c/strong\u003e. This can include arithmetic operations, method calls, and more:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eage = \u003cspan class=\"hljs-number\"\u003e25\u003c/span\u003e\nage_message = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;In 5 years, you will be \u003cspan class=\"hljs-subst\"\u003e{age + \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e}\u003c/span\u003e years old.\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(age_message)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eOutput: \u003ccode\u003eIn 5 years, you will be 30 years old.\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eLike \u003ccode\u003estr.format()\u003c/code\u003e, f-strings provide \u003cstrong\u003epowerful formatting options\u003c/strong\u003e. You can \u003cem\u003eformat numbers\u003c/em\u003e, \u003cem\u003ealign text\u003c/em\u003e, and \u003cem\u003econtrol precision\u003c/em\u003e all within the curly braces:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eprice = \u003cspan class=\"hljs-number\"\u003e49.99\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003ef\u0026quot;Price: \u003cspan class=\"hljs-subst\"\u003e{price:\u003cspan class=\"hljs-number\"\u003e.2\u003c/span\u003ef}\u003c/span\u003e USD\u0026quot;\u003c/span\u003e)\n\nscore = \u003cspan class=\"hljs-number\"\u003e85.333\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003ef\u0026quot;Score: \u003cspan class=\"hljs-subst\"\u003e{score:\u003cspan class=\"hljs-number\"\u003e.1\u003c/span\u003ef}\u003c/span\u003e%\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eOutput:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ePrice: 49.99 USD\nScore: 85.3%\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"advancedstringformattingwithfstrings\"\u003eAdvanced String Formatting with f-strings\u003c/h3\u003e\n\u003cp\u003eIn the previous section, we touched on some of these concepts, but, here, we'll dive deeper and explain them in more details.\u003c/p\u003e\n\u003ch4 id=\"multilinefstrings\"\u003eMulti-line f-strings\u003c/h4\u003e\n\u003cp\u003eA less commonly discussed, but incredibly useful feature of f-strings is their ability to \u003cem\u003espan multiple lines\u003c/em\u003e. This capability makes them ideal for constructing longer and more complex strings. Let's dive into how multi-line f-strings work and explore their practical applications.\u003c/p\u003e\n\u003cp\u003eA multi-line f-string allows you to spread a string over several lines, maintaining readability and organization in your code. Here’s how you can create a multi-line f-string:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Brian\u0026quot;\u003c/span\u003e\nprofession = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Developer\u0026quot;\u003c/span\u003e\nlocation = \u003cspan class=\"hljs-string\"\u003e\u0026quot;New York\u0026quot;\u003c/span\u003e\n\nbio = (\u003cspan class=\"hljs-string\"\u003ef\u0026quot;Name: \u003cspan class=\"hljs-subst\"\u003e{name}\u003c/span\u003e\\n\u0026quot;\u003c/span\u003e\n \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Profession: \u003cspan class=\"hljs-subst\"\u003e{profession}\u003c/span\u003e\\n\u0026quot;\u003c/span\u003e\n \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Location: \u003cspan class=\"hljs-subst\"\u003e{location}\u003c/span\u003e\u0026quot;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(bio)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eRunning this will result in:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eName: Brian\nProfession: Developer\nLocation: New York\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eWhy Use Multi-line f-strings?\u003c/strong\u003e Multi-line f-strings are particularly useful in scenarios where you need to format long strings or when dealing with strings that naturally span multiple lines, like addresses, detailed reports, or complex messages. They help in \u003cem\u003ekeeping your code clean and readable\u003c/em\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eAlternatively, you could use \u003cem\u003estring concatenation to create multiline strings\u003c/em\u003e, but the advantage of multi-line f-strings is that they are \u003cem\u003emore efficient and readable\u003c/em\u003e. Each line in a multi-line f-string is a part of the same string literal, whereas concatenation involves creating multiple string objects.\u003c/p\u003e\n\u003ch5 id=\"indentationandwhitespace\"\u003eIndentation and Whitespace\u003c/h5\u003e\n\u003cp\u003eIn multi-line f-strings, you need to be mindful of indentation and whitespace as they are preserved in the output:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003emessage = (\n \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Dear \u003cspan class=\"hljs-subst\"\u003e{name}\u003c/span\u003e,\\n\u0026quot;\u003c/span\u003e\n \u003cspan class=\"hljs-string\"\u003ef\u0026quot; Thank you for your interest in our product. \u0026quot;\u003c/span\u003e\n \u003cspan class=\"hljs-string\"\u003ef\u0026quot;We look forward to serving you.\\n\u0026quot;\u003c/span\u003e\n \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Best Regards,\\n\u0026quot;\u003c/span\u003e\n \u003cspan class=\"hljs-string\"\u003ef\u0026quot; The Team\u0026quot;\u003c/span\u003e\n)\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(message)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eDear Alice,\n Thank you for your interest in our product. We look forward to serving you.\nBest Regards,\n The Team\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"complexexpressionsinsidefstrings\"\u003eComplex Expressions Inside f-strings\u003c/h4\u003e\n\u003cp\u003ePython's f-strings not only simplify the task of string formatting but also introduce an elegant way to embed complex expressions directly within string literals. This powerful feature enhances code readability and efficiency, particularly when dealing with intricate operations.\u003c/p\u003e\n\u003ch5 id=\"embeddingexpressions\"\u003eEmbedding Expressions\u003c/h5\u003e\n\u003cp\u003eAn f-string can \u003cstrong\u003eincorporate any valid Python expression within its curly braces\u003c/strong\u003e. This includes arithmetic operations, method calls, and more:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e math\n\nradius = \u003cspan class=\"hljs-number\"\u003e7\u003c/span\u003e\narea = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;The area of the circle is: \u003cspan class=\"hljs-subst\"\u003e{math.pi * radius ** \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e:\u003cspan class=\"hljs-number\"\u003e.2\u003c/span\u003ef}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(area)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will calculate you the area of the circle of radius 7:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eThe area of the circle is: 153.94\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch5 id=\"callingfunctionsandmethods\"\u003eCalling Functions and Methods\u003c/h5\u003e\n\u003cp\u003eF-strings become particularly powerful when you \u003cstrong\u003eembed function calls\u003c/strong\u003e directly into them. This can streamline your code and enhance readability:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eget_temperature\u003c/span\u003e():\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-number\"\u003e22.5\u003c/span\u003e\n\nweather_report = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;The current temperature is \u003cspan class=\"hljs-subst\"\u003e{get_temperature()}\u003c/span\u003e°C.\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(weather_report)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eThe current temperature is 22.5°C.\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch5 id=\"inlineconditionallogic\"\u003eInline Conditional Logic\u003c/h5\u003e\n\u003cp\u003eYou can even use \u003cstrong\u003econditional expressions within f-strings\u003c/strong\u003e, allowing for dynamic string content based on certain conditions:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003escore = \u003cspan class=\"hljs-number\"\u003e85\u003c/span\u003e\ngrade = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;You \u003cspan class=\"hljs-subst\"\u003e{\u003cspan class=\"hljs-string\"\u003e\u0026#x27;passed\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e score \u0026gt;= \u003cspan class=\"hljs-number\"\u003e60\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;failed\u0026#x27;\u003c/span\u003e}\u003c/span\u003e the exam.\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(grade)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSince the \u003ccode\u003escore\u003c/code\u003e is greater than \u003ccode\u003e60\u003c/code\u003e, this will output: \u003ccode\u003eYou passed the exam.\u003c/code\u003e\u003c/p\u003e\n\u003ch5 id=\"listcomprehensions\"\u003eList Comprehensions\u003c/h5\u003e\n\u003cp\u003eF-strings can also incorporate list comprehensions, making it possible to generate dynamic lists and include them in your strings:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003enumbers = [\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e]\nsquared = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Squared numbers: \u003cspan class=\"hljs-subst\"\u003e{[x**\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e x \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e numbers]}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(squared)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will yield:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eSquared numbers: [1, 4, 9, 16, 25]\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch5 id=\"nestedfstrings\"\u003eNested f-strings\u003c/h5\u003e\n\u003cp\u003eFor more advanced formatting needs, you can \u003cstrong\u003enest f-strings within each other\u003c/strong\u003e. This is particularly useful when you need to format a part of the string differently:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Bob\u0026quot;\u003c/span\u003e\nage = \u003cspan class=\"hljs-number\"\u003e30\u003c/span\u003e\nprofile = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Name: \u003cspan class=\"hljs-subst\"\u003e{name}\u003c/span\u003e, Age: \u003cspan class=\"hljs-subst\"\u003e{\u003cspan class=\"hljs-string\"\u003ef\u0026#x27;\u003cspan class=\"hljs-subst\"\u003e{age}\u003c/span\u003e years old\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e age \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;Age not provided\u0026#x27;\u003c/span\u003e}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(profile)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere. we independently formatted how the \u003ccode\u003eAge\u003c/code\u003e section will be displayed: \u003ccode\u003eName: Bob, Age: 30 years old\u003c/code\u003e\u003c/p\u003e\n\u003ch5 id=\"handlingexceptions\"\u003eHandling Exceptions\u003c/h5\u003e\n\u003cp\u003eYou can even use f-strings to \u003cstrong\u003ehandle exceptions in a concise manner\u003c/strong\u003e, though it should be done cautiously to maintain code clarity:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ex = \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e\ny = \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e\nresult = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Division result: \u003cspan class=\"hljs-subst\"\u003e{x / y \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e y != \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;Error: Division by zero\u0026#x27;\u003c/span\u003e}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(result)\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;Division result: Error: Division by zero\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"conditionallogicandternaryoperationsinpythonfstrings\"\u003eConditional Logic and Ternary Operations in Python f-strings\u003c/h4\u003e\n\u003cp\u003eWe briefly touched on this topic in the previous section, but, here, we'll get into more details. This functionality is particularly useful when you need to dynamically change the content of a string based on certain conditions.\u003c/p\u003e\n\u003cp\u003eAs we previously discussed, the ternary operator in Python, which follows the format \u003ccode\u003ex if condition else y\u003c/code\u003e, can be seamlessly integrated into f-strings. This allows for inline conditional checks and dynamic string content:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eage = \u003cspan class=\"hljs-number\"\u003e20\u003c/span\u003e\nage_group = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;\u003cspan class=\"hljs-subst\"\u003e{\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Adult\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e age \u0026gt;= \u003cspan class=\"hljs-number\"\u003e18\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;Minor\u0026#x27;\u003c/span\u003e}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003ef\u0026quot;Age Group: \u003cspan class=\"hljs-subst\"\u003e{age_group}\u003c/span\u003e\u0026quot;\u003c/span\u003e)\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;Age Group: Adult\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eYou can also use ternary operations within f-strings for conditional formatting. This is particularly useful for changing the format of the string based on certain conditions:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003escore = \u003cspan class=\"hljs-number\"\u003e75\u003c/span\u003e\nresult = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Score: \u003cspan class=\"hljs-subst\"\u003e{score}\u003c/span\u003e (\u003cspan class=\"hljs-subst\"\u003e{\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Pass\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e score \u0026gt;= \u003cspan class=\"hljs-number\"\u003e50\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;Fail\u0026#x27;\u003c/span\u003e}\u003c/span\u003e)\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(result)\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;Score: 75 (Pass)\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eBesides handling basic conditions, ternary operations inside f-strings can also handle \u003cstrong\u003emore complex conditions\u003c/strong\u003e, allowing for intricate logical operations:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ehours_worked = \u003cspan class=\"hljs-number\"\u003e41\u003c/span\u003e\npay_rate = \u003cspan class=\"hljs-number\"\u003e20\u003c/span\u003e\novertime_rate = \u003cspan class=\"hljs-number\"\u003e1.5\u003c/span\u003e\ntotal_pay = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Total Pay: $\u003cspan class=\"hljs-subst\"\u003e{(hours_worked * pay_rate) + ((hours_worked - \u003cspan class=\"hljs-number\"\u003e40\u003c/span\u003e) * pay_rate * overtime_rate) \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e hours_worked \u0026gt; \u003cspan class=\"hljs-number\"\u003e40\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e hours_worked * pay_rate}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(total_pay)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, we calculated the total pay by using inline ternary operator: \u003ccode\u003eTotal Pay: $830.0\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eCombining multiple conditions\u003c/strong\u003e within f-strings is something that can be easily achieved:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etemperature = \u003cspan class=\"hljs-number\"\u003e75\u003c/span\u003e\nweather = \u003cspan class=\"hljs-string\"\u003e\u0026quot;sunny\u0026quot;\u003c/span\u003e\nactivity = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Activity: \u003cspan class=\"hljs-subst\"\u003e{\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Swimming\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e weather == \u003cspan class=\"hljs-string\"\u003e\u0026#x27;sunny\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eand\u003c/span\u003e temperature \u0026gt; \u003cspan class=\"hljs-number\"\u003e70\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;Reading indoors\u0026#x27;\u003c/span\u003e}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(activity)\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;Activity: Swimming\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eTernary operations in f-strings can also be used for \u003cstrong\u003edynamic formatting\u003c/strong\u003e, such as changing text color based on a condition:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eprofit = -\u003cspan class=\"hljs-number\"\u003e20\u003c/span\u003e\nprofit_message = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Profit: \u003cspan class=\"hljs-subst\"\u003e{\u003cspan class=\"hljs-string\"\u003e\u0026#x27;+\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e profit \u0026gt;= \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;\u0026#x27;\u003c/span\u003e}\u003c/span\u003e\u003cspan class=\"hljs-subst\"\u003e{profit}\u003c/span\u003e \u003cspan class=\"hljs-subst\"\u003e{\u003cspan class=\"hljs-string\"\u003e\u0026#x27;(green)\u0026#x27;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e profit \u0026gt;= \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;(red)\u0026#x27;\u003c/span\u003e}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(profit_message)\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;Profit: -20 (red)\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"formattingdatesandtimeswithpythonfstrings\"\u003eFormatting Dates and Times with Python f-strings\u003c/h4\u003e\n\u003cp\u003eOne of the many strengths of Python's f-strings is their ability to elegantly handle date and time formatting. In this section, we'll explore how to use f-strings to format dates and times, showcasing various formatting options to suit different requirements.\u003c/p\u003e\n\u003cp\u003eTo format a datetime object using an f-string, you can simply include the desired format specifiers inside the curly braces:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e datetime \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e datetime\n\ncurrent_time = datetime.now()\nformatted_time = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Current time: \u003cspan class=\"hljs-subst\"\u003e{current_time:%Y-%m-%d %H:%M:%S}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_time)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you the current time in the format you specified:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eCurrent time: [current date and time in YYYY-MM-DD HH:MM:SS format]\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Here, you can also use any of the other datetime specifiers, such as \u003ccode\u003e%B\u003c/code\u003e, \u003ccode\u003e%s\u003c/code\u003e, and so on.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eIf you're working with \u003cem\u003etimezone-aware datetime objects\u003c/em\u003e, f-strings can provide you with the \u003cstrong\u003etime zone information\u003c/strong\u003e using the \u003ccode\u003e%z\u003c/code\u003e specifier:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e datetime \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e timezone, timedelta\n\ntimestamp = datetime.now(timezone.utc)\nformatted_timestamp = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;UTC Time: \u003cspan class=\"hljs-subst\"\u003e{timestamp:%Y-%m-%d %H:%M:%S %Z}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_timestamp)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you: \u003ccode\u003eUTC Time: [current UTC date and time] UTC\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eF-strings can be particularly handy for creating \u003cstrong\u003ecustom date and time formats\u003c/strong\u003e, tailored for display in user interfaces or reports:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eevent_date = datetime(\u003cspan class=\"hljs-number\"\u003e2023\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e12\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e31\u003c/span\u003e)\nevent_time = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Event Date: \u003cspan class=\"hljs-subst\"\u003e{event_date:%d-%m-%Y | %I:%M%p}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(event_time)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eOutput: \u003ccode\u003eEvent Date: 31-12-2023 | 12:00AM\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eYou can also combine f-strings with \u003ccode\u003etimedelta\u003c/code\u003e objects to \u003cstrong\u003edisplay relative times\u003c/strong\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e datetime \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e timedelta\n\ncurrent_time = datetime.now()\nhours_passed = timedelta(hours=\u003cspan class=\"hljs-number\"\u003e6\u003c/span\u003e)\nfuture_time = current_time + hours_passed\nrelative_time = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Time after 6 hours: \u003cspan class=\"hljs-subst\"\u003e{future_time:%H:%M}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(relative_time)\n\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;Time after 6 hours: [time 6 hours from now in HH:MM format]\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAll-in-all, you can create whichever datetime format using a combination of the available specifiers within a f-string:\u003c/p\u003e\n\u003ctable class=\"table table-striped\"\u003e\n \u003cthead\u003e\n \u003ctr\u003e\n \u003cth style=\"width:150px;\"\u003eSpecifier\u003c/th\u003e\n \u003cth\u003eUsage\u003c/th\u003e\n \u003c/tr\u003e\n \u003cthead\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\n \u003ctd\u003e%a\u003c/td\u003e\n \u003ctd\u003eAbbreviated weekday name.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%A\u003c/td\u003e\n \u003ctd\u003eFull weekday name.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%b\u003c/td\u003e\n \u003ctd\u003eAbbreviated month name.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%B\u003c/td\u003e\n \u003ctd\u003eFull month name.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%c\u003c/td\u003e\n \u003ctd\u003eDate and time representation appropriate for locale. If the # flag (`%#c`) precedes the specifier, long date and time representation is used.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%d\u003c/td\u003e\n \u003ctd\u003eDay of month as a decimal number (01 – 31). If the # flag (`%#d`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%H\u003c/td\u003e\n \u003ctd\u003eHour in 24-hour format (00 – 23). If the # flag (`%#H`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%I\u003c/td\u003e\n \u003ctd\u003eHour in 12-hour format (01 – 12). If the # flag (`%#I`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%j\u003c/td\u003e\n \u003ctd\u003eDay of year as decimal number (001 – 366). If the # flag (`%#j`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%m\u003c/td\u003e\n \u003ctd\u003eMonth as decimal number (01 – 12). If the # flag (`%#m`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%M\u003c/td\u003e\n \u003ctd\u003eMinute as decimal number (00 – 59). If the # flag (`%#M`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%p\u003c/td\u003e\n \u003ctd\u003eCurrent locale\u0026#39;s A.M./P.M. indicator for 12-hour clock.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%S\u003c/td\u003e\n \u003ctd\u003eSecond as decimal number (00 – 59). If the # flag (`%#S`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%U\u003c/td\u003e\n \u003ctd\u003eWeek of year as decimal number, with Sunday as first day of week (00 – 53). If the # flag (`%#U`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%w\u003c/td\u003e\n \u003ctd\u003eWeekday as decimal number (0 – 6; Sunday is 0). If the # flag (`%#w`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%W\u003c/td\u003e\n \u003ctd\u003eWeek of year as decimal number, with Monday as first day of week (00 – 53). If the # flag (`%#W`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%x\u003c/td\u003e\n \u003ctd\u003eDate representation for current locale. If the # flag (`%#x`) precedes the specifier, long date representation is enabled.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%X\u003c/td\u003e\n \u003ctd\u003eTime representation for current locale.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%y\u003c/td\u003e\n \u003ctd\u003eYear without century, as decimal number (00 – 99). If the # flag (`%#y`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%Y\u003c/td\u003e\n \u003ctd\u003eYear with century, as decimal number. If the # flag (`%#Y`) precedes the specifier, the leading zeros are removed from the number.\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e%z, %Z\u003c/td\u003e\n \u003ctd\u003eEither the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown.\u003c/td\u003e\n \u003c/tr\u003e\n \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"advancednumberformattingwithpythonfstrings\"\u003eAdvanced Number Formatting with Python f-strings\u003c/h4\u003e\n\u003cp\u003ePython's f-strings are not only useful for embedding expressions and creating dynamic strings, but they also excel in formatting numbers for various contexts. They can be helpful when dealing with financial data, scientific calculations, or statistical information,since they offer a wealth of options for presenting numbers in a clear, precise, and readable format. In this section, we'll dive into the advanced aspects of number formatting using f-strings in Python.\u003c/p\u003e\n\u003cp\u003eBefore exploring advanced techniques, let's start with basic number formatting:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003enumber = \u003cspan class=\"hljs-number\"\u003e123456.789\u003c/span\u003e\nformatted_number = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Basic formatting: \u003cspan class=\"hljs-subst\"\u003e{number:,}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_number)\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;Basic formatting: 123,456.789\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, we simply changed the way we print the \u003ccode\u003enumber\u003c/code\u003e so it uses commas as thousands separator and full stops as a decimal separator.\u003c/p\u003e\n\u003cp\u003eF-strings allow you to \u003cstrong\u003econtrol the precision of floating-point numbers\u003c/strong\u003e, which is crucial in fields like finance and engineering:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003epi = \u003cspan class=\"hljs-number\"\u003e3.141592653589793\u003c/span\u003e\nformatted_pi = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Pi rounded to 3 decimal places: \u003cspan class=\"hljs-subst\"\u003e{pi:\u003cspan class=\"hljs-number\"\u003e.3\u003c/span\u003ef}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_pi)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, we rounded Pi to 3 decimal places: \u003ccode\u003ePi rounded to 3 decimal places: 3.142\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eFor \u003cstrong\u003edisplaying percentages\u003c/strong\u003e, f-strings can convert decimal numbers to percentage format:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ecompletion_ratio = \u003cspan class=\"hljs-number\"\u003e0.756\u003c/span\u003e\nformatted_percentage = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Completion: \u003cspan class=\"hljs-subst\"\u003e{completion_ratio:\u003cspan class=\"hljs-number\"\u003e.2\u003c/span\u003e%}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_percentage)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you: \u003ccode\u003eCompletion: 75.60%\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eAnother useful feature is that f-strings support \u003cstrong\u003eexponential notation\u003c/strong\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eavogadro_number = \u003cspan class=\"hljs-number\"\u003e6.02214076e23\u003c/span\u003e\nformatted_avogadro = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Avogadro\u0026#x27;s number: \u003cspan class=\"hljs-subst\"\u003e{avogadro_number:\u003cspan class=\"hljs-number\"\u003e.2\u003c/span\u003ee}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_avogadro)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will convert Avogadro's number from the usual decimal notation to the exponential notation: \u003ccode\u003eAvogadro's number: 6.02e+23\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eBesides this, f-strings can also \u003cstrong\u003eformat numbers in hexadecimal, binary, or octal representation\u003c/strong\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003enumber = \u003cspan class=\"hljs-number\"\u003e255\u003c/span\u003e\nhex_format = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Hexadecimal: \u003cspan class=\"hljs-subst\"\u003e{number:#x}\u003c/span\u003e\u0026quot;\u003c/span\u003e\nbinary_format = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Binary: \u003cspan class=\"hljs-subst\"\u003e{number:#b}\u003c/span\u003e\u0026quot;\u003c/span\u003e\noctal_format = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Octal: \u003cspan class=\"hljs-subst\"\u003e{number:#o}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(hex_format)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(binary_format)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(octal_format)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will transform the number \u003ccode\u003e255\u003c/code\u003e to each of supported number representations:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eHexadecimal: 0xff\nBinary: 0b11111111\nOctal: 0o377\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"lambdasandinlinefunctionsinpythonfstrings\"\u003eLambdas and Inline Functions in Python f-strings\u003c/h4\u003e\n\u003cp\u003ePython's f-strings are not only efficient for embedding expressions and formatting strings but also offer the flexibility to include lambda functions and other inline functions.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis feature opens up a plenty of possibilities for on-the-fly computations and dynamic string generation.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cstrong\u003eLambda functions\u003c/strong\u003e, also known as anonymous functions in Python, can be used within f-strings for inline calculations:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003earea = \u003cspan class=\"hljs-keyword\"\u003elambda\u003c/span\u003e r: \u003cspan class=\"hljs-number\"\u003e3.14\u003c/span\u003e * r ** \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e\nradius = \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e\nformatted_area = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;The area of the circle with radius \u003cspan class=\"hljs-subst\"\u003e{radius}\u003c/span\u003e is: \u003cspan class=\"hljs-subst\"\u003e{area(radius)}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_area)\n\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;The area of the circle with radius 5 is: 78.5\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAs we briefly discussed before, you can also call functions directly within an f-string, making your code more concise and readable:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003esquare\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003en\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e n * n\n\nnum = \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e\nformatted_square = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;The square of \u003cspan class=\"hljs-subst\"\u003e{num}\u003c/span\u003e is: \u003cspan class=\"hljs-subst\"\u003e{square(num)}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_square)\n\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;The square of 4 is: 16\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eLambdas in f-strings can help you implement more \u003cstrong\u003ecomplex expressions\u003c/strong\u003e within f-strings, enabling sophisticated inline computations:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e math\n\nhypotenuse = \u003cspan class=\"hljs-keyword\"\u003elambda\u003c/span\u003e a, b: math.sqrt(a**\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e + b**\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e)\nside1, side2 = \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e\nformatted_hypotenuse = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;The hypotenuse of a triangle with sides \u003cspan class=\"hljs-subst\"\u003e{side1}\u003c/span\u003e and \u003cspan class=\"hljs-subst\"\u003e{side2}\u003c/span\u003e is: \u003cspan class=\"hljs-subst\"\u003e{hypotenuse(side1, side2)}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_hypotenuse)\n\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;The hypotenuse of a triangle with sides 3 and 4 is: 5.0\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eYou can also combine multiple functions within a single f-string for complex formatting needs:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003edouble\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003en\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e n * \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e\n\n\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eformat_as_percentage\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003en\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ef\u0026quot;\u003cspan class=\"hljs-subst\"\u003e{n:\u003cspan class=\"hljs-number\"\u003e.2\u003c/span\u003e%}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\nnum = \u003cspan class=\"hljs-number\"\u003e0.25\u003c/span\u003e\nformatted_result = \u003cspan class=\"hljs-string\"\u003ef\u0026quot;Double of \u003cspan class=\"hljs-subst\"\u003e{num}\u003c/span\u003e as percentage: \u003cspan class=\"hljs-subst\"\u003e{format_as_percentage(double(num))}\u003c/span\u003e\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_result)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eDouble of 0.25 as percentage: 50.00%\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"debuggingwithfstringsinpython38\"\u003eDebugging with f-strings in Python 3.8+\u003c/h4\u003e\n\u003cp\u003ePython 3.8 introduced a subtle yet impactful feature in f-strings: the ability to self-document expressions. This feature, often heralded as a boon for debugging, enhances f-strings beyond simple formatting tasks, making them a powerful tool for diagnosing and understanding code.\u003c/p\u003e\n\u003cp\u003eThe key addition in Python 3.8 is the \u003ccode\u003e=\u003c/code\u003e specifier in f-strings. It allows you to \u003cstrong\u003eprint both the expression and its value\u003c/strong\u003e, which is particularly useful for debugging:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ex = \u003cspan class=\"hljs-number\"\u003e14\u003c/span\u003e\ny = \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003ef\u0026quot;\u003cspan class=\"hljs-subst\"\u003e{x=}\u003c/span\u003e, \u003cspan class=\"hljs-subst\"\u003e{y=}\u003c/span\u003e\u0026quot;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;x=14, y=3\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis feature shines when used with more complex expressions, \u003cstrong\u003eproviding insight into the values of variables\u003c/strong\u003e at specific points in your code:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ename = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e\nage = \u003cspan class=\"hljs-number\"\u003e30\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003ef\u0026quot;\u003cspan class=\"hljs-subst\"\u003e{name.upper()=}\u003c/span\u003e, \u003cspan class=\"hljs-subst\"\u003e{age * \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e=}\u003c/span\u003e\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will print out both the variables you're looking at and its value:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ename.upper()=\u0026#x27;ALICE\u0026#x27;, age * 2=60\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe \u003ccode\u003e=\u003c/code\u003e specifier is also handy for \u003cstrong\u003edebugging within loops\u003c/strong\u003e, where you can track the change of variables in each iteration:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e i \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003erange\u003c/span\u003e(\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e):\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003ef\u0026quot;Loop \u003cspan class=\"hljs-subst\"\u003e{i=}\u003c/span\u003e\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eOutput:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eLoop i=0\nLoop i=1\nLoop i=2\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAdditionally, you can debug function return values and argument values directly within f-strings:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003esquare\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003en\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e n * n\n\nnum = \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003ef\u0026quot;\u003cspan class=\"hljs-subst\"\u003e{square(num)=}\u003c/span\u003e\u0026quot;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-comment\"\u003e# Output: \u0026#x27;square(num)=16\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e While this feature is incredibly useful for debugging, it's important to use it judiciously. The output can become cluttered in complex expressions, so it's best suited for quick and simple debugging scenarios.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cblockquote\u003e\n\u003cp\u003eRemember to remove these debugging statements from production code for clarity and performance.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch4 id=\"performanceoffstrings\"\u003ePerformance of F-strings\u003c/h4\u003e\n\u003cp\u003eF-strings are often lauded for their readability and ease of use, but \u003cem\u003ehow do they stack up in terms of performance\u003c/em\u003e? Here, we'll dive into the performance aspects of f-strings, comparing them with traditional string formatting methods, and provide insights on optimizing string formatting in Python:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ef-strings vs. Concatenation\u003c/strong\u003e: f-strings generally offer \u003cem\u003ebetter performance than string concatenation\u003c/em\u003e, especially in cases with multiple dynamic values. Concatenation can lead to the creation of numerous intermediate string objects, whereas an f-string is compiled into an efficient format.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ef-strings vs. \u003ccode\u003e%\u003c/code\u003e Formatting\u003c/strong\u003e: The old \u003ccode\u003e%\u003c/code\u003e formatting method in Python is less efficient compared to f-strings. f-strings, being a more modern implementation, are \u003cem\u003eoptimized for speed and lower memory usage\u003c/em\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ef-strings vs. \u003ccode\u003estr.format()\u003c/code\u003e\u003c/strong\u003e: f-strings are typically faster than the \u003ccode\u003estr.format()\u003c/code\u003e method. This is because f-strings are \u003cem\u003eprocessed at compile time\u003c/em\u003e, not at runtime, which reduces the overhead associated with parsing and interpreting the format string.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch5 id=\"considerationsforoptimizingstringformatting\"\u003eConsiderations for Optimizing String Formatting\u003c/h5\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eUse f-strings for Simplicity and Speed\u003c/strong\u003e: Given their performance benefits, use f-strings for most string formatting needs, unless working with a Python version earlier than 3.6.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eComplex Expressions\u003c/strong\u003e: For complex expressions within f-strings, be aware that they are evaluated at runtime. If the expression is particularly heavy, it can offset the performance benefits of f-strings.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory Usage\u003c/strong\u003e: In scenarios with extremely large strings or in memory-constrained environments, consider other approaches like string builders or generators.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eReadability vs. Performance\u003c/strong\u003e: While f-strings provide a performance advantage, always balance this with code readability and maintainability.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIn summary, f-strings not only enhance the readability of string formatting in Python but also offer performance benefits over traditional methods like concatenation, \u003ccode\u003e%\u003c/code\u003e formatting, and \u003ccode\u003estr.format()\u003c/code\u003e. They are a robust choice for efficient string handling in Python, provided they are used judiciously, keeping in mind the complexity of embedded expressions and overall code clarity.\u003c/p\u003e\n\u003ch3 id=\"formattingandinternationalization\"\u003eFormatting and Internationalization\u003c/h3\u003e\n\u003cp\u003eWhen your app is targeting a global audience, it's crucial to consider internationalization and localization. Python provides robust tools and methods to handle formatting that respects different cultural norms, such as date formats, currency, and number representations. Let's explore how Python deals with these challenges.\u003c/p\u003e\n\u003ch4 id=\"dealingwithlocalespecificformatting\"\u003eDealing with Locale-Specific Formatting\u003c/h4\u003e\n\u003cp\u003eWhen developing applications for an international audience, you need to format data in a way that is familiar to each user's locale. This includes differences in numeric formats, currencies, date and time conventions, and more.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eThe \u003ccode\u003elocale\u003c/code\u003e Module:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ePython's \u003ccode\u003elocale\u003c/code\u003e module allows you to set and get the locale information and provides functionality for locale-sensitive formatting.\u003c/li\u003e\n\u003cli\u003eYou can use \u003ccode\u003elocale.setlocale()\u003c/code\u003e to set the locale based on the user’s environment.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eNumber Formatting:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUsing the \u003ccode\u003elocale\u003c/code\u003e module, you can format numbers according to the user's locale, which includes appropriate grouping of digits and decimal point symbols.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e locale\nlocale.setlocale(locale.LC_ALL, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;en_US.UTF-8\u0026#x27;\u003c/span\u003e)\nformatted_number = locale.format_string(\u003cspan class=\"hljs-string\"\u003e\u0026quot;%d\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e1234567\u003c/span\u003e, grouping=\u003cspan class=\"hljs-literal\"\u003eTrue\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_number) \u003cspan class=\"hljs-comment\"\u003e# 1,234,567 in US locale\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eCurrency Formatting:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe \u003ccode\u003elocale\u003c/code\u003e module also provides a way to format currency values.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eformatted_currency = locale.currency(\u003cspan class=\"hljs-number\"\u003e1234.56\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(formatted_currency) \u003cspan class=\"hljs-comment\"\u003e# $1,234.56 in US locale\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"dateandtimeformattingforinternationalization\"\u003eDate and Time Formatting for Internationalization\u003c/h4\u003e\n\u003cp\u003eDate and time representations vary significantly across cultures. Python's \u003ccode\u003edatetime\u003c/code\u003e module, combined with the \u003ccode\u003elocale\u003c/code\u003e module, can be used to display date and time in a locale-appropriate format.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eExample:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e locale\n\u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e datetime \u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e datetime\n\nlocale.setlocale(locale.LC_ALL, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;de_DE\u0026#x27;\u003c/span\u003e)\nnow = datetime.now()\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(now.strftime(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;%c\u0026#x27;\u003c/span\u003e)) \u003cspan class=\"hljs-comment\"\u003e# Locale-specific full date and time representation\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"bestpracticesforinternationalization\"\u003eBest Practices for Internationalization:\u003c/h4\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eConsistent Use of Locale Settings:\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eAlways set the locale at the start of your application and use it consistently throughout.\u003c/li\u003e\n\u003cli\u003eRemember to handle cases where the locale setting might not be available or supported.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBe Cautious with Locale Settings:\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eSetting a locale is a global operation in Python, which means it can affect other parts of your program or other programs running in the same environment.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTest with Different Locales:\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eEnsure to test your application with different locale settings to verify that formats are displayed correctly.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandling Different Character Sets and Encodings:\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eBe aware of the encoding issues that might arise with different languages, especially when dealing with non-Latin character sets.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"workingwithsubstrings\"\u003eWorking with Substrings\u003c/h2\u003e\n\u003cp\u003eWorking with substrings is a common task in Python programming, involving extracting, searching, and manipulating parts of strings. Python offers several methods to handle substrings efficiently and intuitively. Understanding these methods is crucial for text processing, data manipulation, and various other applications.\u003c/p\u003e\n\u003ch3 id=\"extractingsubstrings\"\u003eExtracting Substrings\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eSlicing\u003c/strong\u003e is one of the primary ways to \u003cem\u003eextract a substring from a string\u003c/em\u003e. It involves specifying a start and end index, and optionally a step, to slice out a portion of the string.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e We discussed the notion of slicing in more details in the \u0026quot;Basic String Operations\u0026quot; section.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eFor example, say you'd like to extract the word \u0026quot;World\u0026quot; from the sentence \u0026quot;Hello, world!\u0026quot;\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, World!\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-comment\"\u003e# Extract \u0026#x27;World\u0026#x27; from text\u003c/span\u003e\nsubstring = text[\u003cspan class=\"hljs-number\"\u003e7\u003c/span\u003e:\u003cspan class=\"hljs-number\"\u003e12\u003c/span\u003e]\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, the value of \u003ccode\u003esubstring\u003c/code\u003e would be \u003ccode\u003e\u0026quot;World\u0026quot;\u003c/code\u003e. Python also supports \u003cem\u003enegative indexing\u003c/em\u003e (counting from the end), and omitting start or end indices to slice from the beginning or to the end of the string, respectively.\u003c/p\u003e\n\u003ch3 id=\"findingsubstrings\"\u003eFinding Substrings\u003c/h3\u003e\n\u003cp\u003eAs we discussed in the \u0026quot;Common String Methods\u0026quot; section, Python provides methods like \u003ccode\u003efind()\u003c/code\u003e, \u003ccode\u003eindex()\u003c/code\u003e, \u003ccode\u003erfind()\u003c/code\u003e, and \u003ccode\u003erindex()\u003c/code\u003e to search for the position of a substring within a string.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003efind()\u003c/code\u003e and \u003ccode\u003erfind()\u003c/code\u003e return the lowest and the highest index where the substring is found, respectively. They return \u003ccode\u003e-1\u003c/code\u003e if the substring is not found.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eindex()\u003c/code\u003e and \u003ccode\u003erindex()\u003c/code\u003e are similar to \u003ccode\u003efind()\u003c/code\u003e and \u003ccode\u003erfind()\u003c/code\u003e, but raise a \u003ccode\u003eValueError\u003c/code\u003e if the substring is not found.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor example, the position of the word \u0026quot;World\u0026quot; in the string \u0026quot;Hello, World!\u0026quot; would be \u003ccode\u003e7\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, World!\u0026quot;\u003c/span\u003e\nposition = text.find(\u003cspan class=\"hljs-string\"\u003e\u0026quot;World\u0026quot;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(position)\n\u003cspan class=\"hljs-comment\"\u003e# Output: 7\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"replacingsubstrings\"\u003eReplacing Substrings\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003ereplace()\u003c/code\u003e method is used to replace occurrences of a specified substring with another substring:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, World!\u0026quot;\u003c/span\u003e\nnew_text = text.replace(\u003cspan class=\"hljs-string\"\u003e\u0026quot;World\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;Python\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe word \u0026quot;World\u0026quot; will be replaced with the word \u0026quot;Python\u0026quot;, therefore, \u003ccode\u003enew_text\u003c/code\u003e would be \u003ccode\u003e\u0026quot;Hello, Python!\u0026quot;\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"checkingforsubstrings\"\u003eChecking for Substrings\u003c/h3\u003e\n\u003cp\u003eMethods like \u003ccode\u003estartswith()\u003c/code\u003e and \u003ccode\u003eendswith()\u003c/code\u003e are used to check if a string starts or ends with a specified substring, respectively:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, World!\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e text.startswith(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello\u0026quot;\u003c/span\u003e):\n \u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026quot;The string starts with \u0026#x27;Hello\u0026#x27;\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"splittingstrings\"\u003eSplitting Strings\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003esplit()\u003c/code\u003e method breaks a string into a list of substrings based on a specified delimiter:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;one,two,three\u0026quot;\u003c/span\u003e\nitems = text.split(\u003cspan class=\"hljs-string\"\u003e\u0026quot;,\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003eitems\u003c/code\u003e would be \u003ccode\u003e['one', 'two', 'three']\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"joiningstrings\"\u003eJoining Strings\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003ejoin()\u003c/code\u003e method is used to concatenate a list of strings into a single string, with a specified separator:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ewords = [\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Python\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;is\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;fun\u0026#x27;\u003c/span\u003e]\nsentence = \u003cspan class=\"hljs-string\"\u003e\u0026#x27; \u0026#x27;\u003c/span\u003e.join(words)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this example, \u003ccode\u003esentence\u003c/code\u003e would be \u003ccode\u003e\u0026quot;Python is fun\u0026quot;\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"advancedstringtechniques\"\u003eAdvanced String Techniques\u003c/h2\u003e\n\u003cp\u003eBesides simple string manipulation techniques, Python involves more sophisticated methods of manipulating and handling strings, which are essential for complex text processing, encoding, and pattern matching.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIn this section, we'll take a look at an overview of some advanced string techniques in Python.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"unicodeandbytestrings\"\u003eUnicode and Byte Strings\u003c/h3\u003e\n\u003cp\u003eUnderstanding the distinction between Unicode strings and byte strings in Python is quite important when you're dealing with text and binary data. This differentiation is a core aspect of Python's design and plays a significant role in how the language handles string and binary data.\u003c/p\u003e\n\u003cp\u003eSince the introduction of Python 3, the \u003cem\u003edefault string type is Unicode\u003c/em\u003e. This means whenever you create a string using \u003ccode\u003estr\u003c/code\u003e, like when you write \u003ccode\u003es = \u0026quot;hello\u0026quot;\u003c/code\u003e, you are actually working with a Unicode string.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUnicode strings\u003c/strong\u003e are designed to \u003cem\u003estore text data\u003c/em\u003e. One of their key strengths is the ability to represent characters from a wide range of languages, including various symbols and special characters. Internally, Python uses Unicode to represent these strings, making them extremely versatile for text processing and manipulation. Whether you're simply working with plain English text or dealing with multiple languages and complex symbols, Unicode coding helps you make sure that your text data is consistently represented and manipulated within Python.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Depending on the build, Python uses either UTF-16 or UTF-32.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eOn the other hand, \u003cstrong\u003ebyte strings\u003c/strong\u003e are used in Python for \u003cem\u003ehandling raw binary data\u003c/em\u003e. When you face situations that require working directly with bytes - like dealing with binary files, network communication, or any form of low-level data manipulation - byte strings come into play. You can create a byte string by prefixing the string literal with \u003ccode\u003eb\u003c/code\u003e, as in \u003ccode\u003eb = b\u0026quot;bytes\u0026quot;\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eUnlike Unicode strings, byte strings are essentially sequences of bytes - integers in the range of 0-255 - and they don't inherently carry information about text encoding. They are the go-to solution when you need to work with data at the byte level, without the overhead or complexity of text encoding.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e\u003cstrong\u003eConversion between Unicode and byte strings\u003c/strong\u003e\u003c/em\u003e is a common requirement, and Python handles this through explicit encoding and decoding. When you need to convert a Unicode string into a byte string, you use the \u003ccode\u003e.encode()\u003c/code\u003e method along with specifying the encoding, like UTF-8. Conversely, turning a byte string into a Unicode string requires the \u003ccode\u003e.decode()\u003c/code\u003e method.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eLet's consider a practical example where we need to use both Unicode strings and byte strings in Python.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eImagine we have a simple text message in English that we want to send over a network. This message is initially in the form of a Unicode string, which is the default string type in Python 3.\u003c/p\u003e\n\u003cp\u003eFirst, we create our Unicode string:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003emessage = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello, World!\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis \u003ccode\u003emessage\u003c/code\u003e is a Unicode string, perfect for representing text data in Python. However, to send this message over a network, we often need to convert it to bytes, as network protocols typically work with byte streams.\u003c/p\u003e\n\u003cp\u003eWe can convert our Unicode string to a byte string using the \u003ccode\u003e.encode()\u003c/code\u003e method. Here, we'll use UTF-8 encoding, which is a common character encoding for Unicode text:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eencoded_message = message.encode(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;utf-8\u0026#x27;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow, \u003ccode\u003eencoded_message\u003c/code\u003e is a byte string. It's no longer in a format that is directly readable as text, but rather in a format suitable for transmission over a network or for writing to a binary file.\u003c/p\u003e\n\u003cp\u003eLet's say the message reaches its destination, and we need to convert it back to a Unicode string for reading. We can accomplish this by using the \u003ccode\u003e.decode()\u003c/code\u003e method:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003edecoded_message = encoded_message.decode(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;utf-8\u0026#x27;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWith \u003ccode\u003edecoded_message\u003c/code\u003e, we're back to a readable Unicode string, \u0026quot;Hello, World!\u0026quot;.\u003c/p\u003e\n\u003cp\u003eThis process of encoding and decoding is essential when dealing with data transmission or storage in Python, where the distinction between text (Unicode strings) and binary data (byte strings) is crucial. By converting our text data to bytes before transmission, and then back to text after receiving it, we ensure that our data remains consistent and uncorrupted across different systems and processing stages.\u003c/p\u003e\n\u003ch3 id=\"rawstrings\"\u003eRaw Strings\u003c/h3\u003e\n\u003cp\u003eRaw strings are a unique form of string representation that can be particularly useful when dealing with strings that contain many backslashes, like file paths or regular expressions. Unlike normal strings, raw strings treat backslashes (\u003ccode\u003e\\\u003c/code\u003e) as literal characters, not as escape characters. This makes them incredibly handy when you don't want Python to handle backslashes in any special way.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eRaw strings are useful when dealing with regular expressions or any string that may contain backslashes (\u003ccode\u003e\\\u003c/code\u003e), as they treat backslashes as literal characters.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eIn a standard Python string, a backslash signals the start of an escape sequence, which Python interprets in a specific way. For example, \u003ccode\u003e\\n\u003c/code\u003e is interpreted as a newline, and \u003ccode\u003e\\t\u003c/code\u003e as a tab. This is useful in many contexts but can become problematic when your string contains many backslashes and you want them to remain as literal backslashes.\u003c/p\u003e\n\u003cp\u003eA raw string is created by \u003cem\u003eprefixing the string literal with an 'r' or 'R'\u003c/em\u003e. This tells Python to ignore all escape sequences and treat backslashes as regular characters. For example, consider a scenario where you need to define a file path in Windows, which uses backslashes in its paths:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003epath = \u003cspan class=\"hljs-string\"\u003er\u0026quot;C:\\Users\\YourName\\Documents\\File.txt\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, using a raw string prevents Python from interpreting \u003ccode\u003e\\U\u003c/code\u003e, \u003ccode\u003e\\Y\u003c/code\u003e, \u003ccode\u003e\\D\u003c/code\u003e, and \u003ccode\u003e\\F\u003c/code\u003e as escape sequences. If you used a normal string (without the 'r' prefix), Python would try to interpret these as escape sequences, leading to errors or incorrect strings.\u003c/p\u003e\n\u003cp\u003eAnother common use case for raw strings is in \u003cem\u003eregular expressions\u003c/em\u003e. Regular expressions use backslashes for special characters, and using raw strings here can make your regex patterns much more readable and maintainable:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e re\n\npattern = \u003cspan class=\"hljs-string\"\u003er\u0026quot;\\b[A-Z]+\\b\u0026quot;\u003c/span\u003e\ntext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;HELLO, how ARE you?\u0026quot;\u003c/span\u003e\nmatches = re.findall(pattern, text)\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(matches) \u003cspan class=\"hljs-comment\"\u003e# Output: [\u0026#x27;HELLO\u0026#x27;, \u0026#x27;ARE\u0026#x27;]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe raw string \u003ccode\u003er\u0026quot;\\b[A-Z]+\\b\u0026quot;\u003c/code\u003e represents a regular expression that looks for \u003cem\u003ewhole words composed of uppercase letters\u003c/em\u003e. Without the raw string notation, you would have to escape each backslash with another backslash (\u003ccode\u003e\\\\b[A-Z]+\\\\b\u003c/code\u003e), which is less readable.\u003c/p\u003e\n\u003ch3 id=\"multilinestrings\"\u003eMultiline Strings\u003c/h3\u003e\n\u003cp\u003eMultiline strings in Python are a convenient way to handle \u003cem\u003etext data that spans several lines\u003c/em\u003e. These strings are enclosed within triple quotes, either triple single quotes (\u003ccode\u003e'''\u003c/code\u003e) or triple double quotes (\u003ccode\u003e\u0026quot;\u0026quot;\u0026quot;\u003c/code\u003e).\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis approach is often used for creating long strings, docstrings, or even for formatting purposes within the code.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eUnlike single or double-quoted strings, which end at the first line break, multiline strings allow the text to continue over several lines, preserving the line breaks and white spaces within the quotes.\u003c/p\u003e\n\u003cp\u003eLet's consider a practical example to illustrate the use of multiline strings. Suppose you are writing a program that requires a long text message or a formatted output, like a paragraph or a poem. Here's how you might use a multiline string for this purpose:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003elong_text = \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026quot;\u0026quot;\nThis is a multiline string in Python.\nIt spans several lines, maintaining the line breaks\nand spaces just as they are within the triple quotes.\n\n You can also create indented lines within it,\nlike this one!\n\u0026quot;\u0026quot;\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(long_text)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWhen you run this code, Python will output the entire block of text exactly as it's formatted within the triple quotes, including all the line breaks and spaces. This makes multiline strings particularly useful for writing text that needs to maintain its format, such as when generating formatted emails, long messages, or even code documentation.\u003c/p\u003e\n\u003cp\u003eIn Python, multiline strings are also commonly used for \u003cem\u003edocstrings\u003c/em\u003e. Docstrings provide a convenient way to document your Python classes, functions, modules, and methods. They are written immediately after the definition of a function, class, or a method and are enclosed in triple quotes:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003emy_function\u003c/span\u003e():\u003c/span\u003e\n \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026quot;\u0026quot;\n This is a docstring for the my_function.\n It can provide an explanation of what the function does,\n its parameters, return values, and more.\n \u0026quot;\u0026quot;\u0026quot;\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003epass\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWhen you use the built-in \u003ccode\u003ehelp()\u003c/code\u003e function on \u003ccode\u003emy_function\u003c/code\u003e, Python will display the text in the docstring as the documentation for that function.\u003c/p\u003e\n\u003ch3 id=\"regularexpressions\"\u003eRegular Expressions\u003c/h3\u003e\n\u003cp\u003eRegular expressions in Python, facilitated by the \u003ccode\u003ere\u003c/code\u003e module, are a powerful tool for pattern matching and manipulation of strings. They provide a concise and flexible means for matching strings of text, such as particular characters, words, or patterns of characters.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eRegular expressions are used for a wide range of tasks including validation, parsing, and string manipulation.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eAt the core of regular expressions are patterns that are matched against strings. These patterns are expressed in a specialized syntax that allows you to define what you're looking for in a string. Python's \u003ccode\u003ere\u003c/code\u003e module supports a set of functions and syntax that adhere to regular expression rules.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-reference\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-link-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eAdvice:\u003c/strong\u003e If you want to have more comprehensive insight into regular expressions in Python, you should definitely read our \u003ca href=\"https://stackabuse.com/introduction-to-regular-expressions-in-python/\" target=\"_blank\"\u003e\u0026quot;Introduction to Regular Expressions in Python\u0026quot;\u003c/a\u003e article.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eSome of the key functions in the \u003ccode\u003ere\u003c/code\u003e module include:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003ere.match()\u003c/strong\u003e: Determines if the regular expression matches at the beginning of the string.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ere.search()\u003c/strong\u003e: Scans through the string and returns a Match object if the pattern is found anywhere in the string.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ere.findall()\u003c/strong\u003e: Finds all occurrences of the pattern in the string and returns them as a list.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ere.finditer()\u003c/strong\u003e: Similar to \u003ccode\u003ere.findall()\u003c/code\u003e, but returns an iterator yielding Match objects instead of the strings.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ere.sub()\u003c/strong\u003e: Replaces occurrences of the pattern in the string with a replacement string.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eTo use regular expressions in Python, you typically follow these steps:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eImport the \u003ccode\u003ere\u003c/code\u003e module.\u003c/li\u003e\n\u003cli\u003eDefine the regular expression pattern as a string.\u003c/li\u003e\n\u003cli\u003eUse one of the \u003ccode\u003ere\u003c/code\u003e module's functions to search or manipulate the string using the pattern.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eHere's a practical example to demonstrate these steps:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e re\n\n\u003cspan class=\"hljs-comment\"\u003e# Sample text\u003c/span\u003e\ntext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;The rain in Spain falls mainly in the plain.\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Regular expression pattern to find all words that start with \u0026#x27;S\u0026#x27; or \u0026#x27;s\u0026#x27;\u003c/span\u003e\npattern = \u003cspan class=\"hljs-string\"\u003er\u0026quot;\\bs\\w*\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e# The r before the string makes it a raw string\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Using re.findall() to find all occurrences\u003c/span\u003e\nfound_words = re.findall(pattern, text, re.IGNORECASE)\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(found_words) \u003cspan class=\"hljs-comment\"\u003e# Output: [\u0026#x27;Spain\u0026#x27;, \u0026#x27;spain\u0026#x27;]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this example:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003er\u0026quot;\\bs\\w*\u0026quot;\u003c/code\u003e is the regular expression pattern. \u003ccode\u003e\\b\u003c/code\u003e indicates a word boundary, \u003ccode\u003es\u003c/code\u003e is the literal character 's', and \u003ccode\u003e\\w*\u003c/code\u003e matches any word character (letters, digits, or underscores) zero or more times.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ere.IGNORECASE\u003c/code\u003e is a flag that makes the search case-insensitive.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ere.findall()\u003c/code\u003e searches the string \u003ccode\u003etext\u003c/code\u003e for all occurrences that match the pattern.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eRegular expressions are extremely versatile but can be complex for intricate patterns. It's important to carefully craft your regular expression for accuracy and efficiency, especially for complex string processing tasks.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-reference\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-link-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eAdvice:\u003c/strong\u003e One of the interesting use cases for regular expressions is matching phone numbers. You can read more about that in our \u003ca href=\"https://stackabuse.com/python-regular-expressions-validate-phone-numbers/\" target=\"_blank\"\u003e\u0026quot;Python Regular Expressions - Validate Phone Numbers\u0026quot;\u003c/a\u003e article.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch2 id=\"stringsandcollections\"\u003eStrings and Collections\u003c/h2\u003e\n\u003cp\u003eIn Python, strings and collections (like lists, tuples, and dictionaries) \u003cem\u003eoften interact\u003c/em\u003e, either through conversion of one type to another or by manipulating strings using methods influenced by collection operations. Understanding how to efficiently work with strings and collections is crucial for tasks like data parsing, text processing, and more.\u003c/p\u003e\n\u003ch3 id=\"splittingstringsintolists\"\u003eSplitting Strings into Lists\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003esplit()\u003c/code\u003e method is used to divide a string into a list of substrings. It's particularly useful for parsing CSV files or user input:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003etext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;apple,banana,cherry\u0026quot;\u003c/span\u003e\nfruits = text.split(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;,\u0026#x27;\u003c/span\u003e)\n\u003cspan class=\"hljs-comment\"\u003e# fruits is now [\u0026#x27;apple\u0026#x27;, \u0026#x27;banana\u0026#x27;, \u0026#x27;cherry\u0026#x27;]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"joininglistelementsintoastring\"\u003eJoining List Elements into a String\u003c/h3\u003e\n\u003cp\u003eConversely, the \u003ccode\u003ejoin()\u003c/code\u003e method combines a list of strings into a single string, with a specified separator:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003efruits = [\u003cspan class=\"hljs-string\"\u003e\u0026#x27;apple\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;banana\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;cherry\u0026#x27;\u003c/span\u003e]\ntext = \u003cspan class=\"hljs-string\"\u003e\u0026#x27;, \u0026#x27;\u003c/span\u003e.join(fruits)\n\u003cspan class=\"hljs-comment\"\u003e# text is now \u0026#x27;apple, banana, cherry\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"stringanddictionaryinteractions\"\u003eString and Dictionary Interactions\u003c/h3\u003e\n\u003cp\u003eStrings can be used to create dynamic dictionary keys, and format strings using dictionary values:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003einfo = {\u003cspan class=\"hljs-string\"\u003e\u0026quot;name\u0026quot;\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;age\u0026quot;\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e30\u003c/span\u003e}\ntext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Name: {name}, Age: {age}\u0026quot;\u003c/span\u003e.\u003cspan class=\"hljs-built_in\"\u003eformat\u003c/span\u003e(**info)\n\u003cspan class=\"hljs-comment\"\u003e# text is now \u0026#x27;Name: Alice, Age: 30\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"listcomprehensionswithstrings\"\u003eList Comprehensions with Strings\u003c/h3\u003e\n\u003cp\u003eList comprehensions can include string operations, allowing for concise manipulation of strings within collections:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ewords = [\u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;world\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;python\u0026quot;\u003c/span\u003e]\nupper_words = [word.upper() \u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e word \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e words]\n\u003cspan class=\"hljs-comment\"\u003e# upper_words is now [\u0026#x27;HELLO\u0026#x27;, \u0026#x27;WORLD\u0026#x27;, \u0026#x27;PYTHON\u0026#x27;]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"mappingandfilteringstringsincollections\"\u003eMapping and Filtering Strings in Collections\u003c/h3\u003e\n\u003cp\u003eUsing functions like \u003ccode\u003emap()\u003c/code\u003e and \u003ccode\u003efilter()\u003c/code\u003e, you can apply string methods or custom functions to collections:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ewords = [\u003cspan class=\"hljs-string\"\u003e\u0026quot;Hello\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;world\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;python\u0026quot;\u003c/span\u003e]\nlengths = \u003cspan class=\"hljs-built_in\"\u003emap\u003c/span\u003e(\u003cspan class=\"hljs-built_in\"\u003elen\u003c/span\u003e, words)\n\u003cspan class=\"hljs-comment\"\u003e# lengths is now an iterator of [5, 5, 6]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"slicingandindexingstringsincollections\"\u003eSlicing and Indexing Strings in Collections\u003c/h3\u003e\n\u003cp\u003eYou can slice and index strings in collections in a similar way to how you do with individual strings:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eword_list = [\u003cspan class=\"hljs-string\"\u003e\u0026quot;apple\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;banana\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;cherry\u0026quot;\u003c/span\u003e]\nfirst_letters = [word[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e] \u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e word \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e word_list]\n\u003cspan class=\"hljs-comment\"\u003e# first_letters is now [\u0026#x27;a\u0026#x27;, \u0026#x27;b\u0026#x27;, \u0026#x27;c\u0026#x27;]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"usingtuplesasstringformatspecifiers\"\u003eUsing Tuples as String Format Specifiers\u003c/h3\u003e\n\u003cp\u003eTuples can be used to specify format specifiers dynamically in string formatting:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eformat_spec = (\u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e30\u003c/span\u003e)\ntext = \u003cspan class=\"hljs-string\"\u003e\u0026quot;Name: %s, Age: %d\u0026quot;\u003c/span\u003e % format_spec\n\u003cspan class=\"hljs-comment\"\u003e# text is now \u0026#x27;Name: Alice, Age: 30\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"stringperformanceconsiderations\"\u003eString Performance Considerations\u003c/h2\u003e\n\u003cp\u003eWhen working with strings in Python, it's important to consider their performance implications, especially in large-scale applications, data processing tasks, or situations where efficiency is critical. In this section, we'll take a look at some key performance considerations and best practices for handling strings in Python.\u003c/p\u003e\n\u003ch3 id=\"immutabilityofstrings\"\u003eImmutability of Strings\u003c/h3\u003e\n\u003cp\u003eSince strings are immutable in Python, \u003cem\u003eeach time you modify a string, a new string is created\u003c/em\u003e. This can lead to \u003cstrong\u003esignificant memory usage\u003c/strong\u003e and reduced performance in scenarios involving extensive string manipulation.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eTo mitigate this, when dealing with large amounts of string concatenations, it's often more efficient to use list comprehension or the \u003ccode\u003ejoin()\u003c/code\u003e method instead of repeatedly using \u003ccode\u003e+\u003c/code\u003e or \u003ccode\u003e+=\u003c/code\u003e.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eFor example, it would be more efficient to join a large list of strings instead of concatenating it using the \u003ccode\u003e+=\u003c/code\u003e operator:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Inefficient\u003c/span\u003e\nresult = \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e s \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e large_list_of_strings:\n result += s\n\n\u003cspan class=\"hljs-comment\"\u003e# More efficient\u003c/span\u003e\nresult = \u003cspan class=\"hljs-string\"\u003e\u0026quot;\u0026quot;\u003c/span\u003e.join(large_list_of_strings)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eGenerally speaking, concatenating strings using the \u003ccode\u003e+\u003c/code\u003e operator in a loop is inefficient, especially for large datasets. Each concatenation creates a new string and thus, requires more memory and time.\u003c/p\u003e\n\u003ch3 id=\"usefstringsforformatting\"\u003eUse f-Strings for Formatting\u003c/h3\u003e\n\u003cp\u003ePython 3.6 introduced f-Strings, which are not only more readable but also faster at runtime compared to other string formatting methods like \u003ccode\u003e%\u003c/code\u003e formatting or \u003ccode\u003estr.format()\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"avoidunnecessarystringoperations\"\u003eAvoid Unnecessary String Operations\u003c/h3\u003e\n\u003cp\u003eOperations like \u003ccode\u003estrip()\u003c/code\u003e, \u003ccode\u003ereplace()\u003c/code\u003e, or \u003ccode\u003eupper()\u003c/code\u003e/\u003ccode\u003elower()\u003c/code\u003e create new string objects. It's advisable to avoid these operations in critical performance paths unless necessary.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWhen processing large text data, consider whether you can operate on larger chunks of data at once, rather than processing the string one character or line at a time.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"stringinterning\"\u003eString Interning\u003c/h3\u003e\n\u003cp\u003ePython automatically interns small strings (usually those that look like identifiers) to save memory and improve performance. This means that identical strings may be stored in memory only once.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eExplicit interning of strings (\u003ccode\u003esys.intern()\u003c/code\u003e) can sometimes be beneficial in memory-sensitive applications where many identical string instances are used.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"usebuiltinfunctionsandlibraries\"\u003eUse Built-in Functions and Libraries\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eLeverage Python’s built-in functions and libraries for string processing, as they are generally optimized for performance.\u003c/li\u003e\n\u003cli\u003eFor complex string operations, especially those involving pattern matching, consider using the \u003ccode\u003ere\u003c/code\u003e module (regular expressions) which is faster for matching operations compared to manual string manipulation.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--## Conclusion\n\nThis ends our journey through the world of strings in Python that has hopefully been extensive and illuminating. We began by understanding the basics of creating and manipulating strings, exploring how they are indexed, concatenated, and how their immutable nature influences operations in Python. This immutability, a core characteristic of Python strings, ensures security and efficiency in Python's design.\n\nDiving into the array of built-in string methods, we uncovered the versatility of Python in handling common tasks such as case conversion, trimming, searching, and sophisticated formatting. We also examined the various ways Python allows for string formatting, from the traditional `%` operator to the more modern `str.format()` method, and the concise and powerful f-Strings introduced in Python 3.6.\n\nOur exploration then took us to the substrings, where slicing and manipulating parts of strings revealed Python's flexibility and power in handling string data. We further ventured into advanced string techniques, discussing the handling of Unicode, the utility of raw strings, and the powerful capabilities of regular expressions for complex string manipulations.\n\nThe interaction between strings and collections such as lists, tuples, and dictionaries showcased the dynamic ways in which strings can be converted and manipulated within these structures. This interaction is pivotal in tasks ranging from parsing and formatting data to complex data transformations.\n\nLastly, we peaked into the critical aspect of string performance considerations. We discussed the importance of understanding and applying efficient string handling techniques, emphasizing practices that enhance performance, reduce memory usage, and ensure the scalability of Python applications.\n\nOverall, this comprehensive overview underscores that strings, as a fundamental data type, are integral to programming in Python. They are involved in almost every aspect of programming, from simple text manipulation to complex data processing. With the insights and techniques discussed, you are now better equipped to tackle a wide range of programming challenges, making informed choices about how to effectively and efficiently handle strings in Python.\n\n--\u003e","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"read_time_min":111,"published_at":1706209844433,"created_at":1706206300776,"updated_at":1713452066158,"tags":[{"id":9,"name":"python","slug":"python","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1431358631000,"updated_at":1431358631000,"_pivot_content_id":2126,"_pivot_tag_id":9,"_pivot_sort_order":0}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2126,"_pivot_user_id":1,"_pivot_role":"editor","_pivot_sort_order":1},{"id":94,"name":"Dimitrije Stamenic","slug":"stamd","role_id":4,"img_profile":"https://s3.amazonaws.com/s3.stackabuse.com/media/users/91dc45351236146b499e059557c35823.png","img_cover":null,"bio_html":"","website":"https://www.linkedin.com/in/stamd/","location":"Belgrade, Serbia","facebook":null,"twitter":"stamenic_d","github":"stamd","created_at":1618418516000,"updated_at":1703355178722,"role":"editor","_pivot_content_id":2126,"_pivot_user_id":94,"_pivot_role":"author","_pivot_sort_order":0}],"_pivot_user_id":1,"_pivot_content_id":2126},{"id":2125,"title":"Behind the Scenes: Never Trust User Input","slug":"behind-the-scenes-never-trust-user-input","body_html":"\u003cp\u003e\u003csmall\u003e\u003cem\u003eThis article is the first in a series of posts I'm writing about running various SaaS products and websites for the last 8 years. I'll be sharing some of the issues I've dealt with, lessons I've learned, mistakes I've made, and maybe a few things that went right. \u003ca target=\"_blank\" href=\"https://twitter.com/ScottWRobinson\"\u003eLet me know\u003c/a\u003e what you think!\u003c/em\u003e\u003c/small\u003e\u003c/p\u003e\n\u003cp\u003eBack in 2019 or 2020, I had decided to rewrite the entire backend for \u003ca href=\"https://blocksender.io/\"\u003eBlock Sender\u003c/a\u003e, a SaaS application that helps users create better email blocks, among other features. In the process, I added a few new features and upgraded to much more modern technologies. I ran the tests, deployed the code, manually tested everything in production, and other than a few random odds and ends, everything seemed to be working great. I wish this was the end of the story, but...\u003c/p\u003e\n\u003cp\u003eA few weeks later, I was notified by a customer (which is embarrassing in itself) that the service wasn't working and they were getting lots of should-be-blocked emails in their inbox, so I investigated. Many times this issue is due to Google removing the connection from our service to the user's account, which the system handles by notifying the user via email and asking them to reconnect, but this time it was something else.\u003c/p\u003e\n\u003cp\u003eIt looked like the backend worker that handles checking emails against user blocks kept crashing every 5-10 minutes. The weirdest part - there were no errors in the logs, memory was fine, but the CPU would occasionally spike at seemingly random times. So for the next 24 hours (with a 3-hour break to sleep - sorry customers 😬), I had to manually restart the worker every time it crashed. For some reason, the Elastic Beanstalk service was waiting far too long to restart, which is why I had to do it manually.\u003c/p\u003e\n\u003cp\u003eDebugging issues in production is always a pain, especially since I couldn't reproduce the issue locally, let alone figure out what was causing it. So like any \u0026quot;good\u0026quot; developer, I just started logging \u003cem\u003eeverything\u003c/em\u003e and waited for the server to crash again. Since the CPU was spiking periodically, I figured it wasn't a macro issue (like when you run out of memory) and was probably being caused by a specific email or user. So I tried to narrow it down:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eWas it crashing on a certain email ID or type?\u003c/li\u003e\n\u003cli\u003eWas it crashing for a given customer?\u003c/li\u003e\n\u003cli\u003eWas it crashing at some regular interval?\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAfter hours of this, and staring at logs longer than I'd care to, eventually, I did narrow it down to a specific customer. From there, the search space narrowed quite a bit - it was most likely a blocking rule or a specific email our server kept retrying on. Luckily for me, it was the former, which is a far easier problem to debug given that we're a very privacy-focused company and don't store or view any email data.\u003c/p\u003e\n\u003cp\u003eBefore we get into the exact problem, let's first talk about one of Block Sender's features. At the time I had many customers asking for wildcard blocking, which would allow them to block certain types of email addresses that followed the same pattern. For example, if you wanted to block all emails from marketing email addresses, you could use the wildcard \u003ccode\u003emarketing@*\u003c/code\u003e and it would block all emails from any address that started with \u003ccode\u003emarketing@\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eOne thing I didn't think about is that not everyone understands how wildcards work. I assumed that most people would use them in the same way I do as a developer, using one \u003ccode\u003e*\u003c/code\u003e to represent any number of characters. Unfortunately, this particular user had assumed you needed to use \u003cem\u003eone wildcard for each character you wanted to match\u003c/em\u003e. In their case, they wanted to block all emails from a certain domain (which is a native feature Block Sender has, but they must not have realized it, which is a whole problem in itself). So instead of using \u003ccode\u003e*@example.com\u003c/code\u003e, they used \u003ccode\u003e**********@example.com\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/behind-the-scenes-never-trust-user-input-1.gif\" alt=\"POV: Watching your users use your app...\"\u003e\u003cbr\u003e\n\u003csmall\u003ePOV: Watching your users use your app...\u003c/small\u003e\u003c/p\u003e\n\u003cp\u003eTo handle wildcards on our worker server, we're using the Node.js library \u003ca target=\"_blank\" rel=\"nofollow noopener\" href=\"https://www.npmjs.com/package/matcher\"\u003ematcher\u003c/a\u003e, which helps with glob matching by turning it into a regular expression. This library would then turn \u003ccode\u003e**********@example.com\u003c/code\u003e into something like the following regex:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e/[\\s\\S]*[\\s\\S]*[\\s\\S]*[\\s\\S]*[\\s\\S]*[\\s\\S]*[\\s\\S]*[\\s\\S]*[\\s\\S]*[\\s\\S]*@example\\.com/i\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf you have any experience with regex, you know that they can get very complicated very quickly, especially on a computational level. Matching the above expression to any reasonable length of text becomes very computationally expensive, which ended up tying up the CPU on our worker server. \u003cstrong\u003eThis is why the server would crash every few minutes; it would get stuck trying to match a complex regular expression to an email address\u003c/strong\u003e. So every time this user received an email, in addition to all of the retries we built in to handle temporary failures, it would crash our server.\u003c/p\u003e\n\u003cp\u003eSo how did I fix this? Obviously, the quick fix was to find all blocks with multiple wildcards in succession and correct them. But I also needed to do a better job of sanitizing user input. Any user could enter a regex and take down the entire system with a \u003ca target=\"_blank\" rel=\"nofollow noopener\" href=\"https://en.wikipedia.org/wiki/ReDoS\"\u003eReDoS attack\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eHandling this particular case was fairly simple - remove successive wildcard characters:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eblock = block.replace(\u003cspan class=\"hljs-regexp\"\u003e/\\*+/g\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;*\u0026#x27;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eBut that still leaves the app open to other types of ReDoS attacks. Luckily there are a number of packages/libraries to help us with these types as well:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca target=\"_blank\" rel=\"nofollow noopener\" href=\"https://www.npmjs.com/package/safe-regex\"\u003esafe-regex\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca target=\"_blank\" rel=\"nofollow noopener\" href=\"https://github.com/superhuman/rxxr2\"\u003erxxr2\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eUsing a combination of the solutions above, and other safeguards, I've been able to prevent this from happening again. But it was a good reminder that you can never trust user input, and you should always sanitize it before using it in your application. I wasn't even aware this was a potential issue until it happened to me, so hopefully, this helps someone else avoid the same problem.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eHave any questions, comments, or want to share a story of your own? Reach out on \u003ca target=\"_blank\" href=\"https://twitter.com/ScottWRobinson\"\u003eTwitter\u003c/a\u003e!\u003c/em\u003e\u003c/p\u003e\n","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"read_time_min":8,"published_at":1702582079869,"created_at":1702571048996,"updated_at":1702582084632,"tags":[{"id":268,"name":"SaaS","slug":"saas","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1702581678858,"updated_at":1702581678858,"_pivot_content_id":2125,"_pivot_tag_id":268,"_pivot_sort_order":0}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2125,"_pivot_user_id":1,"_pivot_role":"author","_pivot_sort_order":1}],"_pivot_user_id":1,"_pivot_content_id":2125},{"id":2064,"title":"Guide to Heaps in Python","slug":"guide-to-heaps-in-python","body_html":"\u003cp\u003eIn this guide, we'll embark on a journey to understand heaps from the ground up. We'll start by demystifying what heaps are and their inherent properties. From there, we'll dive into Python's own implementation of heaps, the \u003ccode\u003eheapq\u003c/code\u003e module, and explore its rich set of functionalities. So, if you've ever wondered how to efficiently manage a dynamic set of data where the highest (or lowest) priority element is frequently needed, you're in for a treat.\u003c/p\u003e\n\u003ch3 id=\"whatisaheap\"\u003eWhat is a Heap?\u003c/h3\u003e\n\u003cp\u003eThe first thing you'd want to understand before diving into the usage of heaps is \u003cem\u003ewhat is a heap\u003c/em\u003e. A heap stands out in the world of data structures as a tree-based powerhouse, particularly skilled at \u003cstrong\u003emaintaining order and hierarchy\u003c/strong\u003e. While it might resemble a binary tree to the untrained eye, the nuances in its structure and governing rules distinctly set it apart.\u003c/p\u003e\n\u003cp\u003eOne of the defining characteristics of a heap is its nature as a \u003cem\u003e\u003cstrong\u003ecomplete binary tree\u003c/strong\u003e\u003c/em\u003e. This means that every level of the tree, except perhaps the last, is entirely filled. Within this last level, nodes populate from left to right. Such a structure ensures that heaps can be efficiently represented and manipulated using arrays or lists, with each element's position in the array mirroring its placement in the tree.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/guide-to-heaps-in-python-1.png\" alt=\"guide-to-heaps-in-python-01.png\"\u003e\u003c/p\u003e\n\u003cp\u003eThe true essence of a heap, however, lies in its \u003cem\u003e\u003cstrong\u003eordering\u003c/strong\u003e\u003c/em\u003e. In a \u003cem\u003emax heap\u003c/em\u003e, any given node's value surpasses or equals the values of its children, positioning the largest element right at the root. On the other hand, a \u003cem\u003emin heap\u003c/em\u003e operates on the opposite principle: any node's value is either less than or equal to its children's values, ensuring the smallest element sits at the root.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/guide-to-heaps-in-python-2.png\" alt=\"guide-to-heaps-in-python-02.png\"\u003e\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eAdvice:\u003c/strong\u003e You can visualize a heap as a \u003cem\u003epyramid of numbers\u003c/em\u003e. For a max heap, as you ascend from the base to the peak, the numbers increase, culminating in the maximum value at the pinnacle. In contrast, a min heap starts with the minimum value at its peak, with numbers escalating as you move downwards.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eAs we progress, we'll dive deeper into how these inherent properties of heaps enable efficient operations and how Python's \u003ccode\u003eheapq\u003c/code\u003e module seamlessly integrates heaps into our coding endeavors.\u003c/p\u003e\n\u003ch3 id=\"characteristicsandpropertiesofheaps\"\u003eCharacteristics and Properties of Heaps\u003c/h3\u003e\n\u003cp\u003eHeaps, with their unique structure and ordering principles, bring forth a set of distinct characteristics and properties that make them invaluable in various computational scenarios.\u003c/p\u003e\n\u003cp\u003eFirst and foremost, heaps are \u003cstrong\u003einherently efficient\u003c/strong\u003e. Their tree-based structure, specifically the complete binary tree format, ensures that operations like insertion and extraction of priority elements (maximum or minimum) can be performed in logarithmic time, typically \u003cem\u003eO(log n)\u003c/em\u003e. This efficiency is a boon for algorithms and applications that require frequent access to priority elements.\u003c/p\u003e\n\u003cp\u003eAnother notable property of heaps is their \u003cstrong\u003ememory efficiency\u003c/strong\u003e. Since heaps can be represented using arrays or lists without the need for explicit pointers to child or parent nodes, they are space-saving. Each element's position in the array corresponds to its placement in the tree, allowing for predictable and straightforward traversal and manipulation.\u003c/p\u003e\n\u003cp\u003eThe ordering property of heaps, whether as a max heap or a min heap, ensures that \u003cstrong\u003ethe root always holds the element of highest priority\u003c/strong\u003e. This consistent ordering is what allows for quick access to the top-priority element without having to search through the entire structure.\u003c/p\u003e\n\u003cp\u003eFurthermore, heaps are \u003cstrong\u003eversatile\u003c/strong\u003e. While binary heaps (where each parent has at most two children) are the most common, heaps can be generalized to have more than two children, known as \u003cem\u003ed-ary heaps\u003c/em\u003e. This flexibility allows for fine-tuning based on specific use cases and performance requirements.\u003c/p\u003e\n\u003cp\u003eLastly, heaps are \u003cstrong\u003eself-adjusting\u003c/strong\u003e. Whenever elements are added or removed, the structure rearranges itself to maintain its properties. This dynamic balancing ensures that the heap remains optimized for its core operations at all times.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-reference\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-link-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eAdvice:\u003c/strong\u003e These properties made heap data structure a good fit for an efficient sorting algorithm - heap sort. To learn more about heap sort in Python, read our \u003ca target=\"_blank\" href=\"https://stackabuse.com/heap-sort-in-python/\"\u003e\u0026quot;Heap Sort in Python\u0026quot;\u003c/a\u003e article.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eAs we delve deeper into Python's implementation and practical applications, the true potential of heaps will unfold before us.\u003c/p\u003e\n\u003ch3 id=\"typesofheaps\"\u003eTypes of Heaps\u003c/h3\u003e\n\u003cp\u003eNot all heaps are created equal. Depending on their ordering and structural properties, heaps can be categorized into different types, each with its own set of applications and advantages. The two main categories are \u003cem\u003emax heap\u003c/em\u003e and \u003cem\u003emin heap\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003eThe most distinguishing feature of a \u003cstrong\u003emax heap\u003c/strong\u003e is that the value of any given node is greater than or equal to the values of its children. This ensures that the largest element in the heap always resides at the root. Such a structure is particularly useful when there's a need to frequently access the maximum element, as in certain priority queue implementations.\u003c/p\u003e\n\u003cp\u003eThe counterpart to the max heap, a \u003cstrong\u003emin heap\u003c/strong\u003e ensures that the value of any given node is less than or equal to the values of its children. This positions the smallest element of the heap at the root. Min heaps are invaluable in scenarios where the least element is of prime importance, such as in algorithms that deal with real-time data processing.\u003c/p\u003e\n\u003cp\u003eBeyond these primary categories, heaps can also be distinguished based on their branching factor:\u003c/p\u003e\n\u003cp\u003eWhile binary heaps are the most common, with each parent having at most two children, the concept of heaps can be extended to nodes having more than two children. In a \u003cstrong\u003ed-ary heap\u003c/strong\u003e, each node has at most \u003ccode\u003ed\u003c/code\u003e children. This variation can be optimized for specific scenarios, like decreasing the height of the tree to speed up certain operations.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eBinomial Heap\u003c/strong\u003e is a set of binomial trees that are defined recursively. Binomial heaps are used in priority queue implementations and offer efficient merge operations.\u003c/p\u003e\n\u003cp\u003eNamed after the famous Fibonacci sequence, the \u003cstrong\u003eFibonacci heap\u003c/strong\u003e offers better-amortized running times for many operations compared to binary or binomial heaps. They're particularly useful in network optimization algorithms.\u003c/p\u003e\n\u003ch3 id=\"pythonsheapimplementationtheheapqmodule\"\u003ePython's Heap Implementation - The \u003cem\u003eheapq\u003c/em\u003e Module\u003c/h3\u003e\n\u003cp\u003ePython offers a built-in module for heap operations - the \u003ccode\u003eheapq\u003c/code\u003e module. This module provides a collection of heap-related functions that allow developers to transform lists into heaps and perform various heap operations without the need for a custom implementation. Let's dive into the nuances of this module and how it brings you the power of heaps.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003eheapq\u003c/code\u003e module doesn't provide a distinct heap data type. Instead, it offers functions that work on regular Python lists, transforming and treating them as \u003cem\u003ebinary heaps\u003c/em\u003e.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis approach is both memory-efficient and integrates seamlessly with Python's existing data structures.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThat means that \u003cem\u003eheaps are represented as lists\u003c/em\u003e in \u003ccode\u003eheapq\u003c/code\u003e. The beauty of this representation is its simplicity - the zero-based list index system serves as an implicit binary tree. For any given element at position \u003ccode\u003ei\u003c/code\u003e, its:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLeft Child is at position \u003ccode\u003e2*i + 1\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eRight Child is at position \u003ccode\u003e2*i + 2\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eParent Node is at position \u003ccode\u003e(i-1)//2\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/guide-to-heaps-in-python-3.png\" alt=\"guide-to-heaps-in-python-03.png\"\u003e\u003c/p\u003e\n\u003cp\u003eThis implicit structure ensures that there's no need for a separate node-based binary tree representation, making operations straightforward and memory usage minimal.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eSpace Complexity:\u003c/strong\u003e Heaps are typically implemented as binary trees but don't require storage of explicit pointers for child nodes. This makes them space-efficient with a space complexity of \u003cem\u003eO(n)\u003c/em\u003e for storing n elements.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eIt's essential to note that the \u003ccode\u003eheapq\u003c/code\u003e module \u003cstrong\u003ecreates min heaps by default\u003c/strong\u003e. This means that the smallest element is always at the root (or the first position in the list). If you need a max heap, you'd have to invert order by multiplying elements by \u003ccode\u003e-1\u003c/code\u003e or use a custom comparison function.\u003c/p\u003e\n\u003cp\u003ePython's \u003ccode\u003eheapq\u003c/code\u003e module provides a suite of functions that allow developers to perform various heap operations on lists.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e To use the \u003ccode\u003eheapq\u003c/code\u003e module in your application, you'll need to import it using simple \u003ccode\u003eimport heapq\u003c/code\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eIn the following sections, we'll dive deep into each of these fundamental operations, exploring their mechanics and use cases.\u003c/p\u003e\n\u003ch3 id=\"howtotransformalistintoaheap\"\u003eHow to Transform a List into a Heap\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003eheapify()\u003c/code\u003e function is the starting point for many heap-related tasks. It takes an iterable (typically a list) and rearranges its elements in-place to satisfy the properties of a min heap:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e heapq\n\ndata = [\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e9\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e6\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e]\nheapq.heapify(data)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(data)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will output a reordered list that represents a valid min heap:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e[1, 1, 2, 3, 3, 9, 4, 6, 5, 5, 5]\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eTime Complexity:\u003c/strong\u003e Converting an unordered list into a heap using the \u003ccode\u003eheapify\u003c/code\u003e function is an \u003cem\u003eO(n)\u003c/em\u003e operation. This might seem counterintuitive, as one might expect it to be \u003cem\u003eO(nlogn)\u003c/em\u003e, but due to the tree structure's properties, it can be achieved in linear time.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"howtoaddanelementtotheheap\"\u003eHow to Add an Element to the Heap\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003eheappush()\u003c/code\u003e function allows you to insert a new element into the heap while maintaining the heap's properties:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e heapq\n\nheap = []\nheapq.heappush(heap, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e)\nheapq.heappush(heap, \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e)\nheapq.heappush(heap, \u003cspan class=\"hljs-number\"\u003e7\u003c/span\u003e)\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heap)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eRunning the code will give you a list of elements maintaining the min heap property:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e[3, 5, 7]\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eTime Complexity:\u003c/strong\u003e The insertion operation in a heap, which involves placing a new element in the heap while maintaining the heap property, has a time complexity of \u003cem\u003eO(logn)\u003c/em\u003e. This is because, in the worst case, the element might have to travel from the leaf to the root.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"howtoremoveandreturnthesmallestelementfromtheheap\"\u003eHow to Remove and Return the Smallest Element from the Heap\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003eheappop()\u003c/code\u003e function extracts and returns the smallest element from the heap (the root in a min heap). After removal, it ensures the list remains a valid heap:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e heapq\n\nheap = [\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e7\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e9\u003c/span\u003e]\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heapq.heappop(heap))\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heap)\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e The \u003ccode\u003eheappop()\u003c/code\u003e is invaluable in algorithms that require processing elements in ascending order, like the Heap Sort algorithm, or when implementing priority queues where tasks are executed based on their urgency.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eThis will output the smallest element and the remaining list:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e1\n[3, 7, 5, 9]\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003e1\u003c/code\u003e is the smallest element from the \u003ccode\u003eheap\u003c/code\u003e, and the remaining list has maintained the heap property, even after we removed \u003ccode\u003e1\u003c/code\u003e.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eTime Complexity:\u003c/strong\u003e Removing the root element (which is the smallest in a min heap or largest in a max heap) and reorganizing the heap also takes \u003cem\u003eO(logn)\u003c/em\u003e time.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"howtopushanewitemandpopthesmallestitem\"\u003eHow to Push a New Item and Pop the Smallest Item\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003eheappushpop()\u003c/code\u003e function is a combined operation that pushes a new item onto the heap and then pops and returns the smallest item from the heap:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e heapq\n\nheap = [\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e7\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e9\u003c/span\u003e]\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heapq.heappushpop(heap, \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e)) \n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heap)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will output \u003ccode\u003e3\u003c/code\u003e, the smallest element, and print out the new \u003ccode\u003eheap\u003c/code\u003e list that now includes \u003ccode\u003e4\u003c/code\u003e while maintaining the heap property:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e3\n[4, 5, 7, 9]\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Using the \u003ccode\u003eheappushpop()\u003c/code\u003e function is more efficient than performing operations of pushing a new element and popping the smallest one separately.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"howtoreplacethesmallestitemandpushanewitem\"\u003eHow to Replace the Smallest Item and Push a New Item\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003eheapreplace()\u003c/code\u003e function pops the smallest element and pushes a new element onto the heap, all in one efficient operation:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e heapq\n\nheap = [\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e7\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e9\u003c/span\u003e]\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heapq.heapreplace(heap, \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e))\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heap)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis prints \u003ccode\u003e1\u003c/code\u003e, the smallest element, and the list now includes 4 and maintains the heap property:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e1\n[4, 5, 7, 9]\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote\u003c/strong\u003e: \u003ccode\u003eheapreplace()\u003c/code\u003e is beneficial in streaming scenarios where you want to replace the current smallest element with a new value, such as in rolling window operations or real-time data processing tasks.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"findingmultipleextremesinpythonsheap\"\u003eFinding Multiple Extremes in Python's Heap\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003enlargest(n, iterable[, key])\u003c/code\u003e and \u003ccode\u003ensmallest(n, iterable[, key])\u003c/code\u003e functions are designed to retrieve multiple largest or smallest elements from an iterable. They can be more efficient than sorting the entire iterable when you only need a few extreme values. For example, say you have the following list and you want to find three smallest and three largest values in the list:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003edata = [\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e9\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e6\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e]\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003enlargest()\u003c/code\u003e and \u003ccode\u003ensmallest()\u003c/code\u003e functions can come in handy:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e heapq\n\ndata = [\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e4\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e9\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e6\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e]\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heapq.nlargest(\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, data)) \u003cspan class=\"hljs-comment\"\u003e# Outputs [9, 6, 5]\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(heapq.nsmallest(\u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e, data)) \u003cspan class=\"hljs-comment\"\u003e# Outputs [1, 1, 2]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis will give you two lists - one contains the three largest values and the other contains the three smallest values from the \u003ccode\u003edata\u003c/code\u003e list:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e[9, 6, 5]\n[1, 1, 2]\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"howtobuildyourcustomheap\"\u003eHow to Build Your Custom Heap\u003c/h3\u003e\n\u003cp\u003eWhile Python's \u003ccode\u003eheapq\u003c/code\u003e module provides a robust set of tools for working with heaps, there are scenarios where the default min heap behavior might not suffice. Whether you're looking to implement a max heap or need a heap that operates based on custom comparison functions, building a custom heap can be the answer. Let's explore how to tailor heaps to specific needs.\u003c/p\u003e\n\u003ch4 id=\"implementingamaxheapusingheapq\"\u003eImplementing a Max Heap using \u003ccode\u003eheapq\u003c/code\u003e\u003c/h4\u003e\n\u003cp\u003eBy default, \u003ccode\u003eheapq\u003c/code\u003e creates \u003cem\u003emin heaps\u003c/em\u003e. However, with a simple trick, you can use it to implement a max heap. The idea is to invert the order of elements by multiplying them by \u003ccode\u003e-1\u003c/code\u003e before adding them to the heap:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e heapq\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eMaxHeap\u003c/span\u003e:\u003c/span\u003e\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e__init__\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself\u003c/span\u003e):\u003c/span\u003e\n self.heap = []\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003epush\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, val\u003c/span\u003e):\u003c/span\u003e\n heapq.heappush(self.heap, -val)\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003epop\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e -heapq.heappop(self.heap)\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003epeek\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e -self.heap[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e]\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWith this approach, the largest number (in terms of absolute value) becomes the smallest, allowing the \u003ccode\u003eheapq\u003c/code\u003e functions to maintain a max heap structure.\u003c/p\u003e\n\u003ch4 id=\"heapswithcustomcomparisonfunctions\"\u003eHeaps with Custom Comparison Functions\u003c/h4\u003e\n\u003cp\u003eSometimes, you might need a heap that doesn't just compare based on the natural order of elements. For instance, if you're working with complex objects or have specific sorting criteria, a custom comparison function becomes essential.\u003c/p\u003e\n\u003cp\u003eTo achieve this, you can wrap elements in a helper class that overrides the comparison operators:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e heapq\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eCustomElement\u003c/span\u003e:\u003c/span\u003e\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e__init__\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, obj, comparator\u003c/span\u003e):\u003c/span\u003e\n self.obj = obj\n self.comparator = comparator\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e__lt__\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, other\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e self.comparator(self.obj, other.obj)\n\n\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003ecustom_heappush\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eheap, obj, comparator=\u003cspan class=\"hljs-keyword\"\u003elambda\u003c/span\u003e x, y: x \u0026lt; y\u003c/span\u003e):\u003c/span\u003e\n heapq.heappush(heap, CustomElement(obj, comparator))\n\n\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003ecustom_heappop\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eheap\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e heapq.heappop(heap).obj\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWith this setup, you can define any custom comparator function and use it with the heap.\u003c/p\u003e\n\u003c!--### Conclusion\n\nHeaps offer predictable performance for many operations, making them a reliable choice for priority-based tasks. However, it's essential to consider the specific requirements and characteristics of the application at hand. In some cases, tweaking the heap's implementation or even opting for alternative data structures might yield better real-world performance.\n\nHeaps, as we've journeyed through, are more than just another data structure. They represent a confluence of efficiency, structure, and adaptability. From their foundational properties to their implementation in Python's `heapq` module, heaps offer a robust solution to a myriad of computational challenges, especially those centered around priority.--\u003e","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":"Explore the intricacies of heaps, a tree-based data structure adept at maintaining order and hierarchy. Dive into Python's' heapq module, offering a rich set of functionalities for managing dynamic data sets where priority elements are frequently accessed. Learn how heaps stand out in the world of data structures and their seamless integration in Python.","read_time_min":19,"published_at":1700076112041,"created_at":1695040116196,"updated_at":1713452081664,"tags":[{"id":9,"name":"python","slug":"python","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1431358631000,"updated_at":1431358631000,"_pivot_content_id":2064,"_pivot_tag_id":9,"_pivot_sort_order":0},{"id":79,"name":"data structures","slug":"data-structures","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1509379932000,"updated_at":1509379932000,"_pivot_content_id":2064,"_pivot_tag_id":79,"_pivot_sort_order":1}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2064,"_pivot_user_id":1,"_pivot_role":"editor","_pivot_sort_order":1},{"id":94,"name":"Dimitrije Stamenic","slug":"stamd","role_id":4,"img_profile":"https://s3.amazonaws.com/s3.stackabuse.com/media/users/91dc45351236146b499e059557c35823.png","img_cover":null,"bio_html":"","website":"https://www.linkedin.com/in/stamd/","location":"Belgrade, Serbia","facebook":null,"twitter":"stamenic_d","github":"stamd","created_at":1618418516000,"updated_at":1703355178722,"role":"editor","_pivot_content_id":2064,"_pivot_user_id":94,"_pivot_role":"author","_pivot_sort_order":0}],"_pivot_user_id":1,"_pivot_content_id":2064},{"id":2001,"title":"Guide to Hash Tables in Python","slug":"hash-tables-in-python","body_html":"\u003cp\u003eWhile Python doesn't have a built-in data structure explicitly called a \u003cem\u003e\u0026quot;hash table\u0026quot;\u003c/em\u003e, it provides the \u003cem\u003edictionary\u003c/em\u003e, which is a form of a hash table. Python dictionaries are unordered collections of \u003cem\u003ekey-value pairs\u003c/em\u003e, where the key is unique and holds a corresponding value. Thanks to a process known as \u003cem\u003e\u0026quot;hashing\u0026quot;\u003c/em\u003e, dictionaries enable efficient retrieval, addition, and removal of entries.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e If you're a Python programmer and have ever used a dictionary to store data as key-value pairs, you've already benefited from hash table technology without necessarily knowing it! \u003cstrong\u003ePython dictionaries are implemented using hash tables!\u003c/strong\u003e\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"alert alert-reference\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-link-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eLink:\u003c/strong\u003e You can read more about dictionaries in Python in our \u003ca target=\"_blank\" href=\"https://stackabuse.com/python-dictionary-tutorial/\"\u003e\u0026quot;Guide to Dictionaries in Python\u0026quot;\u003c/a\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cblockquote\u003e\n\u003cp\u003eIn this guide, we'll delve into the world of hash tables. We'll start with the basics, explaining what hash tables are and how they work. We'll also explore Python's implementation of hash tables via dictionaries, provide a step-by-step guide to creating a hash table in Python, and even touch on how to handle hash collisions. Along the way, we'll demonstrate the utility and efficiency of hash tables with real-world examples and handy Python snippets.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"defininghashtableskeyvaluepairdatastructure\"\u003eDefining Hash Tables: Key-Value Pair Data Structure\u003c/h3\u003e\n\u003cp\u003eSince dictionaries in Python are essentially an implementation of hash tables, let's first focus on what hash tables actually are, and dive into Python implementation afterward.\u003c/p\u003e\n\u003cp\u003eHash tables are a type of data structure that provides a mechanism to store data in an \u003cem\u003eassociative manner\u003c/em\u003e. In a hash table, data is stored in an \u003cem\u003earray format\u003c/em\u003e, but each data value has its own \u003cem\u003eunique key\u003c/em\u003e, which is used to identify the data. This mechanism is based on key-value pairs, making the retrieval of data a swift process.\u003c/p\u003e\n\u003cp\u003eThe analogy often used to explain this concept is a real-world dictionary. In a dictionary, you use a known word (the \u0026quot;key\u0026quot;) to find its meaning (the \u0026quot;value\u0026quot;). If you know the word, you can quickly find its definition. Similarly, in a hash table, if you know the key, you can quickly retrieve its value.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eEssentially, we are trying to store key-value pairs in the most efficient way possible.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eFor example, say we want to create a hash table that stores the birth month of various people. The people's names are our keys and their birth months are the values:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e+-----------------------+\n| Key | Value |\n+-----------------------+\n| Alice | January |\n| Bob | May |\n| Charlie | January |\n| David | August |\n| Eve | December |\n| Brian | May |\n+-----------------------+\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eTo store these key-value pairs in a hash table, we'll first need a way to convert the value of keys to the appropriate indexes of the array that represents a hash table. That's where a \u003cstrong\u003ehash function\u003c/strong\u003e comes into play! Being the backbone of a hash table implementation, this function processes the key and returns the corresponding index in the data storage array - just as we need.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe goal of a \u003cem\u003egood hash function\u003c/em\u003e is to distribute the keys evenly across the array, minimizing the chance of collisions (where two keys produce the same index).\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/hash-tables-in-python-1.png\" alt=\"hash-tables-in-python-01.png\"\u003e\u003c/p\u003e\n\u003cp\u003eIn reality, hash functions are much more complex, but for simplicity, let's use a hash function that maps each name to an index by taking the ASCII value of the first letter of the name modulo the size of the table:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003esimple_hash\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003ekey, array_size\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eord\u003c/span\u003e(key[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e]) % array_size\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis hash function is \u003cem\u003esimple\u003c/em\u003e, but it \u003cem\u003ecould lead to collisions\u003c/em\u003e because different keys might start with the same letter and hence the resulting indices will be the same. For example, say our array has the size of \u003ccode\u003e10\u003c/code\u003e, running the \u003ccode\u003esimple_hash(key, 10)\u003c/code\u003e for each of our keys will give us:\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/hash-tables-in-python-2.png\" alt=\"hash-tables-in-python-02.png\"\u003e\u003c/p\u003e\n\u003cp\u003eAlternatively, we can reshape this data in a more concise way:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e+---------------------+\n| Key | Index |\n+---------------------+\n| Alice | 5 |\n| Bob | 6 |\n| Charlie | 7 |\n| David | 8 |\n| Eve | 9 |\n| Brian | 6 |\n+---------------------+\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, \u003ccode\u003eBob\u003c/code\u003e and \u003ccode\u003eBrian\u003c/code\u003e have the same index in the resulting array, which results in \u003cem\u003ea collision\u003c/em\u003e. We'll talk more about collisions in the latter sections - both in terms of creating hash functions that minimize the chance of collisions and resolving collisions when they occur.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cem\u003eDesigning robust hash functions is one of the most important aspects of hash table efficiency!\u003c/em\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e In Python, dictionaries are an implementation of a hash table, where the keys are hashed, and the resulting hash value determines where in the dictionary's underlying data storage the corresponding value is placed.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eIn the following sections, we'll dive deeper into the inner workings of hash tables, discussing their operations, potential issues (like collisions), and solutions to these problems.\u003c/p\u003e\n\u003ch3 id=\"demystifyingtheroleofhashfunctionsinhashtables\"\u003eDemystifying the Role of Hash Functions in Hash Tables\u003c/h3\u003e\n\u003cp\u003eHash functions are the \u003cem\u003eheart and soul\u003c/em\u003e of hash tables. They serve as a bridge between the keys and their associated values, providing a means of efficiently storing and retrieving data. Understanding the role of hash functions in hash tables is crucial to grasp how this powerful data structure operates.\u003c/p\u003e\n\u003ch4 id=\"whatisahashfunction\"\u003eWhat is a Hash Function?\u003c/h4\u003e\n\u003cp\u003eIn the context of hash tables, a hash function is a special function that takes a \u003cem\u003ekey as input\u003c/em\u003e and \u003cem\u003ereturns an index\u003c/em\u003e which the corresponding value should be stored or retrieved from. It transforms the key into a \u003cem\u003e\u003cstrong\u003ehash\u003c/strong\u003e\u003c/em\u003e - a number that corresponds to an index in the array that forms the underlying structure of the hash table.\u003c/p\u003e\n\u003cp\u003eThe hash function needs to be \u003cem\u003e\u003cstrong\u003edeterministic\u003c/strong\u003e\u003c/em\u003e, meaning that it should always produce the same hash for the same key. This way, whenever you want to retrieve a value, you can use the hash function on the key to find out where the value is stored.\u003c/p\u003e\n\u003ch4 id=\"theroleofhashfunctionsinhashtables\"\u003eThe Role of Hash Functions in Hash Tables\u003c/h4\u003e\n\u003cp\u003eThe main objective of a hash function in a hash table is to distribute the keys \u003cem\u003eas uniformly as possible\u003c/em\u003e across the array. This is important because the uniform distribution of keys allows for a constant time complexity of \u003cem\u003eO(1)\u003c/em\u003e for data operations such as insertions, deletions, and retrievals \u003cem\u003eon average\u003c/em\u003e.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-reference\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-link-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eLink:\u003c/strong\u003e You can read more about the Big-O notation in our article \u003ca target=\"_blank\" href=\"https://stackabuse.com/big-o-notation-and-algorithm-analysis-with-python-examples/\"\u003e\u0026quot;Big O Notation and Algorithm Analysis with Python Examples\u0026quot;\u003c/a\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eTo illustrate how a hash function works in a hash table, let's again take a look at the example from the previous section:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e+-----------------------+\n| Key | Value |\n+-----------------------+\n| Alice | January |\n| Bob | May |\n| Charlie | January |\n| David | August |\n| Eve | December |\n| Brian | May |\n+-----------------------+\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAs before, assume we have a hash function, \u003ccode\u003esimple_hash(key)\u003c/code\u003e, and a hash table of size \u003ccode\u003e10\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eAs we've seen before, running, say, \u003ccode\u003e\u0026quot;Alice\u0026quot;\u003c/code\u003e through the \u003ccode\u003esimple_hash()\u003c/code\u003e function returns the index \u003ccode\u003e5\u003c/code\u003e. That means we can find the element with the key \u003ccode\u003e\u0026quot;Alice\u0026quot;\u003c/code\u003e and the value \u003ccode\u003e\u0026quot;January\u0026quot;\u003c/code\u003e in the array representing the hash table, on the index \u003ccode\u003e5\u003c/code\u003e (6th element of that array):\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/hash-tables-in-python-3.png\" alt=\"hash-tables-in-python-03.png\"\u003e\u003c/p\u003e\n\u003cp\u003eAnd that applies to each key of our original data. Running each key through the hash function will give us the integer value - an index in the hash table array where that element is stored:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e+---------------------+\n| Key | Index |\n+---------------------+\n| Alice | 5 |\n| Bob | 6 |\n| Charlie | 7 |\n| David | 8 |\n| Eve | 9 |\n| Brian | 6 |\n+---------------------+\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis can easily translate to the array representing a hash table - an element with the key \u003ccode\u003e\u0026quot;Alice\u0026quot;\u003c/code\u003e will be stored under index \u003ccode\u003e5\u003c/code\u003e, \u003ccode\u003e\u0026quot;Bob\u0026quot;\u003c/code\u003e under index \u003ccode\u003e6\u003c/code\u003e, and so on:\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/hash-tables-in-python-4.png\" alt=\"hash-tables-in-python-04.png\"\u003e\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Under the index \u003ccode\u003e6\u003c/code\u003e there are two elements - \u003ccode\u003e{\u0026quot;Bob\u0026quot;, \u0026quot;February\u0026quot;}\u003c/code\u003e and \u003ccode\u003e{\u0026quot;Brian\u0026quot;, \u0026quot;May\u0026quot;}\u003c/code\u003e. In the illustration above, that collision was solved using the method called \u003cem\u003eseparate chaining\u003c/em\u003e, which we'll talk about more later in this article.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eWhen we want to retrieve the value associated with the key \u003ccode\u003e\u0026quot;Alice\u0026quot;\u003c/code\u003e, we again pass the key to the hash function, which returns the index \u003ccode\u003e5\u003c/code\u003e. We then immediately access the value at index \u003ccode\u003e3\u003c/code\u003e of the hash table, which is \u003ccode\u003e\u0026quot;January\u0026quot;\u003c/code\u003e.\u003c/p\u003e\n\u003ch4 id=\"challengeswithhashfunctions\"\u003eChallenges with Hash Functions\u003c/h4\u003e\n\u003cp\u003eWhile the idea behind hash functions is fairly straightforward, \u003cstrong\u003edesigning a good hash function can be challenging\u003c/strong\u003e. A primary concern is what's known as a \u003cem\u003ecollision\u003c/em\u003e, which occurs when two different keys hash to the same index in the array.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eJust take a look at the \u003ccode\u003e\u0026quot;Bob\u0026quot;\u003c/code\u003e and \u003ccode\u003e\u0026quot;Brian\u0026quot;\u003c/code\u003e keys in our example. They have the same index, meaning they are stored in the same place in the hash table array. In its essence, this is an example of a hashing collision.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe likelihood of \u003cem\u003ecollisions\u003c/em\u003e is dictated by the hash function and the size of the hash table. While it's virtually impossible to completely avoid collisions for any non-trivial amount of data, a good hash function coupled with an appropriately sized hash table will minimize the chances of collisions.\u003c/p\u003e\n\u003cp\u003eDifferent strategies such as \u003cem\u003eopen addressing\u003c/em\u003e and \u003cem\u003eseparate chaining\u003c/em\u003e can be used to resolve collisions when they occur, which we'll cover in a later section.\u003c/p\u003e\n\u003ch3 id=\"analyzingtimecomplexityofhashtablesacomparison\"\u003eAnalyzing Time Complexity of Hash Tables: A Comparison\u003c/h3\u003e\n\u003cp\u003eOne of the key benefits of using hash tables, which sets them apart from many other data structures, is their time complexity for basic operations. Time complexity is a computational concept that refers to the amount of time an operation or a function takes to run, as a function of the size of the input to the program.\u003c/p\u003e\n\u003cp\u003eWhen discussing time complexity, we generally refer to three cases:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eBest Case:\u003c/strong\u003e The minimum time required for executing an operation.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAverage Case:\u003c/strong\u003e The average time needed for executing an operation.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWorst Case:\u003c/strong\u003e The maximum time needed for executing an operation.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eHash tables are especially noteworthy for their \u003cem\u003eimpressive time complexity in the \u003cstrong\u003eaverage case\u003c/strong\u003e scenario\u003c/em\u003e. In that scenario, basic operations in hash tables (inserting, deleting, and accessing elements) have a \u003cstrong\u003econstant time complexity of O(1)\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eThe constant time complexity implies that the time taken to perform these operations remains constant, regardless of the number of elements in the hash table.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis makes these operations extremely efficient, especially when dealing with large datasets.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eWhile the average case time complexity for hash tables is O(1), \u003cem\u003ethe \u003cstrong\u003eworst-case\u003c/strong\u003e scenario is a different story\u003c/em\u003e. If multiple keys hash to the same index (a situation known as a \u003cem\u003ecollision\u003c/em\u003e), the time complexity can degrade to \u003cstrong\u003eO(n)\u003c/strong\u003e, where \u003cem\u003en\u003c/em\u003e is the number of keys mapped to the same index.\u003c/p\u003e\n\u003cp\u003eThis scenario occurs because, when resolving collisions, additional steps must be taken to store and retrieve data, typically by traversing a linked list of entries that hash to the same index.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e With a well-designed hash function and a correctly sized hash table, this worst-case scenario is generally the exception rather than the norm. A good hash function paired with appropriate collision resolution strategies can keep collisions to a minimum.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch4 id=\"comparingtootherdatastructures\"\u003eComparing to Other Data Structures\u003c/h4\u003e\n\u003cp\u003eWhen compared to other data structures, \u003cem\u003ehash tables stand out for their efficiency\u003c/em\u003e. For instance, operations like search, insertion, and deletion in a balanced binary search tree or a balanced AVL Tree have a time complexity of \u003cem\u003eO(log n)\u003c/em\u003e, which, although not bad, is not as efficient as the \u003cem\u003eO(1)\u003c/em\u003e time complexity that hash tables offer in the average case.\u003c/p\u003e\n\u003cp\u003eWhile arrays and linked lists offer \u003cem\u003eO(1)\u003c/em\u003e time complexity for some operations, they can't maintain this level of efficiency across all basic operations. For example, searching in an unsorted array or linked list takes \u003cem\u003eO(n)\u003c/em\u003e time, and insertion in an array takes \u003cem\u003eO(n)\u003c/em\u003e time in the worst case.\u003c/p\u003e\n\u003ch3 id=\"pythonsapproachtohashtablesanintroductiontodictionaries\"\u003ePython's Approach to Hash Tables: An Introduction to Dictionaries\u003c/h3\u003e\n\u003cp\u003ePython provides a built-in data structure that implements the functionality of a hash table called a dictionary, often referred to as a \u0026quot;dict\u0026quot;. Dictionaries are one of Python's most powerful data structures, and understanding how they work can significantly boost your programming skills.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-reference\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-link-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eAdvice:\u003c/strong\u003e You can read a more comprehensive overview of dictionaries in Python in our \u003ca target=\"_blank\" href=\"https://stackabuse.com/python-dictionary-tutorial/\"\u003e\u0026quot;Guide to Dictionaries in Python\u0026quot;\u003c/a\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch4 id=\"whataredictionaries\"\u003eWhat are Dictionaries?\u003c/h4\u003e\n\u003cp\u003eIn Python, dictionaries (dicts) are unordered collections of key-value pairs. Keys in a dictionary are unique and immutable, which means they can't be changed once they're set. This property is essential for the correct functioning of a hash table. Values, on the other hand, can be of any type and are mutable, meaning you can change them.\u003c/p\u003e\n\u003cp\u003eA key-value pair in a dictionary is also known as an item. Each key in a dictionary is associated (or mapped) to a single value, forming a key-value pair:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003emy_dict = {\u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026quot;January\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;Bob\u0026quot;\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026quot;May\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;Charlie\u0026quot;\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026quot;January\u0026quot;\u003c/span\u003e}\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"howdodictionariesworkinpython\"\u003eHow do Dictionaries Work in Python?\u003c/h4\u003e\n\u003cp\u003eBehind the scenes, \u003cem\u003ePython's dictionaries operate as a hash table\u003c/em\u003e. When you create a dictionary and add a key-value pair, Python applies a hash function to the key, which results in a hash value. This hash value then determines where in memory the corresponding value will be stored.\u003c/p\u003e\n\u003cp\u003eThe beauty of this is that when you want to retrieve the value, Python applies the same hash function to the key, which rapidly guides Python to where the value is stored, regardless of the size of the dictionary:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003emy_dict = {}\nmy_dict[\u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e] = \u003cspan class=\"hljs-string\"\u003e\u0026quot;January\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e# Hash function determines the location for \u0026quot;January\u0026quot;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(my_dict[\u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e]) \u003cspan class=\"hljs-comment\"\u003e# \u0026quot;January\u0026quot;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch4 id=\"keyoperationsandtimecomplexity\"\u003eKey Operations and Time Complexity\u003c/h4\u003e\n\u003cp\u003ePython's built-in dictionary data structure makes performing basic hash table operations—such as insertions, access, and deletions a breeze. These operations typically have an average time complexity of O(1), making them remarkably efficient.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e As with hash tables, the worst-case time complexity can be \u003cem\u003eO(n)\u003c/em\u003e, but this happens rarely, only when there are hash collisions.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003e\u003cstrong\u003eInserting key-value pairs\u003c/strong\u003e into a Python dictionary is straightforward. You simply assign a value to a key using the assignment operator (\u003ccode\u003e=\u003c/code\u003e). If the key doesn't already exist in the dictionary, it's added. If it does exist, its current value is replaced with the new value:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003emy_dict = {}\nmy_dict[\u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e] = \u003cspan class=\"hljs-string\"\u003e\u0026quot;January\u0026quot;\u003c/span\u003e\nmy_dict[\u003cspan class=\"hljs-string\"\u003e\u0026quot;Bob\u0026quot;\u003c/span\u003e] = \u003cspan class=\"hljs-string\"\u003e\u0026quot;May\u0026quot;\u003c/span\u003e\n\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(my_dict) \u003cspan class=\"hljs-comment\"\u003e# Outputs: {\u0026#x27;Alice\u0026#x27;: \u0026#x27;January\u0026#x27;, \u0026#x27;Bob\u0026#x27;: \u0026#x27;May\u0026#x27;}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eAccessing a value\u003c/strong\u003e in a Python dictionary is just as simple as inserting one. You can access the value associated with a particular key by referencing the key in square brackets. If you attempt to access a key that doesn't exist in the dictionary, Python will raise a \u003ccode\u003eKeyError\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(my_dict[\u003cspan class=\"hljs-string\"\u003e\u0026quot;Alice\u0026quot;\u003c/span\u003e]) \u003cspan class=\"hljs-comment\"\u003e# Outputs: Python\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Raises KeyError: \u0026#x27;Charlie\u0026#x27;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(my_dict[\u003cspan class=\"hljs-string\"\u003e\u0026quot;Charlie\u0026quot;\u003c/span\u003e])\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eTo prevent this error, you can use the dictionary's \u003ccode\u003eget()\u003c/code\u003e method, which allows you to return a default value if the key doesn't exist:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(my_dict.get(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Charlie\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;Unknown\u0026quot;\u003c/span\u003e)) \u003cspan class=\"hljs-comment\"\u003e# Outputs: Unknown\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Similarly, the \u003ccode\u003esetdefault()\u003c/code\u003e method can be used to safely insert a key-value pair into the dictionary if the key doesn't already exist:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003emy_dict.setdefault(\u003cspan class=\"hljs-string\"\u003e\u0026quot;new_key\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;default_value\u0026quot;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eYou can \u003cstrong\u003eremove a key-value pair\u003c/strong\u003e from a Python dictionary using the \u003ccode\u003edel\u003c/code\u003e keyword. If the key exists in the dictionary, it's removed along with its value. If the key doesn't exist, Python will also raise a \u003ccode\u003eKeyError\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-keyword\"\u003edel\u003c/span\u003e my_dict[\u003cspan class=\"hljs-string\"\u003e\u0026quot;Bob\u0026quot;\u003c/span\u003e]\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(my_dict) \u003cspan class=\"hljs-comment\"\u003e# Outputs: {\u0026#x27;Alice\u0026#x27;: \u0026#x27;January\u0026#x27;}\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Raises KeyError: \u0026#x27;Bob\u0026#x27;\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003edel\u003c/span\u003e my_dict[\u003cspan class=\"hljs-string\"\u003e\u0026quot;Bob\u0026quot;\u003c/span\u003e]\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eLike with access, if you want to prevent an error when trying to delete a key that doesn't exist, you can use the dictionary's \u003ccode\u003epop()\u003c/code\u003e method, which removes a key, returns its value if it exists, and returns a default value if it doesn't:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(my_dict.pop(\u003cspan class=\"hljs-string\"\u003e\u0026quot;Bob\u0026quot;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026quot;Unknown\u0026quot;\u003c/span\u003e)) \u003cspan class=\"hljs-comment\"\u003e# Outputs: Unknown\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAll-in-all, Python dictionaries serve as a high-level, user-friendly implementation of a hash table. They are easy to use, yet powerful and efficient, making them an excellent tool for handling a wide variety of programming tasks.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eAdvice:\u003c/strong\u003e If you're testing for membership (i.e., whether an item is in a collection), a dictionary (or a set) is often a more efficient choice than a list or a tuple, especially for larger collections. That's because dictionaries and sets use hash tables, which allow them to test for membership in constant time (\u003cem\u003eO(1)\u003c/em\u003e), as opposed to lists or tuples, which take linear time (\u003cem\u003eO(n)\u003c/em\u003e).\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eIn the next sections, we will dive deeper into the practical aspects of using dictionaries in Python, including creating dictionaries (hash tables), performing operations, and handling collisions.\u003c/p\u003e\n\u003ch3 id=\"howtocreateyourfirsthashtableinpython\"\u003eHow to Create Your First Hash Table in Python\u003c/h3\u003e\n\u003cp\u003ePython's dictionaries provide a ready-made implementation of hash tables, allowing you to store and retrieve key-value pairs with excellent efficiency. However, to understand hash tables thoroughly, it can be beneficial to implement one from scratch. In this section, we'll guide you through creating a simple hash table in Python.\u003c/p\u003e\n\u003cp\u003eWe'll start by defining a \u003ccode\u003eHashTable\u003c/code\u003e class. The hash table will be represented by a list (the \u003ccode\u003etable\u003c/code\u003e), and we will use a very simple hash function that calculates the remainder of the ASCII value of the key string's first character divided by the size of the table:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eHashTable\u003c/span\u003e:\u003c/span\u003e\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e__init__\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, size\u003c/span\u003e):\u003c/span\u003e\n self.size = size\n self.table = [\u003cspan class=\"hljs-literal\"\u003eNone\u003c/span\u003e]*size\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e_hash\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eord\u003c/span\u003e(key[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e]) % self.size\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this class, we have the \u003ccode\u003e__init__()\u003c/code\u003e method to initialize the hash table, and a \u003ccode\u003e_hash()\u003c/code\u003e method, which is our simple hash function.\u003c/p\u003e\n\u003cp\u003eNow, we'll add methods to our \u003ccode\u003eHashTable\u003c/code\u003e class for adding key-value pairs, getting values by key, and removing entries:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eHashTable\u003c/span\u003e:\u003c/span\u003e\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e__init__\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, size\u003c/span\u003e):\u003c/span\u003e\n self.size = size\n self.table = [\u003cspan class=\"hljs-literal\"\u003eNone\u003c/span\u003e]*size\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e_hash\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eord\u003c/span\u003e(key[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e]) % self.size\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eset\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key, value\u003c/span\u003e):\u003c/span\u003e\n hash_index = self._\u003cspan class=\"hljs-built_in\"\u003ehash\u003c/span\u003e(key)\n self.table[hash_index] = (key, value)\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eget\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key\u003c/span\u003e):\u003c/span\u003e\n hash_index = self._\u003cspan class=\"hljs-built_in\"\u003ehash\u003c/span\u003e(key)\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e self.table[hash_index] \u003cspan class=\"hljs-keyword\"\u003eis\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003enot\u003c/span\u003e \u003cspan class=\"hljs-literal\"\u003eNone\u003c/span\u003e:\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e self.table[hash_index][\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e]\n\n \u003cspan class=\"hljs-keyword\"\u003eraise\u003c/span\u003e KeyError(\u003cspan class=\"hljs-string\"\u003ef\u0026#x27;Key \u003cspan class=\"hljs-subst\"\u003e{key}\u003c/span\u003e not found\u0026#x27;\u003c/span\u003e)\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eremove\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key\u003c/span\u003e):\u003c/span\u003e\n hash_index = self._\u003cspan class=\"hljs-built_in\"\u003ehash\u003c/span\u003e(key)\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e self.table[hash_index] \u003cspan class=\"hljs-keyword\"\u003eis\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003enot\u003c/span\u003e \u003cspan class=\"hljs-literal\"\u003eNone\u003c/span\u003e:\n self.table[hash_index] = \u003cspan class=\"hljs-literal\"\u003eNone\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e:\n \u003cspan class=\"hljs-keyword\"\u003eraise\u003c/span\u003e KeyError(\u003cspan class=\"hljs-string\"\u003ef\u0026#x27;Key \u003cspan class=\"hljs-subst\"\u003e{key}\u003c/span\u003e not found\u0026#x27;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe \u003ccode\u003eset()\u003c/code\u003e method adds a key-value pair to the table, while the \u003ccode\u003eget()\u003c/code\u003e method retrieves a value by its key. The \u003ccode\u003eremove()\u003c/code\u003e method deletes a key-value pair from the hash table.\u003c/p\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e If the key doesn't exist, the \u003ccode\u003eget\u003c/code\u003e and \u003ccode\u003eremove\u003c/code\u003e methods raise a \u003ccode\u003eKeyError\u003c/code\u003e.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eNow, we can create a hash table and use it to store and retrieve data:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-comment\"\u003e# Create a hash table of size 10\u003c/span\u003e\nhash_table = HashTable(\u003cspan class=\"hljs-number\"\u003e10\u003c/span\u003e)\n\n\u003cspan class=\"hljs-comment\"\u003e# Add some key-value pairs\u003c/span\u003e\nhash_table.\u003cspan class=\"hljs-built_in\"\u003eset\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Alice\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;January\u0026#x27;\u003c/span\u003e)\nhash_table.\u003cspan class=\"hljs-built_in\"\u003eset\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Bob\u0026#x27;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;May\u0026#x27;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-comment\"\u003e# Retrieve a value\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(hash_table.get(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Alice\u0026#x27;\u003c/span\u003e)) \u003cspan class=\"hljs-comment\"\u003e# Outputs: \u0026#x27;January\u0026#x27;\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e# Remove a key-value pair\u003c/span\u003e\nhash_table.remove(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Bob\u0026#x27;\u003c/span\u003e)\n\n\u003cspan class=\"hljs-comment\"\u003e# This will raise a KeyError, as \u0026#x27;Bob\u0026#x27; was removed\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003eprint\u003c/span\u003e(hash_table.get(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Bob\u0026#x27;\u003c/span\u003e))\n\u003c/code\u003e\u003c/pre\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e The above hash table implementation is quite simple and does not handle hash collisions. In real-world use, you'd need a more sophisticated hash function and collision resolution strategy.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003ch3 id=\"resolvingcollisionsinpythonhashtables\"\u003eResolving Collisions in Python Hash Tables\u003c/h3\u003e\n\u003cp\u003eHash collisions are an inevitable part of using hash tables. A hash collision occurs when two different keys hash to the same index in the hash table. As Python dictionaries are an implementation of hash tables, they also need a way to handle these collisions.\u003c/p\u003e\n\u003cp\u003ePython's built-in hash table implementation uses a method called \u003cem\u003e\u003cstrong\u003e\u0026quot;open addressing\u0026quot;\u003c/strong\u003e\u003c/em\u003e to handle hash collisions. However, to better understand the collision resolution process, let's discuss a simpler method called \u003cem\u003e\u003cstrong\u003e\u0026quot;separate chaining\u0026quot;\u003c/strong\u003e\u003c/em\u003e.\u003c/p\u003e\n\u003ch4 id=\"separatechaining\"\u003eSeparate Chaining\u003c/h4\u003e\n\u003cp\u003eSeparate chaining is a collision resolution method in which each slot in the hash table holds a linked list of key-value pairs. When a collision occurs (i.e., two keys hash to the same index), the key-value pair is simply appended to the end of the linked list at the colliding index.\u003c/p\u003e\n\u003cp\u003eRemember, we had a collision in our example because both \u003ccode\u003e\u0026quot;Bob\u0026quot;\u003c/code\u003e and \u003ccode\u003e\u0026quot;Brian\u0026quot;\u003c/code\u003e had the same index - \u003ccode\u003e6\u003c/code\u003e. Let's use that example to illustrate the mechanism behind separate chaining. If we were to assume that the \u003ccode\u003e\u0026quot;Bob\u0026quot;\u003c/code\u003e element was added to the hash table first, we'd run into the problem when trying to store the \u003ccode\u003e\u0026quot;Brian\u0026quot;\u003c/code\u003e element since the index \u003ccode\u003e6\u003c/code\u003e was already taken.\u003c/p\u003e\n\u003cp\u003eSolving this situation using separate chaining would include adding the \u003ccode\u003e\u0026quot;Brian\u0026quot;\u003c/code\u003e element as the second element of the linked list assigned to index \u003ccode\u003e6\u003c/code\u003e (the \u003ccode\u003e\u0026quot;Bob\u0026quot;\u003c/code\u003e element is the first element of that list). And that's all there is to it, just as shown in the following illustration:\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://s3.stackabuse.com/media/articles/hash-tables-in-python-5.png\" alt=\"hash-tables-in-python-05.png\"\u003e\u003c/p\u003e\n\u003cp\u003eHere's how we might modify our \u003ccode\u003eHashTable\u003c/code\u003e class from the previous example to use separate chaining:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eHashTable\u003c/span\u003e:\u003c/span\u003e\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e__init__\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, size\u003c/span\u003e):\u003c/span\u003e\n self.size = size\n self.table = [[] \u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e _ \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003erange\u003c/span\u003e(size)]\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003e_hash\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key\u003c/span\u003e):\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eord\u003c/span\u003e(key[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e]) % self.size\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eset\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key, value\u003c/span\u003e):\u003c/span\u003e\n hash_index = self._\u003cspan class=\"hljs-built_in\"\u003ehash\u003c/span\u003e(key)\n \u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e kvp \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e self.table[hash_index]:\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e kvp[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e] == key:\n kvp[\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e] = value\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\n\n self.table[hash_index].append([key, value])\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eget\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key\u003c/span\u003e):\u003c/span\u003e\n hash_index = self._\u003cspan class=\"hljs-built_in\"\u003ehash\u003c/span\u003e(key)\n \u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e kvp \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e self.table[hash_index]:\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e kvp[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e] == key:\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e kvp[\u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e]\n\n \u003cspan class=\"hljs-keyword\"\u003eraise\u003c/span\u003e KeyError(\u003cspan class=\"hljs-string\"\u003ef\u0026#x27;Key \u003cspan class=\"hljs-subst\"\u003e{key}\u003c/span\u003e not found\u0026#x27;\u003c/span\u003e)\n\n \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003edef\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eremove\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eself, key\u003c/span\u003e):\u003c/span\u003e\n hash_index = self._\u003cspan class=\"hljs-built_in\"\u003ehash\u003c/span\u003e(key)\n \u003cspan class=\"hljs-keyword\"\u003efor\u003c/span\u003e i, kvp \u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eenumerate\u003c/span\u003e(self.table[hash_index]):\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e kvp[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e] == key:\n self.table[hash_index].pop(i)\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\n\n \u003cspan class=\"hljs-keyword\"\u003eraise\u003c/span\u003e KeyError(\u003cspan class=\"hljs-string\"\u003ef\u0026#x27;Key \u003cspan class=\"hljs-subst\"\u003e{key}\u003c/span\u003e not found\u0026#x27;\u003c/span\u003e)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn this updated implementation, the \u003ccode\u003etable\u003c/code\u003e is initialized as a list of empty lists (i.e., each slot is an empty linked list). In the \u003ccode\u003eset()\u003c/code\u003e method, we iterate over the linked list at the hashed index, updating the value if the key already exists. If it doesn't, we append a new key-value pair to the list.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003eget()\u003c/code\u003e and \u003ccode\u003eremove()\u003c/code\u003e methods also need to iterate over the linked list at the hashed index to find the key they're looking for.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWhile this approach solves the problem of collisions, it does lead to an increase in time complexity when collisions are frequent.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch4 id=\"openaddressing\"\u003eOpen Addressing\u003c/h4\u003e\n\u003cp\u003eThe method used by Python dictionaries to handle collisions is more sophisticated than separate chaining. Python uses a form of open addressing called \u003cem\u003e\u003cstrong\u003e\u0026quot;probing\u0026quot;\u003c/strong\u003e\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003eIn probing, when a collision occurs, the hash table checks the next available slot and places the key-value pair there instead. The process of finding the next available slot is called \u0026quot;probing\u0026quot;, and several strategies can be used, such as:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eLinear probing\u003c/em\u003e - checking one slot at a time in order\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eQuadratic probing\u003c/em\u003e - checking slots in increasing powers of two\u003c/li\u003e\n\u003c/ul\u003e\n\n \u003cdiv class=\"alert alert-note\"\u003e\n \u003cdiv class=\"flex\"\u003e\n \n \u003cdiv class=\"flex-shrink-0 mr-3\"\u003e\n \u003cimg src=\"/assets/images/icon-information-circle-solid.svg\" class=\"icon\" aria-hidden=\"true\" /\u003e\n \u003c/div\u003e\n \n \u003cdiv class=\"w-full\"\u003e\n \u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e The specific method Python uses is more complex than any of these, but it ensures that lookups, insertions, and deletions remain close to \u003cem\u003eO(1)\u003c/em\u003e time complexity even in cases where collisions are frequent.\u003c/p\u003e\n\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003cp\u003eLet's just take a quick look at the collision example from the previous section, and show how would we treat it using the open addressing method. Say we have a hash table with only one element - \u003ccode\u003e{\u0026quot;Bob\u0026quot;, \u0026quot;May\u0026quot;}\u003c/code\u003e on the index number \u003ccode\u003e6\u003c/code\u003e. Now, we wouldn't be able to add the \u003ccode\u003e\u0026quot;Brian\u0026quot;\u003c/code\u003e element to the hash table due to the collision. But, the mechanism of linear probing tells us to store it in the first empty index - \u003ccode\u003e7\u003c/code\u003e. That's it, easy right?\u003c/p\u003e\n\u003c!--### Conclusion\n\nFrom their conceptual underpinnings to their implementation as dictionaries in Python, hash tables stand as one of the most powerful and versatile data structures. They allow us to efficiently store, retrieve, and manipulate data in our programs, making them invaluable for a multitude of real-world applications such as caching, data indexing, frequency analysis, and much more.\n\nHash tables owe their prowess to their time complexity of _O(1)_ for essential operations, making them exceptionally fast even with large amounts of data. Moreover, their collision resolution strategies, such as Python's open addressing approach, ensure that they manage collisions effectively, maintaining their efficiency.\n\nWhile dictionaries, as Python's implementation of hash tables, are powerful and efficient, they do consume _more memory than other data structures like lists or tuples_. This is generally a fair trade-off for the performance benefits they offer, but if memory usage is a concern (for instance, if you're working with a very large dataset), it's something to keep in mind.\n\nIn such cases, you may want to consider alternatives like lists of tuples for small datasets or more memory-efficient data structures provided by libraries like NumPy or pandas for larger datasets.--\u003e","parent_id":null,"type":"article","visibility":"public","img_feature":null,"is_featured":false,"locale":"en","custom_excerpt":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"comment_id":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"read_time_min":31,"published_at":1699561184180,"created_at":1693425928815,"updated_at":1713452102164,"tags":[{"id":9,"name":"python","slug":"python","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1431358631000,"updated_at":1431358631000,"_pivot_content_id":2001,"_pivot_tag_id":9,"_pivot_sort_order":0},{"id":79,"name":"data structures","slug":"data-structures","img_cover":null,"description_html":"","og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"meta_title":null,"meta_description":null,"inject_header":null,"inject_footer":null,"canonical_url":null,"color":null,"created_at":1509379932000,"updated_at":1509379932000,"_pivot_content_id":2001,"_pivot_tag_id":79,"_pivot_sort_order":1}],"contributors":[{"id":1,"name":"Scott Robinson","slug":"scott","role_id":1,"img_profile":"//s3.stackabuse.com/media/users/1922fc67b9d11d6364dc01a3d19f4293.jpg","img_cover":null,"bio_html":"","website":null,"location":"Omaha, NE","facebook":null,"twitter":"ScottWRobinson","github":"scottwrobinson","created_at":1431311293000,"updated_at":1676411663329,"role":"owner","_pivot_content_id":2001,"_pivot_user_id":1,"_pivot_role":"editor","_pivot_sort_order":1},{"id":94,"name":"Dimitrije Stamenic","slug":"stamd","role_id":4,"img_profile":"https://s3.amazonaws.com/s3.stackabuse.com/media/users/91dc45351236146b499e059557c35823.png","img_cover":null,"bio_html":"","website":"https://www.linkedin.com/in/stamd/","location":"Belgrade, Serbia","facebook":null,"twitter":"stamenic_d","github":"stamd","created_at":1618418516000,"updated_at":1703355178722,"role":"editor","_pivot_content_id":2001,"_pivot_user_id":94,"_pivot_role":"author","_pivot_sort_order":0}],"_pivot_user_id":1,"_pivot_content_id":2001}],"content_count":"524"},"page":1,"error":null},"__N_SSP":true},"page":"/author/[...slug]","query":{"slug":["scott"]},"buildId":"1740324887682","isFallback":false,"isExperimentalCompile":false,"gssp":true,"scriptLoader":[]}</script></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10