<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ari Abramowitz</title>
    <description>The latest articles on Forem by Ari Abramowitz (@ariabramowitz).</description>
    <link>https://forem.com/ariabramowitz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2661068%2Fe11c6cac-d270-463a-90e8-34fd6f91eac9.jpg</url>
      <title>Forem: Ari Abramowitz</title>
      <link>https://forem.com/ariabramowitz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ariabramowitz"/>
    <language>en</language>
    <item>
      <title>The Tale of the Flickering Monitors, part 2: You're (not) Grounded!</title>
      <dc:creator>Ari Abramowitz</dc:creator>
      <pubDate>Tue, 26 Aug 2025 16:37:08 +0000</pubDate>
      <link>https://forem.com/ariabramowitz/the-tale-of-the-flickering-monitors-part-2-youre-not-grounded-5i2</link>
      <guid>https://forem.com/ariabramowitz/the-tale-of-the-flickering-monitors-part-2-youre-not-grounded-5i2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a followup to my previous post:&lt;/em&gt; &lt;a href="https://dev.to/ariabramowitz/the-tale-of-the-flickering-monitors-3ob6-temp-slug-7015125"&gt;&lt;em&gt;The Tale of the Flickering Monitors&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. To recap, my monitors were blinking in strange and disruptive ways. The culprit turned out to be my treadmill, and spraying some water on it made the flickering stop. If that sounds like a head scratcher, welcome to my world.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After last weeks wild and crazy monitor adventures, I thought I would be done writing about computer screens and instead focus on what I generally try to use those screens for: work. But there were still some loose ends to tie up. Spraying the treadmill cut down the flickering, but it was only a temporary fix. Once the water dried, the flicker returned and I had to spray again. Not terrible, but not ideal.&lt;/p&gt;

&lt;p&gt;Also, I wasnt wearing shoes and all of this spraying was making my socks wet, which is never a good thing.&lt;/p&gt;

&lt;p&gt;At this point I knew the problem had to do with static electricity buildup. I figured the socks werent helping with that, so I tried putting my sneakers on. The flickering seemed to stop. That was good, but could I do better?&lt;/p&gt;

&lt;p&gt;I searched around a bit more and discovered a whole community of people with similar treadmill-caused monitor flickering issues. Among them, this guy (flickering at 5:30):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/-lTdZFEQPn8?t=223" rel="noopener noreferrer"&gt;https://youtu.be/-lTdZFEQPn8?t=223&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wasnt going to start playing around with wires the way he did (again, Im a software guy). And the static discharge bands didnt look like they would be any better than my current sneaker solution. But Mr. ElectroBOOMs talk about &lt;em&gt;electrical grounding&lt;/em&gt; basically, giving stray electricity a safe place to go got me thinking.&lt;/p&gt;

&lt;p&gt;There was something about my treadmills power cord that I had noticed a long time ago and then promptly ignored: the plug was not a standard Israeli plug (I live in Israel). To compare, below is a picture of standard 2- and 3- pronged Israeli plugs, next to the thing I found attached to my treadmill:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgx1t99uueq7nb97ee9v.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgx1t99uueq7nb97ee9v.jpeg" width="600" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was unusual, but I plugged it in and, hey, it worked. I hardly gave it a second thought. Until now.&lt;/p&gt;

&lt;p&gt;I knew that the third prong on a 3-prong plug is usually meant for grounding, but this plug didnt have a third prong. It just had a metal strip going down the middle. Maybe that was the problem. I fed a picture of it to chatgpt. This time, it gave me some darned good information:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ah this is actually a &lt;strong&gt;Schuko plug (Type F, common in Europe).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Its not just a 2-prong plug. The two round pins are live and neutral, and the &lt;strong&gt;metal strips on the top and bottom edges&lt;/strong&gt; (you can see them on your photo) are the ground contacts. When you plug it into a proper Schuko socket, those strips touch the grounded clips in the socket and provide a full earth ground.&lt;/p&gt;

&lt;p&gt;So your treadmill &lt;em&gt;does&lt;/em&gt; support grounding its just that the ground is on the &lt;strong&gt;side rails&lt;/strong&gt; , not a third pin sticking out.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Again, for comparison, below is a standard Israeli outlet (left) and a Shuko outlet (right):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8k3s1itog0pclatcfva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8k3s1itog0pclatcfva.png" width="687" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Shuko plug fit in the Israeli outlet. It was able to power the treadmill, just the grounding mechanism didn't have anything to attach to. I thought I might be on to something. I went back to Google and discovered the nifty product pictured below: a Shuko to Israeli plug adapter. I ordered one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjhnce2b3kgn2pw94rwn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjhnce2b3kgn2pw94rwn.jpg" width="740" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Shuko to Israeli plug adapters (&lt;/em&gt;&lt;a href="https://shop.super-pharm.co.il/electricity-and-electronics/cables-and-adapters/electric-cables/%D7%9E%D7%AA%D7%90%D7%9D-%D7%97%D7%A9%D7%9E%D7%9C-%D7%9E%D7%AA%D7%A7%D7%A2-%D7%92%D7%A8%D7%9E%D7%A0%D7%99-(Schuko)-%D7%9C%D7%A9%D7%A7%D7%A2-%D7%99%D7%A9%D7%A8%D7%90%D7%9C%D7%99-%D7%9B%D7%95%D7%9C%D7%9C-%D7%94%D7%90%D7%A8%D7%A7%D7%94-3-%D7%A4%D7%99%D7%A0%D7%99%D7%9D-%D7%A2%D7%93-16A-%D7%A7%D7%91%D7%95%D7%A2/p/mp-00106831" rel="noopener noreferrer"&gt;&lt;em&gt;https://shop.super-pharm.co.il/electricity-and-electronics/cables-and-adapters/electric-cables/----(Schuko)-----3---16A-/p/mp-00106831&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The adapter arrived a few days later. As a test, I turned on the treadmill one more time without the adapter. It was still flickering. So I attached the adapter, held my breath, and it kept flickering. Oh well. At least I had the sneaker solution. It beat the spray bottle, and I got to learn a bit more about plugs and outlets along the way.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;&lt;em&gt;P.S.&lt;/em&gt;&lt;/strong&gt; While doing all of this, I decided to give my homemade docking station stand (&lt;a href="https://dev.to/ariabramowitz/the-tale-of-the-flickering-monitors-3ob6-temp-slug-7015125"&gt;mentioned in my last post&lt;/a&gt;) a slight upgrade so it looks a bit less like what it is: a piece of garbage. Well call this version 2.1:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfs0hx8yjnnkbj82n9a9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfs0hx8yjnnkbj82n9a9.jpeg" width="600" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;]]&amp;gt;&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>The Tale of the Flickering Monitors</title>
      <dc:creator>Ari Abramowitz</dc:creator>
      <pubDate>Wed, 20 Aug 2025 21:18:35 +0000</pubDate>
      <link>https://forem.com/ariabramowitz/the-tale-of-the-flickering-monitors-1555</link>
      <guid>https://forem.com/ariabramowitz/the-tale-of-the-flickering-monitors-1555</guid>
      <description>&lt;p&gt;Like many software engineers and other professionals, I prefer having extra screen space when I'm working. At my desk in my home office, I have two external monitors that I use in addition to my laptops built-in screen. For the past few weeks, Ive noticed that one or both would occasionally flicker. The offending screen would turn off for a second or two, then turn back on, with everything still on the screen where I had left it. An annoyance I could work around, but when I touched the docking station that my monitors were connected to, I noticed it was very hot.&lt;/p&gt;

&lt;p&gt;Thinking the docking station might be overheating, I built a cardboard stand for ventilation. My mother-in-law happened to be around and suggested upgrading to a piece of plastic food packaging. That became version 2.0 and it worked, at least for a few days. The docking station got a bit cooler and the flickering seemed to taper off.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1755763939946%2F2a80b1a0-b22e-49a3-b890-b9f1dc100ea7.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1755763939946%2F2a80b1a0-b22e-49a3-b890-b9f1dc100ea7.jpeg" alt="Versions 1.0 and 2.0 of my homemade docking station stand" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Versions 1.0 and 2.0 of my homemade docking station stand&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yesterday, however, the flicker frequency suddenly picked up dramatically. The screens would blink multiple times per minute, interrupting my work and making them essentially unusable. The problem had to be re-addressed.&lt;/p&gt;

&lt;p&gt;I had run into a similar issue about a year or two earlier. Somehow the mysterious flickering had been resolved, but I did not remember how - if it disappeared on its own, or if I found a fix, or what that fix might have been. Unfortunately, two weeks prior to the more recent incident, my group lost a large portion of our Teams chat history due to unrelated and unforeseen circumstances. I was on my own.&lt;/p&gt;

&lt;p&gt;My first thought was to make sure this didnt happen again next time. I started a new page in &lt;a href="https://www.notion.com/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt; so I could jot down whatever I was about to find out.&lt;/p&gt;

&lt;p&gt;I thought this still might be an overheating problem, so I found a small fan and pointed it at the docking station. It made no difference. The flickering continued apace.&lt;/p&gt;

&lt;p&gt;Then I got to work trying to isolate where the problem was really coming from. I swapped out my work laptop (system76, popos) for my personal one (lenovo, kubuntu), and the flicker continued. Whatever was happening probably did not have to do with the laptops hardware, since it persisted on two different machines. And if it was a software problem, it had to be something affecting both laptops.&lt;/p&gt;

&lt;p&gt;I posted about the problem on my groups Teams channel. Someone asked if I had done any system updates recently that might have unintentionally caused the problem. I hadnt certainly not anything that would have affected &lt;em&gt;both&lt;/em&gt; computers. Still, I thought Id try switching Linux kernels. (For context: in Linux, the kernel is the core of the operating system. Hardware-related bugs sometimes appear or disappear between versions, so trying a different kernel is a common troubleshooting step.) However, I knew that finding the right kernel might turn into a wild goose chase, assuming that was the problem at all. So before going down that path, I searched around and found a suggestion to tweak some Intel driver frame delivery settings (&lt;a href="https://www.reddit.com/r/Ubuntu/comments/1cfzjpj/comment/lpc77o7/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/Ubuntu/comments/1cfzjpj/comment/lpc77o7/&lt;/a&gt;). Unfortunately, that didnt help.&lt;/p&gt;

&lt;p&gt;So I moved on to kernel hoping. I tried 5 different versions (6.0.19, 6.5.6, 6.8.12, 6.12.42, and 6.16.1), but the flickering persisted across all of them.&lt;/p&gt;

&lt;p&gt;From there, I launched into a long back and forth with chatgpt. It suggested checking logs from various sources on my machine, using &lt;code&gt;journalctl&lt;/code&gt; and &lt;code&gt;dmesg&lt;/code&gt;. Nothing particularly insightful came from that. It then suggested updating the &lt;code&gt;linux-firmware&lt;/code&gt; on my machine. I dutifully obliged. The flickering dutifully continued.&lt;/p&gt;

&lt;p&gt;I then tried to clarify that chatgpt understood what I meant by flickering, realizing that the term could refer to different screen-related issues which might stem from different causes. It did understand. It just couldnt figure out what to do about it.&lt;/p&gt;

&lt;p&gt;At some point in all of these attempts, I noticed that the flickering followed an odd pattern. I normally stand when I work, and I have a desk treadmill that I use so I can walk at the same time. &lt;em&gt;The flickering only happened when the treadmill was turned on&lt;/em&gt;. Strange, but consistent. The easy solution, without understanding what was happening, would be to stop using the treadmill. Of course, I didnt want to do that, and I had been using the same treadmill and monitors for nearly four years with (almost) no issues. Why had the flickering suddenly jumped today?&lt;/p&gt;

&lt;p&gt;I told chatgpt about the treadmill epiphany and it started talking about electromagnetic noise and voltage dips. This was not my area of expertise, but I stuck around for the ride. It suggested rearranging the cables or moving the treadmill to another room (which would obviously defeat the purpose of a &lt;em&gt;desk&lt;/em&gt; treadmill, but what can you expect from an LLM that doesnt have to worry staying active during the workday?). I moved a bookcase to gain access to a separate outlet that I could plug the treadmill into. I threw in an extension cord and attached it to an outlet in the bathroom across the hall. Still no difference. The flickering continued.&lt;/p&gt;

&lt;p&gt;Chatgpt recommended several other pieces of hardware I could buy that might (&lt;em&gt;might&lt;/em&gt;) solve the problem a more well shielded HDMI cable, an Uninterruptible Power Supply (or UPS), or a line conditioner but I was hesitant to do any of these things not really knowing that they would solve the problem. It suggested twist[ing] the cable on itself. Easy enough, but also ineffective.&lt;/p&gt;

&lt;p&gt;Finally, I went back to Google and updated my search: monitor flickering when treadmill on. The first result led me to a reddit user with the same brand of treadmill, complaining that their screen flickers when the treadmill turns on:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I just bought a walking pad so that I can work while getting my steps in. I was super excited to get started, only to realize shortly after that walking on the treadmill while using the computer causes my monitors to flicker&lt;/p&gt;

&lt;p&gt;Update: I have found a silly, but useful solution to this problem. I figured that the issue was caused by static electricity. I googled how to get rid of static electricity, and it said to create more humidity in the room. I have a spray bottle of water, and I just spray it on the track of the treadmill. Dont spray too much so that youre slipping and sliding, but just enough that it is a tiny little bit wet. This is seem to solve the problem for me. Ill probably get a humidifier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reddit.com/r/Monitors/comments/10jfbfh/monitors_flicker_while_using_walking_pad/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/Monitors/comments/10jfbfh/monitors_flicker_while_using_walking_pad/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then it hit me.&lt;/p&gt;

&lt;p&gt;A few days earlier, I had discovered some mold growing in my office. Among the measures that I took to address that, I put a *de*humidifier in the office. By now, the dehumidifier had been sitting there for just about 24 hours and, together with the treadmill, created the perfect atmosphere for screen flickering. I had found the answer.&lt;/p&gt;

&lt;p&gt;I found a spray bottle, and sprayed a bit of water on the treadmill. The flickering stopped.&lt;/p&gt;

&lt;p&gt;And with that, I was back to my regularly scheduled programming (pun very much intended).&lt;/p&gt;

&lt;p&gt;Part 2 (theres more!?) here: &lt;a href="https://ariabramowitz.me/the-tale-of-the-flickering-monitors-part-2-youre-not-grounded" rel="noopener noreferrer"&gt;https://ariabramowitz.me/the-tale-of-the-flickering-monitors-part-2-youre-not-grounded&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1755765138970%2Fc8158aed-e3d5-4d3d-a4b3-6cbd9b57d4ca.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1755765138970%2Fc8158aed-e3d5-4d3d-a4b3-6cbd9b57d4ca.jpeg" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;]]&amp;gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>hardware</category>
      <category>troubleshooting</category>
      <category>work</category>
    </item>
    <item>
      <title>Linux Boot Trouble: "Gave up waiting for root file system"</title>
      <dc:creator>Ari Abramowitz</dc:creator>
      <pubDate>Sun, 04 May 2025 19:39:50 +0000</pubDate>
      <link>https://forem.com/ariabramowitz/linux-boot-trouble-gave-up-waiting-for-root-file-system-146e</link>
      <guid>https://forem.com/ariabramowitz/linux-boot-trouble-gave-up-waiting-for-root-file-system-146e</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad05gyvu08uvfqqwlio1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad05gyvu08uvfqqwlio1.jpeg" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently ran into the error above while trying to start up my dual-boot Lenovo laptop (Kubuntu + Windows 11). These are the steps I took to fix it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Starting with &lt;a href="https://askubuntu.com/a/1482431" rel="noopener noreferrer"&gt;this SO post&lt;/a&gt;, I did the following:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ran &lt;code&gt;sudo file -s /dev/sda3&lt;/code&gt; to check the filesystem type. Output was &lt;code&gt;data&lt;/code&gt;, suggesting this was likely not the right partition. No other partition seemed to be the one I was looking for.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Went to BIOS to check various settings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Went to Lenovo boot menu and selected Ubuntu was able to start up (?!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ran the following to reinstall GRUB Bootloader:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ran &lt;code&gt;cat /etc/fstab&lt;/code&gt; to make sure things looked right: &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Saved a backup of my fstab in case this happens again:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rebooted the laptop to see if the fix held: &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removed several old popos entries in the laptops boot order. Not clear if those had anything to do with this, but cant hurt to remove&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;]]&amp;gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>dualbooting</category>
      <category>work</category>
    </item>
    <item>
      <title>Python Operator Chaining… and why you still can’t trust ChatGPT</title>
      <dc:creator>Ari Abramowitz</dc:creator>
      <pubDate>Sat, 08 Mar 2025 19:04:10 +0000</pubDate>
      <link>https://forem.com/ariabramowitz/python-operator-chaining-and-why-you-still-cant-trust-chatgpt-19hm</link>
      <guid>https://forem.com/ariabramowitz/python-operator-chaining-and-why-you-still-cant-trust-chatgpt-19hm</guid>
      <description>&lt;p&gt;A colleague of mine recently posted the following on a Teams channel which we’ve appropriately named “Something cool I learned today!”:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;"a" in "abc" is True&lt;/code&gt; will evaluate to &lt;code&gt;False&lt;/code&gt; (!)&lt;/p&gt;

&lt;p&gt;This is because the [Python] interpreter reads this as &lt;code&gt;"a" in ("abc" is True)&lt;/code&gt;, which is the same as &lt;code&gt;"a" in False&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first problem with this, which I did not catch until later, is that &lt;code&gt;"a" in False&lt;/code&gt; does not in fact evaluate to &lt;code&gt;False&lt;/code&gt;. It raises an exception because &lt;code&gt;False&lt;/code&gt; is not iterable so the &lt;code&gt;in&lt;/code&gt; operator does not work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="nc"&gt;Traceback &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;stdin&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bool&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;iterable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having overlooked that issue, I was about to respond with &lt;a href="https://www.geeksforgeeks.org/precedence-and-associativity-of-operators-in-python/" rel="noopener noreferrer"&gt;this link&lt;/a&gt; giving more details about operator precedence in Python. However, after looking more closely at the explanation there, I noticed something else: &lt;em&gt;&lt;code&gt;in&lt;/code&gt; and &lt;code&gt;is&lt;/code&gt; have the same precedence&lt;/em&gt; and have left-to-right associativity (they get processed left-to-right). Following that, I would have expected the example to evaluate to &lt;code&gt;True&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; ("a" in "abc") is True
&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; True
&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But when I actually ran the code, it returned &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Something wasn't lining up, so I decided to do some more digging. I started with a conversation with ChatGPT that went something like this (full thread here - &lt;a href="https://chatgpt.com/share/67c629cb-38e8-8013-8daf-290abec2600a):" rel="noopener noreferrer"&gt;https://chatgpt.com/share/67c629cb-38e8-8013-8daf-290abec2600a):&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: Hey, ChatGPT, what's going on here?&lt;br&gt;
&lt;strong&gt;ChatGPT&lt;/strong&gt;: Simple. It’s operator precedence.&lt;br&gt;
&lt;strong&gt;Me&lt;/strong&gt;: But don’t &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;in&lt;/code&gt; have the same precedence?&lt;br&gt;
&lt;strong&gt;ChatGPT&lt;/strong&gt;: Good point. This should evaluate to &lt;code&gt;True&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Me&lt;/strong&gt;: But it doesn’t.&lt;br&gt;
&lt;strong&gt;ChatGPT&lt;/strong&gt;: Oooohhh. Riiiighht. It’s &lt;em&gt;operator chaining&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was a good reminder that ChatGPT is still not a Python expert. I would have expected it to catch both of the points I mentioned above, unravel the incorrect assumptions, and then give the correct explanation. Instead, it gave a misleading answer and only corrected itself after two rounds of prodding. Oh well.&lt;/p&gt;

&lt;p&gt;Needless to say, my conversation with ChatGPT was not the &lt;em&gt;most&lt;/em&gt; confidence-inspiring one I’ve had in my life, so I went to Google next. I found a Stack Overflow post with a similar question and the same explanation that ChatGPT eventually gave: &lt;a href="https://stackoverflow.com/questions/31487806/a-in-abc-true-evaluates-to-false" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/31487806/a-in-abc-true-evaluates-to-false&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essentially, because of "operator chaining" the example above, &lt;code&gt;"a" in "abc" is True&lt;/code&gt;, translates to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;abc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;abc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;"abc"&lt;/code&gt; is not &lt;code&gt;True&lt;/code&gt;, the right half of the expression, and thereby all of it, evaluates to &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is similar to how Python evaluates &lt;code&gt;1 &amp;lt; 2 &amp;lt; 3&lt;/code&gt; as &lt;code&gt;(1 &amp;lt; 2) and (2 &amp;lt; 3)&lt;/code&gt;. Alternatively, using the example from &lt;a href="https://docs.python.org/3/reference/expressions.html#comparisons" rel="noopener noreferrer"&gt;the Python docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;x &amp;lt; y &amp;lt;= z&lt;/code&gt; is equivalent to &lt;code&gt;x &amp;lt; y and y &amp;lt;= z&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I had known about this rule generally, but did not realize it applied in a case like this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lessons learned:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If two or more comparison operators are "chained" together, Python inserts &lt;code&gt;and&lt;/code&gt;s between them to interpret what's going on.

&lt;ul&gt;
&lt;li&gt;"Comparison operators" include: &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;!=&lt;/code&gt;, &lt;code&gt;is&lt;/code&gt;, &lt;code&gt;is not&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt;, and &lt;code&gt;not in&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ChatGPT is not a Python expert... yet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more on this, check out these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GeeksForGeeks on operator precedence: &lt;a href="https://www.geeksforgeeks.org/precedence-and-associativity-of-operators-in-python/" rel="noopener noreferrer"&gt;https://www.geeksforgeeks.org/precedence-and-associativity-of-operators-in-python/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack Overflow on the example covered here: &lt;a href="https://stackoverflow.com/questions/31487806/a-in-abc-true-evaluates-to-false" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/31487806/a-in-abc-true-evaluates-to-false&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Python docs on operators: &lt;a href="https://docs.python.org/3/reference/expressions.html#comparisons" rel="noopener noreferrer"&gt;https://docs.python.org/3/reference/expressions.html#comparisons&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PEP 535 – Rich comparison chaining: &lt;a href="https://peps.python.org/pep-0535/" rel="noopener noreferrer"&gt;https://peps.python.org/pep-0535/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Python Imports and Module Caching: Behind the Scenes</title>
      <dc:creator>Ari Abramowitz</dc:creator>
      <pubDate>Sat, 08 Mar 2025 18:59:21 +0000</pubDate>
      <link>https://forem.com/ariabramowitz/python-imports-and-module-caching-behind-the-scenes-3g5n</link>
      <guid>https://forem.com/ariabramowitz/python-imports-and-module-caching-behind-the-scenes-3g5n</guid>
      <description>&lt;p&gt;&lt;small&gt;This is another post based on &lt;a href="https://www.udemy.com/course/python-3-deep-dive-part-1/" rel="noopener noreferrer"&gt;Dr. Fred Baptiste' Python 3: Deep Dive&lt;/a&gt; series. For more, head over to Udemy.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;What happens behind the scenes in a python &lt;code&gt;import&lt;/code&gt; statement? Glad I asked. Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;b&gt;Check &lt;code&gt;sys.modules&lt;/code&gt;:&lt;/b&gt; Python first checks &lt;code&gt;sys.modules&lt;/code&gt; to see if your module has already been loaded.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sys.modules&lt;/code&gt; is a regular python &lt;code&gt;dict&lt;/code&gt; that is used to cache modules. The keys are strings of the modules' names and the values are module objects (i.e. objects of type &lt;code&gt;ModuleType&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;If your module is already in &lt;code&gt;sys.modules&lt;/code&gt;, python adds the cached version to &lt;code&gt;globals()&lt;/code&gt; and skips the steps below.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Create a module object:&lt;/b&gt; If python does not find the module in &lt;code&gt;sys.modules&lt;/code&gt;, it creates a new &lt;code&gt;ModuleType&lt;/code&gt; object and loads the module's source code into it&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Cache the module:&lt;/b&gt; The new &lt;code&gt;module&lt;/code&gt; objects is added to the &lt;code&gt;sys.modules&lt;/code&gt; cache&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Compile and execute:&lt;/b&gt; Python compiles and &lt;em&gt;executes&lt;/em&gt; the source code from your module&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Add to &lt;code&gt;globals()&lt;/code&gt;:&lt;/b&gt; Python and adds your module to &lt;code&gt;globals()&lt;/code&gt;, making it available for use going forward.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;b&gt;Key Point&lt;/b&gt;: It is often said that importing a python module will execute all of the code in the module. That is only partly true. &lt;b&gt;Python only executes a module the first time it is imported, then caches it in &lt;code&gt;sys.modules&lt;/code&gt;.&lt;/b&gt; Subsequent &lt;code&gt;import&lt;/code&gt; statements throughout your code, even in different files, will refer back to the cached version and will not execute the module again.&lt;/p&gt;

&lt;p&gt;Below is a bit of code to bring all of this home. We will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a simple module (&lt;code&gt;module1&lt;/code&gt;) with a print statement so we can see when the module gets executed.&lt;/li&gt;
&lt;li&gt;Import &lt;code&gt;module1&lt;/code&gt; into &lt;code&gt;main.py&lt;/code&gt;, which will execute &lt;code&gt;module1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;module1&lt;/code&gt; from &lt;code&gt;globals()&lt;/code&gt;, then try accessing it to demonstrate that it is no longer available.&lt;/li&gt;
&lt;li&gt;Re-import &lt;code&gt;module1&lt;/code&gt;. This will add &lt;code&gt;module1&lt;/code&gt; back to &lt;code&gt;globals()&lt;/code&gt;, but will use the cached version from &lt;code&gt;sys.modules&lt;/code&gt; and will not re-execute &lt;code&gt;module1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Access &lt;code&gt;module1&lt;/code&gt; again to demonstrate that is has in fact been added back to &lt;code&gt;globals()&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# module1.py
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Running module1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# main.py
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;======== Running main.py ======== &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Importing module1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;module1&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deleting module1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;module1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Deletes from globals(), but not from sys.modules
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accessing module 1 after deleting from globals()&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# This will cause an exception. module1 is still cached in `sys.modules`,
&lt;/span&gt;    &lt;span class="c1"&gt;# but the reference to the cache has been removed from globals()
&lt;/span&gt;    &lt;span class="n"&gt;module1&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;NameError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NameError&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Re-importing module1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Adds the cached version of module1 back to globals(), without
# re-executing the module
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;module1&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accessing module 1 after re-importing from globals()&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;module1&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Done!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=================================&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output from main.py:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;======== Running main.py ========
Importing module1
Running module1
Deleting module1
Accessing module 1 after deleting from globals()
NameError name 'module1' is not defined
Re-importing module1
Accessing module 1 after re-importing from globals()
Done!
=================================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
    </item>
    <item>
      <title>Namedtuple Default Values</title>
      <dc:creator>Ari Abramowitz</dc:creator>
      <pubDate>Sat, 08 Mar 2025 18:53:47 +0000</pubDate>
      <link>https://forem.com/ariabramowitz/namedtuple-default-values-3ame</link>
      <guid>https://forem.com/ariabramowitz/namedtuple-default-values-3ame</guid>
      <description>&lt;p&gt;I've been making my way through a deep-dive python series on Udemy (I highly recommend it - &lt;a href="https://www.udemy.com/course/python-3-deep-dive-part-1/" rel="noopener noreferrer"&gt;Python 3: Deep Dive by Dr. Fred Baptiste&lt;/a&gt;). The course recently touched on the question of how to set default arguments on a &lt;code&gt;namedtuple&lt;/code&gt;. I found out afterwards that as of python 3.7 &lt;code&gt;namedtuple&lt;/code&gt; has a &lt;code&gt;defaults&lt;/code&gt; argument (&lt;a href="https://docs.python.org/3/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields" rel="noopener noreferrer"&gt;see the docs&lt;/a&gt;), making the following neat little trick largely irrelevant. We'll pretend that doesn't exist for the moment.&lt;/p&gt;

&lt;p&gt;Dr. Baptiste's way around the problem relies on the &lt;code&gt;__new__&lt;/code&gt; method and the &lt;code&gt;__defaults__&lt;/code&gt; property, neither of which typically get much air time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;__new__&lt;/code&gt; is a built in method on all classes. It creates an instance of the class (before &lt;code&gt;__init__&lt;/code&gt; gets called)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__defaults__&lt;/code&gt; is a property on all functions that stores the default values, and it's writable

&lt;ul&gt;
&lt;li&gt;if there are fewer defaults than function arguments, the values get "right aligned". See the screenshot:
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnnl9e5asz18pc0keicgg.png" alt=" " width="498" height="474"&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;If you're on python 3.7+, stick with the built-in option. If not though, good to know you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;namedtuple&lt;/span&gt;

&lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;namedtuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Point&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;z&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# Defaults `y` to 2, and `z` to 3. `x` has no default
&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__defaults__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# Point(x=1, y=2, z=3)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
    </item>
    <item>
      <title>Python Decorators: How They Work and How to Write One</title>
      <dc:creator>Ari Abramowitz</dc:creator>
      <pubDate>Sat, 08 Mar 2025 18:42:03 +0000</pubDate>
      <link>https://forem.com/ariabramowitz/python-decorators-how-they-work-and-how-to-write-one-1dig</link>
      <guid>https://forem.com/ariabramowitz/python-decorators-how-they-work-and-how-to-write-one-1dig</guid>
      <description>&lt;p&gt;This is a dev talk I gave back in February 2023 at Centers Healthcare explaining how python decorators work and how to write one. Enjoy!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Rm_t21RUHqM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>Python Imports and Module Caching</title>
      <dc:creator>Ari Abramowitz</dc:creator>
      <pubDate>Tue, 14 Jan 2025 22:00:00 +0000</pubDate>
      <link>https://forem.com/ariabramowitz/python-imports-and-module-caching-109i</link>
      <guid>https://forem.com/ariabramowitz/python-imports-and-module-caching-109i</guid>
      <description>&lt;p&gt;&lt;em&gt;This is another post based on Dr. Fred Baptiste Python 3: Deep Dive series. For more,&lt;/em&gt; &lt;a href="https://www.udemy.com/course/python-3-deep-dive-part-1/" rel="noopener noreferrer"&gt;&lt;em&gt;head over to Udemy.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What happens behind the scenes in a python &lt;code&gt;import&lt;/code&gt; statement? Glad I asked. Heres how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check&lt;/strong&gt; &lt;code&gt;sys.modules&lt;/code&gt; &lt;strong&gt;:&lt;/strong&gt; Python first checks &lt;code&gt;sys.modules&lt;/code&gt; to see if your module has already been loaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a module object:&lt;/strong&gt; If python does not find the module in &lt;code&gt;sys.modules&lt;/code&gt;, it creates a new &lt;code&gt;ModuleType&lt;/code&gt; object and loads the modules source code into it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache the module:&lt;/strong&gt; The new &lt;code&gt;module&lt;/code&gt; objects is added to the &lt;code&gt;sys.modules&lt;/code&gt; cache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compile and execute:&lt;/strong&gt; Python compiles and executes the source code from your module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add to&lt;/strong&gt; &lt;code&gt;globals()&lt;/code&gt; &lt;strong&gt;:&lt;/strong&gt; Python and adds your module to &lt;code&gt;globals()&lt;/code&gt;, making it available for use going forward.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Key Point&lt;/strong&gt; : It is often said that importing a python module will execute all of the code in the module. That is only partly true. &lt;strong&gt;Python only executes a module the first time it is imported, then caches it in&lt;/strong&gt; &lt;code&gt;sys.modules&lt;/code&gt;. Subsequent &lt;code&gt;import&lt;/code&gt; statements throughout your code, even in different files, will refer back to the cached version and will not execute the module again.&lt;/p&gt;

&lt;p&gt;Below is a bit of code to bring all of this home. We will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a simple module (&lt;code&gt;module1&lt;/code&gt;) with a print statement so we can see when the module gets executed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import &lt;code&gt;module1&lt;/code&gt; into &lt;code&gt;main.py&lt;/code&gt;, which will execute &lt;code&gt;module1&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete &lt;code&gt;module1&lt;/code&gt; from &lt;code&gt;globals()&lt;/code&gt;, then try accessing it to demonstrate that it is no longer available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-import &lt;code&gt;module1&lt;/code&gt;. This will add &lt;code&gt;module1&lt;/code&gt; back to &lt;code&gt;globals()&lt;/code&gt;, but will use the cached version from &lt;code&gt;sys.modules&lt;/code&gt; and will not re-execute &lt;code&gt;module1&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access &lt;code&gt;module1&lt;/code&gt; again to demonstrate that is has in fact been added back to &lt;code&gt;globals()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# module1.pyprint("Running module1")# main.pyprint("======== Running main.py ======== ")print("Importing module1")import module1print("Deleting module1")del globals()["module1"] # Deletes from globals(), but not from sys.modulestry: print("Accessing module 1 after deleting from globals()") # This will cause an exception. module1 is still cached in `sys.modules`, # but the reference to the cache has been removed from globals() module1except NameError as e: print("NameError", e)print("Re-importing module1")# Adds the cached version of module1 back to globals(), without# re-executing the moduleimport module1print("Accessing module 1 after re-importing from globals()")module1print("Done!")print("=================================")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output from main.py:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;======== Running main.py ========Importing module1Running module1Deleting module1Accessing module 1 after deleting from globals()NameError name 'module1' is not definedRe-importing module1Accessing module 1 after re-importing from globals()Done!=================================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;]]&amp;gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>work</category>
    </item>
  </channel>
</rss>
