0

mathspp.com · 24d · discuss

Learn how to use the sentinel built-in from Python 3.15 for placeholder values. Python 3.15 introduced the new sentinel built-in. The sentinel built-in can be used to create placeholder values: NOTHING = sentinel("NOTHING") A placeholder created by sentinel is the more idiomatic way to provide default arguments or return values where None wouldn't be usable. 15 days of Python 3.15 To celebrate the release of Python 3.15, over the next 15 business days I'll be writing about a new 3.15 feature every day. Explained clearly and with examples so you don't have to sift through the changelog. Subscribe to receive this free email series: (function() { window.GravRecaptchaInitializers = window.GravRecaptchaInitializers || {}; function addHiddenInput(form, name, value) { const existing = form.querySelector('input[type="hidden"][name="' + name + '"]'); if (existing) { existing.value = value; } else { const input = document.createElement('input'); input.setAttribute('type', 'hidden'); input.setAttribute('name', name); input.setAttribute('value', value); form.insertBefore(input, form.firstChild); } } function initRecaptchaV3(container) { const formId = container.dataset.formId; const siteKey = container.dataset.sitekey; const action = container.dataset.action; const form = document.getElementById(formId); if (!form) return; console.log(`Initializing reCAPTCHA v3 for form ${formId}`); const submitHandler = function(event) { event.preventDefault(); console.log(`reCAPTCHA v3 intercepting submit for form ${formId}`); grecaptcha.ready(function() { grecaptcha.execute(siteKey, { action: action }) .then(function(token) { console.log(`reCAPTCHA v3 token received for form ${formId}`); addHiddenInput(form, 'data[token]', token); addHiddenInput(form, 'data[action]', action); form.removeEventListener('submit', submitHandler); if (form.dataset.xhrEnabled === 'true' && window.GravFormXHR && typeof window.GravFormXHR.submit === 'function') { window.GravFormXHR.submit(form); } else { if (typeof form.requestSubmit === 'function') { form.requestSubmit(); } else { form.submit(); } } setTimeout(() => { const currentForm = document.getElementById(formId); if (currentForm && !currentForm.dataset.recaptchaListenerAttached) { currentForm.addEventListener('submit', submitHandler); currentForm.dataset.recaptchaListenerAttached = 'true'; } else if (currentForm) { delete currentForm.dataset.recaptchaListenerAttached; } }, 0); }); }); }; delete form.dataset.recaptchaListenerAttached; if (!form.dataset.recaptchaListenerAttached) { form.addEventListener('submit', submitHandler); form.dataset.recaptchaListenerAttached = 'true'; } } // Register the initializer function const initializerFunctionName = 'initRecaptcha_enroll'; window.GravRecaptchaInitializers[initializerFunctionName] = function() { const container = document.querySelector('[data-form-id="enroll"][data-captcha-provider="recaptcha"]'); if (!container) return; initRecaptchaV3(container); }; // Initial call if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', window.GravRecaptchaInitializers[initializerFunctionName]); } else { setTimeout(window.GravRecaptchaInitializers[initializerFunctionName], 0); } })(); Enroll for free 🐍🚀 If you want, you can also check the schedule of the upcoming emails. Creating and using sentinels The built-in sentinel accepts a string argument which is the name of the sentinel: NOTHING = sentinel("NOTHING") print(NOTHING) # NOTHING The name of the sentinel is used as its default string representation. Alternatively, you can provide a second named argument to be used as the representation of the sentinel: NOTHING = sentinel("NOTHING", repr="__main__.NOTHING") print(NOTHING) # __main__.NOTHING While there's no runtime restriction imposed, the name of the sentinel and the name of the variable that the sentinel is assigned to should match: # Correct: NOTHING = sentinel("NOTHING") # Wrong: NOTHING = sentinel("nothing") N = sentinel("NOTHING") BANANAS = sentinel("APPLES") Linters and type checkers may complain if there's a mismatch. Since sentinels are typically constants you won't update, it's also common for sentinels to have names in all uppercase. Sentinels are typically used as placeholders and the most common operation is to check if a value is a specific sentinel. For example, imagine a function find that looks...