<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Chú Út Miền Tây's Substack: Nền tảng để lên level - Python]]></title><description><![CDATA[Đi sâu vào bản chất mô hình dữ liệu, cơ chế quản lý bộ nhớ và tư duy hệ thống của Python. Chuỗi bài giúp dân backend làm chủ ngôn ngữ, tối ưu hiệu năng và né bẫy bug kinh điển.]]></description><link>https://quakebaynghe.substack.com/s/nen-tang-e-len-level-python</link><image><url>https://substackcdn.com/image/fetch/$s_!IeAC!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d9a847-4b1b-4d5d-89d2-289fb66bdda1_688x688.png</url><title>Chú Út Miền Tây&apos;s Substack: Nền tảng để lên level - Python</title><link>https://quakebaynghe.substack.com/s/nen-tang-e-len-level-python</link></image><generator>Substack</generator><lastBuildDate>Fri, 19 Jun 2026 14:53:35 GMT</lastBuildDate><atom:link href="https://quakebaynghe.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Chú Út Miền Tây]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[quakebaynghe@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[quakebaynghe@substack.com]]></itunes:email><itunes:name><![CDATA[Chú Út Miền Tây]]></itunes:name></itunes:owner><itunes:author><![CDATA[Chú Út Miền Tây]]></itunes:author><googleplay:owner><![CDATA[quakebaynghe@substack.com]]></googleplay:owner><googleplay:email><![CDATA[quakebaynghe@substack.com]]></googleplay:email><googleplay:author><![CDATA[Chú Út Miền Tây]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Closure trong Python: vì sao hàm nhớ sai giá trị?]]></title><description><![CDATA[N&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level &#183; Python &#183; B&#224;i 5 - Late binding, LEGB v&#224; b&#7851;y scope trong Python]]></description><link>https://quakebaynghe.substack.com/p/python-scope-legb-closure</link><guid isPermaLink="false">https://quakebaynghe.substack.com/p/python-scope-legb-closure</guid><dc:creator><![CDATA[Chú Út Miền Tây]]></dc:creator><pubDate>Fri, 19 Jun 2026 13:02:06 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IeAC!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d9a847-4b1b-4d5d-89d2-289fb66bdda1_688x688.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><span>B&#224;i 5 - series </span><em>&#8220;Python cho d&#226;n backend: n&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level&#8221;</em><span>.</span></p></blockquote><p>C&#226;u &#273;&#7889; l&#224;m dev trung c&#7845;p c&#361;ng v&#7845;p:</p><pre><code><code>fns = [lambda: i for i in range(3)]
print([f() for f in fns])   # t&#432;&#7903;ng [0, 1, 2]... th&#7921;c ra [2, 2, 2] (!)</code></code></pre><p>T&#7841;o ba lambda trong v&#242;ng l&#7863;p, m&#7895;i c&#225;i &#8220;&#273;&#225;ng l&#7869;&#8221; gi&#7919; m&#7897;t gi&#225; tr&#7883; <code>i</code> kh&#225;c nhau. Nh&#432;ng c&#7843; ba &#273;&#7873;u tr&#7843; <code>2</code>. V&#236; sao? &#272;&#226;y l&#224; <strong>late binding</strong> trong closure - b&#7851;y c&#7921;c hay g&#7863;p khi &#273;&#259;ng k&#253; callback/handler trong v&#242;ng l&#7863;p.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://quakebaynghe.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ch&#250; &#218;t Mi&#7873;n T&#226;y's Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><blockquote><p><strong>D&#249;ng AI coding agent?</strong> Late binding trong v&#242;ng l&#7863;p l&#224; m&#7897;t trong nh&#7919;ng bug AI hay t&#7841;o ra nh&#7913;t m&#224; kh&#244;ng c&#7843;nh b&#225;o - n&#243; sinh code tr&#244;ng ho&#224;n to&#224;n h&#7907;p l&#7879;, ch&#7841;y kh&#244;ng l&#7895;i, ch&#7881; ra k&#7871;t qu&#7843; sai. <code>UnboundLocalError</code> th&#236; c&#242;n th&#7845;y ngay; late binding th&#236; &#226;m th&#7847;m. Kh&#244;ng hi&#7875;u closure th&#236; &#273;&#7885;c code AI xong c&#361;ng kh&#244;ng th&#7845;y g&#236; l&#7841; - t&#7899;i khi handler n&#224;o c&#361;ng ch&#7841;y v&#7899;i gi&#225; tr&#7883; cu&#7889;i m&#7899;i ng&#7891;i g&#227;i &#273;&#7847;u.</p></blockquote><h2>Tr&#432;&#7899;c h&#7871;t, closure l&#224; g&#236;?</h2><p>B&#7887; lambda qua m&#7897;t b&#234;n cho d&#7877; h&#236;nh dung. Closure l&#224; <strong>m&#7897;t h&#224;m b&#234;n trong &#8220;nh&#7899;&#8221; &#273;&#432;&#7907;c bi&#7871;n c&#7911;a h&#224;m bao ngo&#224;i, k&#7875; c&#7843; sau khi h&#224;m ngo&#224;i &#273;&#227; ch&#7841;y xong v&#224; tr&#7843; v&#7873;</strong>. Vi&#7871;t b&#7857;ng <code>def</code> l&#7891;ng <code>def</code> cho r&#245;:</p><pre><code><code>def tao_nhan(he_so):
    def nhan(x):
        return x * he_so        # nhan "nh&#7899;" he_so c&#7911;a h&#224;m bao ngo&#224;i
    return nhan
 
nhan_doi = tao_nhan(2)
nhan_ba  = tao_nhan(3)
print(nhan_doi(10))   # 20  &#8594; nh&#7899; he_so = 2
print(nhan_ba(10))    # 30  &#8594; nh&#7899; he_so = 3</code></code></pre><p><code>tao_nhan</code> ch&#7841;y xong, &#273;&#227; <code>return</code> r&#7891;i - v&#7853;y m&#224; <code>nhan_doi</code> v&#7851;n bi&#7871;t <code>he_so = 2</code>, <code>nhan_ba</code> v&#7851;n bi&#7871;t <code>he_so = 3</code>. H&#224;m b&#234;n trong &#8220;g&#243;i theo&#8221; bi&#7871;n c&#7911;a h&#224;m ngo&#224;i &#273;&#7875; x&#224;i sau &#8594; &#273;&#243; ch&#237;nh l&#224; <strong>closure</strong>. M&#7845;u ch&#7889;t: m&#7895;i l&#7847;n g&#7885;i <code>tao_nhan</code> t&#7841;o ra <strong>m&#7897;t bi&#7871;n </strong><code>he_so</code><strong> M&#7898;I ri&#234;ng</strong>, n&#234;n hai closure nh&#7899; hai gi&#225; tr&#7883; kh&#225;c nhau - ch&#7841;y &#273;&#250;ng nh&#432; b&#226;y mong.</p><h2>Nh&#432;ng closure b&#7855;t BI&#7870;N, kh&#244;ng b&#7855;t GI&#193; TR&#7882;</h2><p>&#272;&#226;y m&#7899;i l&#224; ch&#7895; &#273;&#7867; ra c&#225;i &#273;&#7889; &#273;&#7847;u b&#224;i. &#272;a s&#7889; ngh&#297; closure &#8220;ch&#7909;p&#8221; <em>gi&#225; tr&#7883;</em> t&#7841;i th&#7901;i &#273;i&#7875;m t&#7841;o. Sai:</p><blockquote><p>Closure gi&#7919; <strong>tham chi&#7871;u t&#7899;i bi&#7871;n</strong>, kh&#244;ng ph&#7843;i b&#7843;n sao gi&#225; tr&#7883;. N&#243; &#273;&#7885;c gi&#225; tr&#7883; c&#7911;a bi&#7871;n &#273;&#243; <strong>l&#250;c b&#7883; g&#7885;i</strong>, ch&#7913; kh&#244;ng ph&#7843;i l&#250;c t&#7841;o.</p></blockquote><p>V&#237; d&#7909; <code>tao_nhan</code> &#7903; tr&#234;n &#8220;c&#243; v&#7867; &#273;&#250;ng&#8221; ch&#7881; v&#236; <strong>m&#7895;i l&#7847;n g&#7885;i t&#7841;o m&#7897;t </strong><code>he_so</code><strong> ri&#234;ng</strong>. C&#242;n trong v&#242;ng l&#7863;p th&#236; ng&#432;&#7907;c l&#7841;i - ch&#7881; c&#243; <strong>m&#7897;t</strong> bi&#7871;n <code>i</code> d&#249;ng chung cho c&#7843; ba h&#224;m. Vi&#7871;t l&#7841;i c&#225;i &#273;&#7889; b&#7857;ng <code>def</code> (kh&#7887;i lambda) cho th&#7845;y &#273;&#226;y <em>kh&#244;ng ph&#7843;i l&#7895;i c&#7911;a lambda</em>:</p><pre><code><code>fns = []
for i in range(3):
    def f():
        return i        # c&#7843; ba f c&#249;ng nh&#7899; M&#7896;T bi&#7871;n i
    fns.append(f)
 
print([f() for f in fns])   # [2, 2, 2] - y chang b&#7843;n lambda</code></code></pre><p>Ba h&#224;m <code>f</code> c&#249;ng tr&#7887; v&#7873; <strong>m&#7897;t</strong> bi&#7871;n <code>i</code> (v&#242;ng l&#7863;p d&#249;ng &#273;i d&#249;ng l&#7841;i &#273;&#250;ng m&#7897;t bi&#7871;n &#273;&#243;). T&#7899;i l&#250;c b&#226;y <em>g&#7885;i</em> ch&#250;ng - v&#242;ng l&#7863;p &#273;&#227; xong t&#7915; &#273;&#7901;i n&#224;o, <code>i</code> &#273;ang l&#224; <code>2</code> &#8594; c&#7843; ba &#273;&#7885;c ra <code>2</code>. &#272;&#243; g&#7885;i l&#224; <strong>late binding</strong>: gi&#225; tr&#7883; &#273;&#432;&#7907;c &#273;&#7885;c <em>mu&#7897;n</em>, l&#250;c g&#7885;i, kh&#244;ng ph&#7843;i l&#250;c t&#7841;o.</p><h2>LEGB: Python t&#236;m t&#234;n &#7903; &#273;&#226;u</h2><p>Khi g&#7863;p m&#7897;t t&#234;n, Python tra theo th&#7913; t&#7921; <strong>LEGB</strong>:</p><ul><li><p><strong>L</strong>ocal - trong h&#224;m hi&#7879;n t&#7841;i.</p></li><li><p><strong>E</strong>nclosing - h&#224;m bao ngo&#224;i (closure).</p></li><li><p><strong>G</strong>lobal - c&#7845;p module.</p></li><li><p><strong>B</strong>uilt-in - <code>len</code>, <code>print</code>...<br>Lambda &#7903; tr&#234;n t&#236;m <code>i</code> kh&#244;ng th&#7845;y &#7903; Local &#8594; l&#234;n Enclosing/Global, th&#7845;y c&#225;i <code>i</code> c&#7911;a v&#242;ng l&#7863;p &#8594; d&#249;ng chung n&#243;.</p></li></ul><h2>B&#7851;y k&#232;m theo: <code>UnboundLocalError</code></h2><p>C&#249;ng h&#7885; scope, m&#224; c&#7855;n ng&#432;&#7901;i ta nhi&#7873;u kh&#244;ng k&#233;m. G&#7889;c c&#7911;a n&#243; l&#224; m&#7897;t quy t&#7855;c ph&#7843;i n&#7857;m l&#242;ng:</p><blockquote><p>Python quy&#7871;t m&#7897;t t&#234;n l&#224; <strong>local hay kh&#244;ng NGAY L&#218;C BI&#202;N D&#7882;CH h&#224;m</strong> (tr&#432;&#7899;c khi ch&#7841;y), b&#7857;ng c&#225;ch qu&#233;t <strong>to&#224;n b&#7897; th&#226;n h&#224;m</strong>: n&#7871;u m&#7897;t t&#234;n <strong>&#273;&#432;&#7907;c G&#193;N &#7903; B&#7844;T K&#7922; &#272;&#194;U</strong> trong h&#224;m &#8594; t&#234;n &#273;&#243; l&#224; <strong>local cho C&#7842; h&#224;m</strong>, m&#7885;i d&#242;ng - k&#7875; c&#7843; d&#242;ng <em>tr&#432;&#7899;c</em> ch&#7895; g&#225;n.</p></blockquote><pre><code><code>x = 1
def f():
    print(x)    # UnboundLocalError!
    x = 2</code></code></pre><p>&#272;&#7885;c k&#7929; v&#236; sao l&#7895;i: v&#236; c&#243; d&#242;ng <code>x = 2</code> &#273;&#226;u &#273;&#243; trong <code>f</code>, Python &#273;&#227; quy&#7871;t <code>x</code> l&#224; <strong>bi&#7871;n local c&#7911;a </strong><code>f</code> - su&#7889;t c&#7843; h&#224;m. T&#7899;i l&#250;c ch&#7841;y <code>print(x)</code>, bi&#7871;n local <code>x</code> &#273;&#243; <strong>ch&#432;a &#273;&#432;&#7907;c g&#225;n gi&#225; tr&#7883; n&#224;o</strong> &#8594; &#8220;d&#249;ng tr&#432;&#7899;c khi g&#225;n&#8221; &#8594; <code>UnboundLocalError</code>. N&#243; <strong>KH&#212;NG</strong> l&#249;i ra &#273;&#7885;c <code>x = 1</code> &#7903; global, v&#236; &#273;&#227; ch&#7889;t <code>x</code> l&#224; local r&#7891;i.</p><p>&#272;&#7889;i chi&#7871;u cho th&#7845;y ch&#237;nh ph&#233;p <strong>G&#193;N</strong> m&#7899;i l&#224; th&#7911; ph&#7841;m:</p><pre><code><code>x = 1
def chi_doc():
    print(x)    # in ra 1 - OK, v&#236; KH&#212;NG c&#243; d&#242;ng n&#224;o g&#225;n x &#8594; x l&#224; global (LEGB)</code></code></pre><p>Kh&#244;ng c&#243; g&#225;n &#8594; <code>x</code> &#273;&#432;&#7907;c tra ra ngo&#224;i theo LEGB, &#273;&#7885;c global b&#236;nh th&#432;&#7901;ng. C&#243; g&#225;n &#8594; <code>x</code> b&#7883; &#8220;local h&#243;a&#8221; c&#7843; h&#224;m &#8594; &#273;&#7885;c tr&#432;&#7899;c khi g&#225;n l&#224; ch&#7871;t.</p><p><strong>Ca &#273;&#7901;i th&#7921;c hay d&#237;nh nh&#7913;t - d&#249;ng </strong><code>+=</code><strong> v&#7899;i bi&#7871;n ngo&#224;i:</strong></p><pre><code><code>dem = 0
def tang():
    dem += 1    # UnboundLocalError!</code></code></pre><p><code>dem += 1</code> v&#7915;a <strong>&#273;&#7885;c</strong> v&#7915;a <strong>ghi</strong> <code>dem</code>. V&#236; c&#243; ghi &#8594; <code>dem</code> th&#224;nh local c&#7843; h&#224;m &#8594; l&#250;c &#273;&#7885;c (<code>dem + 1</code>) bi&#7871;n local ch&#432;a c&#243; gi&#225; tr&#7883; &#8594; l&#7895;i. Tr&#244;ng nh&#432; &#8220;tao ch&#7881; t&#259;ng c&#225;i bi&#7871;n &#273;&#7871;m&#8221; m&#224; s&#7853;p, kh&#243; hi&#7875;u n&#7871;u kh&#244;ng bi&#7871;t quy t&#7855;c tr&#234;n.</p><p><strong>C&#225;ch s&#7917;a:</strong></p><ul><li><p><code>global dem</code> - n&#7871;u mu&#7889;n ghi v&#224;o bi&#7871;n c&#7845;p module.</p></li><li><p><code>nonlocal dem</code> - n&#7871;u mu&#7889;n ghi v&#224;o bi&#7871;n c&#7911;a h&#224;m bao ngo&#224;i (trong closure).</p></li><li><p>Ho&#7863;c &#273;&#7893;i t&#234;n bi&#7871;n local cho kh&#7887;i &#273;&#7909;ng t&#234;n ngo&#224;i; ho&#7863;c &#273;&#7885;c gi&#225; tr&#7883; ngo&#224;i v&#224;o m&#7897;t t&#234;n kh&#225;c r&#7891;i m&#7899;i x&#224;i.</p></li></ul><pre><code><code>dem = 0
def tang():
    global dem
    dem += 1    # OK</code></code></pre><h2>C&#225;ch s&#7917;a late binding: bind gi&#225; tr&#7883; ngay l&#250;c t&#7841;o</h2><p>M&#7865;o kinh &#273;i&#7875;n - d&#249;ng <strong>default argument</strong> &#273;&#7875; &#8220;ch&#7889;t&#8221; gi&#225; tr&#7883; <code>i</code> t&#7841;i th&#7901;i &#273;i&#7875;m t&#7841;o (v&#236; default &#273;&#432;&#7907;c t&#237;nh ngay - nh&#7899; b&#224;i 1):</p><pre><code><code>fns = [lambda i=i: i for i in range(3)]   # m&#7895;i lambda ch&#7889;t i ri&#234;ng
print([f() for f in fns])                 # [0, 1, 2] - &#273;&#250;ng r&#7891;i</code></code></pre><p><code>lambda i=i</code> ngh&#297;a: tham s&#7889; <code>i</code> c&#243; default l&#224; <em>gi&#225; tr&#7883; hi&#7879;n t&#7841;i</em> c&#7911;a <code>i</code> l&#250;c t&#7841;o &#8594; m&#7895;i c&#225;i gi&#7919; m&#7897;t b&#7843;n ri&#234;ng. M&#7865;o y v&#7853;y v&#7899;i <code>def</code> l&#7891;ng (kh&#7887;i lambda):</p><pre><code><code>fns = []
for i in range(3):
    def f(i=i):        # default i ch&#7889;t gi&#225; tr&#7883; t&#7841;i th&#7901;i &#273;i&#7875;m t&#7841;o
        return i
    fns.append(f)
print([f() for f in fns])   # [0, 1, 2]</code></code></pre><h2>H&#7879; qu&#7843; th&#7921;c chi&#7871;n (b&#7851;y)</h2><p>B&#7851;y n&#224;y c&#7855;n nh&#7913;t khi b&#226;y <strong>t&#7841;o callback/handler trong v&#242;ng l&#7863;p</strong> - &#273;&#259;ng k&#253; route, event handler, button onclick, task... T&#7845;t c&#7843; &#8220;d&#237;nh&#8221; bi&#7871;n v&#242;ng l&#7863;p cu&#7889;i c&#249;ng. Th&#7845;y m&#7845;y handler c&#7913; ch&#7841;y v&#7899;i gi&#225; tr&#7883; cu&#7889;i thay v&#236; gi&#225; tr&#7883; ri&#234;ng &#8594; &#273;&#237;ch th&#7883; late binding.</p><h2>Closure hay d&#249;ng &#273;&#7875; l&#224;m g&#236; trong th&#7921;c t&#7871;</h2><p>Khi &#273;&#227; hi&#7875;u closure l&#224; &#8220;h&#224;m mang theo ng&#7919; c&#7843;nh&#8221;, b&#226;y th&#7845;y n&#243; xu&#7845;t hi&#7879;n kh&#7855;p n&#417;i:</p><p><strong>1. T&#7841;o h&#224;m &#8220;c&#7845;u h&#236;nh s&#7861;n&#8221; (partial application).</strong> Thay v&#236; vi&#7871;t &#273;i vi&#7871;t l&#7841;i c&#249;ng m&#7897;t tham s&#7889;:</p><pre><code><code>def nhan_voi(he_so):
    def nhan(x):
        return x * he_so
    return nhan
 
gap_doi = nhan_voi(2)
gap_ba  = nhan_voi(3)
print(gap_doi(5))    # 10
print(gap_ba(5))     # 15</code></code></pre><p>Closure &#8220;&#273;&#243;ng g&#243;i&#8221; <code>he_so</code> v&#224;o h&#224;m &#8594; b&#226;y c&#243; h&#224;m chuy&#234;n d&#7909;ng m&#224; kh&#244;ng ph&#7843;i truy&#7873;n <code>he_so</code> l&#7841;i m&#7895;i l&#7847;n. (<code>functools.partial</code> l&#224;m &#273;i&#7873;u t&#432;&#417;ng t&#7921; cho h&#224;m b&#7845;t k&#7923; - nh&#432;ng bi&#7871;t closure th&#236; hi&#7875;u <code>partial</code> c&#361;ng ch&#7881; l&#224; v&#7853;y.)</p><p><strong>2. Factory h&#224;m - t&#7841;o nhi&#7873;u h&#224;m c&#249;ng ki&#7875;u, kh&#225;c tham s&#7889;.</strong> V&#237; d&#7909; validator:</p><pre><code><code>def tao_validator(min_val, max_val):
    def validate(x):
        return min_val &lt;= x &lt;= max_val
    return validate
 
tuoi_hop_le    = tao_validator(18, 65)
diem_hop_le    = tao_validator(0, 10)
 
print(tuoi_hop_le(20))    # True
print(diem_hop_le(11))    # False</code></code></pre><p>M&#7895;i l&#7847;n g&#7885;i <code>tao_validator</code> &#8594; m&#7897;t closure ri&#234;ng nh&#7899; <code>min_val</code>/<code>max_val</code> c&#7911;a n&#243;. D&#249;ng nhi&#7873;u m&#224; kh&#244;ng c&#7847;n class.</p><p><strong>3. Gi&#7919; tr&#7841;ng th&#225;i kh&#244;ng c&#7847;n class.</strong> Closure l&#224; c&#225;ch &#273;&#417;n gi&#7843;n &#273;&#7875; c&#243; &#8220;state nh&#7887;&#8221; m&#224; kh&#244;ng ph&#7843;i d&#7921;ng c&#7843; m&#7897;t class:</p><pre><code><code>def tao_dem():
    so_lan = 0                # bi&#7871;n "ri&#234;ng" c&#7911;a closure
    def dem():
        nonlocal so_lan
        so_lan += 1
        return so_lan
    return dem
 
dem_a = tao_dem()
dem_b = tao_dem()            # instance ri&#234;ng, state ri&#234;ng
print(dem_a(), dem_a())      # 1  2
print(dem_b())               # 1  (kh&#244;ng d&#237;nh dem_a)</code></code></pre><p><code>so_lan</code> kh&#244;ng l&#7897; ra ngo&#224;i, kh&#244;ng ai s&#7917;a &#273;&#432;&#7907;c tr&#7921;c ti&#7871;p - gi&#7889;ng attribute private c&#7911;a class, nh&#432;ng g&#7885;n h&#417;n nhi&#7873;u cho tr&#432;&#7901;ng h&#7907;p &#273;&#417;n gi&#7843;n.</p><p><strong>4. N&#7873;n t&#7843;ng c&#7911;a decorator</strong> (b&#224;i 6). C&#225;i <code>wrapper</code> b&#234;n trong decorator ch&#237;nh l&#224; m&#7897;t closure - n&#243; &#8220;nh&#7899;&#8221; <code>func</code> (h&#224;m g&#7889;c) &#273;&#7875; g&#7885;i l&#7841;i. Hi&#7875;u closure l&#224; hi&#7875;u decorator &#273;&#7871;n g&#7889;c.</p><p><strong>5. Callback mang theo ng&#7919; c&#7843;nh.</strong> Trong x&#7917; l&#253; b&#7845;t &#273;&#7891;ng b&#7897;, b&#226;y hay c&#7847;n truy&#7873;n callback &#273;&#227; &#8220;bi&#7871;t&#8221; m&#7897;t s&#7889; th&#244;ng tin s&#7861;n:</p><pre><code><code>def xu_ly_don(ma_don):
    def khi_thanh_cong(ket_qua):
        print(f"&#272;&#417;n {ma_don} thanh to&#225;n xong: {ket_qua}")
    return khi_thanh_cong
 
cb = xu_ly_don("DH001")
cb("500k")    # &#272;&#417;n DH001 thanh to&#225;n xong: 500k</code></code></pre><p>Closure mang theo <code>ma_don</code> m&#224; kh&#244;ng c&#7847;n truy&#7873;n l&#7841;i - h&#7919;u &#237;ch khi &#273;&#259;ng k&#253; callback v&#224;o m&#7897;t system kh&#244;ng bi&#7871;t context c&#7911;a b&#226;y (event bus, async queue...).</p><p><strong>T&#243;m l&#7841;i khi n&#224;o ngh&#297; t&#7899;i closure:</strong> khi b&#226;y c&#7847;n m&#7897;t h&#224;m &#8220;nh&#7899;&#8221; m&#7897;t &#237;t th&#244;ng tin t&#7915; l&#250;c t&#7841;o ra m&#224; kh&#244;ng mu&#7889;n truy&#7873;n &#273;i truy&#7873;n l&#7841;i l&#224;m tham s&#7889; - v&#224; khi c&#225;i &#8220;tr&#7841;ng th&#225;i&#8221; &#273;&#243; &#273;&#417;n gi&#7843;n, kh&#244;ng c&#7847;n d&#7921;ng c&#7843; class.</p><h2>Checklist: b&#226;y n&#7855;m ch&#432;a?</h2><ul><li><p>Closure l&#224; g&#236;? (H&#224;m b&#234;n trong nh&#7899; &#273;&#432;&#7907;c bi&#7871;n c&#7911;a h&#224;m bao ngo&#224;i, k&#7875; c&#7843; sau khi h&#224;m ngo&#224;i ch&#7841;y xong.)</p></li><li><p>Closure b&#7855;t bi&#7871;n hay b&#7855;t gi&#225; tr&#7883;? (B&#7855;t bi&#7871;n - &#273;&#7885;c gi&#225; tr&#7883; l&#250;c G&#7884;I, kh&#244;ng ph&#7843;i l&#250;c t&#7841;o.)</p></li><li><p>V&#236; sao <code>tao_nhan</code> ch&#7841;y &#273;&#250;ng m&#224; v&#242;ng l&#7863;p th&#236; sai? (M&#7895;i l&#7847;n g&#7885;i <code>tao_nhan</code> t&#7841;o <code>he_so</code> ri&#234;ng; v&#242;ng l&#7863;p ch&#7881; c&#243; M&#7896;T bi&#7871;n <code>i</code> d&#249;ng chung.)</p></li><li><p>LEGB l&#224; th&#7913; t&#7921; tra t&#234;n n&#224;o? (Local &#8594; Enclosing &#8594; Global &#8594; Built-in.)</p></li><li><p>Python quy&#7871;t m&#7897;t t&#234;n l&#224; local l&#250;c n&#224;o, d&#7921;a v&#224;o g&#236;? (L&#250;c bi&#234;n d&#7883;ch h&#224;m; n&#7871;u t&#234;n &#273;&#432;&#7907;c g&#225;n &#7903; b&#7845;t k&#7923; &#273;&#226;u trong h&#224;m &#8594; local c&#7843; h&#224;m.)</p></li><li><p>V&#236; sao <code>dem += 1</code> v&#7899;i bi&#7871;n global g&#226;y <code>UnboundLocalError</code>? (C&#243; ghi &#8594; <code>dem</code> th&#224;nh local c&#7843; h&#224;m &#8594; l&#250;c &#273;&#7885;c bi&#7871;n local ch&#432;a &#273;&#432;&#7907;c g&#225;n.)</p></li><li><p><code>global</code> vs <code>nonlocal</code>? (Ghi bi&#7871;n c&#7845;p module vs bi&#7871;n h&#224;m bao ngo&#224;i.)</p></li><li><p>S&#7917;a late binding b&#7857;ng c&#225;ch n&#224;o? (Bind gi&#225; tr&#7883; qua default arg: <code>lambda i=i:</code> ho&#7863;c <code>def f(i=i)</code>.)</p></li><li><p>K&#7875; v&#224;i &#7913;ng d&#7909;ng th&#7921;c t&#7871; c&#7911;a closure? (H&#224;m c&#7845;u h&#236;nh s&#7861;n/partial, factory validator, gi&#7919; state kh&#244;ng c&#7847;n class, n&#7873;n t&#7843;ng decorator, callback mang ng&#7919; c&#7843;nh.)</p></li></ul><div><hr></div><p><em>B&#224;i t&#7899;i: &#8220;Decorator th&#7921;c ch&#7845;t l&#224; g&#236; - </em><code>@</code><em> &#273;&#243; l&#224; ph&#233;p thu&#7853;t g&#236;.&#8221;</em></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://quakebaynghe.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ch&#250; &#218;t Mi&#7873;n T&#226;y's Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Python Shallow vs deep copy: copy bản sao mà bản gốc cũng đổi]]></title><description><![CDATA[N&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level &#183; Python &#183; B&#224;i 4 - Khi .copy() v&#7851;n ch&#432;a &#273;&#7911; &#273;&#7875; d&#7919; li&#7879;u &#273;&#7897;c l&#7853;p]]></description><link>https://quakebaynghe.substack.com/p/python-shallow-vs-deep-copy-copy</link><guid isPermaLink="false">https://quakebaynghe.substack.com/p/python-shallow-vs-deep-copy-copy</guid><dc:creator><![CDATA[Chú Út Miền Tây]]></dc:creator><pubDate>Thu, 18 Jun 2026 15:41:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IeAC!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d9a847-4b1b-4d5d-89d2-289fb66bdda1_688x688.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><span>B&#224;i 4 - series </span><em>&#8220;Python cho d&#226;n backend: n&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level&#8221;</em><span>.</span></p></blockquote><p>B&#224;i 2 n&#243;i <code>b = a</code> kh&#244;ng copy. V&#7853;y g&#7885;i <code>.copy()</code> cho ch&#7855;c l&#224; xong ch&#7899; g&#236;? &#272;&#7889; n&#232;:</p><pre><code><code>goc = {"ten": "A", "tags": ["x", "y"]}
ban_sao = goc.copy()          # t&#432;&#7903;ng &#273;&#227; c&#243; b&#7843;n ri&#234;ng &#273;&#7897;c l&#7853;p
ban_sao["tags"].append("z")
print(goc["tags"])            # ['x', 'y', 'z'] &#8212; b&#7843;n G&#7888;C c&#361;ng &#273;&#7893;i (!)</code></code></pre><p>B&#226;y s&#7917;a <code>ban_sao</code> m&#224; <code>goc</code> d&#237;nh theo. <code>.copy()</code> r&#245; r&#224;ng c&#243; copy m&#224;, sao v&#7851;n l&#7911;ng? V&#236; c&#243; <strong>hai t&#7847;ng</strong> copy, v&#224; b&#226;y m&#7899;i l&#224;m t&#7847;ng ngo&#224;i.</p><blockquote><p><strong>D&#249;ng AI coding agent?</strong> Khi b&#226;y nh&#7901; AI t&#7841;o h&#224;m sao ch&#233;p config hay x&#7917; l&#253; d&#7919; li&#7879;u l&#7891;ng nhau, n&#243; hay t&#7921; tay vi&#7871;t <code>.copy()</code> - g&#7885;n, tr&#244;ng &#273;&#250;ng, ch&#7841;y &#273;&#432;&#7907;c. N&#243; s&#7869; kh&#244;ng h&#7887;i b&#226;y &#8220;c&#7847;n &#273;&#7897;c l&#7853;p t&#7899;i t&#7847;ng n&#224;o&#8221;. K&#7871;t qu&#7843;: data nhi&#7877;m ch&#233;o gi&#7919;a c&#225;c request, l&#7847;n bug c&#7843; bu&#7893;i m&#224; kh&#244;ng th&#7845;y. Hi&#7875;u shallow/deep th&#236; b&#226;y &#273;&#7885;c code AI xong bi&#7871;t ngay c&#7847;n &#273;&#7893;i ch&#7895; n&#224;o.</p></blockquote><h2>&#272;a s&#7889; ngh&#297;: <code>.copy()</code> cho b&#7843;n sao &#273;&#7897;c l&#7853;p ho&#224;n to&#224;n</h2><p>Ch&#7881; &#273;&#250;ng m&#7897;t n&#7917;a. C&#243; hai lo&#7841;i:</p><p><strong>Shallow copy</strong> (<code>.copy()</code>, <code>copy.copy()</code>, <code>dict(d)</code>, <code>list(l)</code>, <code>l[:]</code>):</p><ul><li><p>T&#7841;o <strong>container m&#7899;i</strong> &#7903; t&#7847;ng ngo&#224;i.</p></li><li><p>Nh&#432;ng <strong>c&#225;c ph&#7847;n t&#7917; b&#234;n trong v&#7851;n l&#224; tham chi&#7871;u t&#7899;i C&#217;NG object</strong> (<a href="https://quakebaynghe.substack.com/p/python-object-model-mutable-immutable">nh&#7899; b&#224;i 2!</a>).</p></li></ul><p>N&#234;n trong c&#225;i &#273;&#7889;: <code>ban_sao</code> l&#224; dict m&#7899;i, nh&#432;ng <code>ban_sao["tags"]</code> v&#224; <code>goc["tags"]</code> v&#7851;n tr&#7887; <strong>chung m&#7897;t list</strong>. Append v&#224;o list &#273;&#243; &#8594; c&#7843; hai th&#7845;y.</p><p><strong>Deep copy</strong> (<code>copy.deepcopy()</code>):</p><ul><li><p>Sao <strong>&#273;&#7879; quy</strong> c&#7843; c&#225;c object l&#7891;ng b&#234;n trong &#8594; &#273;&#7897;c l&#7853;p <strong>ho&#224;n to&#224;n</strong>.</p></li></ul><pre><code><code>import copy
goc = {"ten": "A", "tags": ["x", "y"]}
ban_sao = copy.deepcopy(goc)
ban_sao["tags"].append("z")
print(goc["tags"])            # ['x', 'y'] &#8212; g&#7889;c KH&#212;NG &#273;&#7893;i</code></code></pre><h2>C&#417; ch&#7871;: shallow ch&#7881; copy &#8220;l&#7899;p v&#7887;&#8221;</h2><p>H&#236;nh dung d&#7919; li&#7879;u l&#7891;ng nhau nh&#432; h&#7897;p trong h&#7897;p. Shallow copy l&#224;m <strong>m&#7897;t c&#225;i h&#7897;p ngo&#224;i m&#7899;i</strong>, nh&#432;ng c&#225;c h&#7897;p con b&#234;n trong th&#236; <strong>d&#249;ng chung</strong> v&#7899;i b&#7843;n g&#7889;c. Deep copy l&#224;m m&#7899;i <strong>to&#224;n b&#7897;</strong> c&#226;y h&#7897;p.</p><p>V&#7899;i d&#7919; li&#7879;u <strong>ph&#7859;ng</strong> (ch&#7881; ch&#7913;a s&#7889;/chu&#7895;i immutable), shallow l&#224; &#273;&#7911; &#273;&#7897;c l&#7853;p - v&#236; immutable kh&#244;ng s&#7917;a t&#7841;i ch&#7895; &#273;&#432;&#7907;c (b&#224;i 2). V&#7845;n &#273;&#7873; ch&#7881; ph&#225;t sinh khi c&#243; <strong>mutable l&#7891;ng trong mutable</strong> (list trong dict, dict trong list...).</p><h2>H&#7879; qu&#7843; &amp; khi n&#224;o d&#249;ng c&#225;i n&#224;o</h2><p>Bug &#273;i&#7875;n h&#236;nh: copy m&#7897;t config/JSON-like nhi&#7873;u t&#7847;ng, s&#7917;a b&#7843;n sao, r&#7891;i b&#7843;n g&#7889;c (ho&#7863;c b&#7843;n sao kh&#225;c) c&#361;ng &#273;&#7893;i - d&#7919; li&#7879;u nhi&#7877;m ch&#233;o, kh&#243; l&#7847;n.</p><ul><li><p><strong>D&#7919; li&#7879;u ph&#7859;ng / kh&#244;ng l&#7891;ng mutable</strong> &#8594; shallow copy l&#224; &#273;&#7911;, nhanh.</p></li><li><p><strong>D&#7919; li&#7879;u l&#7891;ng nhau c&#7847;n &#273;&#7897;c l&#7853;p th&#7853;t</strong> &#8594; <code>deepcopy</code>. Nh&#432;ng n&#243; <strong>ch&#7853;m v&#224; t&#7889;n RAM</strong> (sao c&#7843; c&#226;y), &#273;&#7915;ng deepcopy b&#7915;a object l&#7899;n trong v&#242;ng n&#243;ng.</p></li><li><p><strong>T&#7889;t nh&#7913;t khi &#273;&#432;&#7907;c:</strong> thi&#7871;t k&#7871; &#273;&#7875; <strong>kh&#244;ng ph&#7843;i copy</strong> - d&#249;ng d&#7919; li&#7879;u immutable (tuple, frozenset), ho&#7863;c t&#7841;o m&#7899;i thay v&#236; s&#7917;a-r&#7891;i-chia-s&#7867;. Tr&#225;nh &#273;&#432;&#7907;c chia s&#7867; th&#236; kh&#7887;i lo copy.</p></li></ul><h2>Checklist: b&#226;y n&#7855;m ch&#432;a?</h2><ul><li><p>Shallow copy copy t&#7899;i t&#7847;ng n&#224;o? (Ch&#7881; container ngo&#224;i; ph&#7847;n t&#7917; b&#234;n trong v&#7851;n d&#249;ng chung.)</p></li><li><p>V&#236; sao s&#7917;a <code>ban_sao["tags"]</code> m&#224; <code>goc</code> &#273;&#7893;i? (Hai dict kh&#225;c nhau nh&#432;ng c&#249;ng tr&#7887; chung m&#7897;t list <code>tags</code>.)</p></li><li><p>Deep copy kh&#225;c g&#236;? (Sao &#273;&#7879; quy c&#7843; object l&#7891;ng &#8594; &#273;&#7897;c l&#7853;p ho&#224;n to&#224;n.)</p></li><li><p>D&#7919; li&#7879;u ph&#7859;ng (ch&#7881; s&#7889;/chu&#7895;i) c&#243; c&#7847;n deepcopy h&#244;ng? (H&#7893;ng - shallow &#273;&#7911;, v&#236; immutable.)</p></li><li><p>Nh&#432;&#7907;c c&#7911;a deepcopy? (Ch&#7853;m, t&#7889;n RAM - &#273;&#7915;ng d&#249;ng b&#7915;a object l&#7899;n.)</p></li><li><p>C&#225;ch n&#233; c&#7843; v&#7845;n &#273;&#7873; copy? (D&#249;ng d&#7919; li&#7879;u immutable / tr&#225;nh chia s&#7867; mutable.)</p></li></ul><div><hr></div><p><em>B&#224;i t&#7899;i: &#8220;Scope LEGB + closure - v&#236; sao </em><code>[lambda: i for i in range(3)]</code><em> c&#7843; ba &#273;&#7873;u tr&#7843; 2.&#8221;</em></p>]]></content:encoded></item><item><title><![CDATA[Python 256 is 256 là True nhưng 257 is 257 lại False - vì sao? ]]></title><description><![CDATA[N&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level &#183; Python &#183; B&#224;i 3 - is vs == v&#224; b&#7851;y integer interning c&#7911;a CPython]]></description><link>https://quakebaynghe.substack.com/p/python-is-vs-equal-interning</link><guid isPermaLink="false">https://quakebaynghe.substack.com/p/python-is-vs-equal-interning</guid><dc:creator><![CDATA[Chú Út Miền Tây]]></dc:creator><pubDate>Thu, 18 Jun 2026 00:30:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IeAC!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d9a847-4b1b-4d5d-89d2-289fb66bdda1_688x688.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><span>B&#224;i 3 - series </span><em>&#8220;Python cho d&#226;n backend: n&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level&#8221;</em><span>.</span></p></blockquote><p>C&#226;u &#273;&#7889; l&#224;m nhi&#7873;u ng&#432;&#7901;i ho&#7843;ng:</p><pre><code><code>a = 256; b = 256
print(a is b)   # True

a = 257; b = 257
print(a is b)   # False (t&#249;y ng&#7919; c&#7843;nh ch&#7841;y!)</code></code></pre><p>C&#249;ng ki&#7875;u so s&#225;nh, c&#249;ng hai s&#7889; b&#7857;ng nhau, m&#224; 256 th&#236; <code>True</code>, 257 th&#236; <code>False</code>? N&#7871;u b&#226;y &#273;ang d&#249;ng <code>is</code> &#273;&#7875; so gi&#225; tr&#7883; th&#236; &#273;&#226;y l&#224; qu&#7843; bom h&#7865;n gi&#7901;.</p><h2><code>is</code><strong> v&#224; </strong><code>==</code><strong> KH&#212;NG gi&#7889;ng nhau</strong></h2><ul><li><p><code>==</code> so <strong>gi&#225; tr&#7883;</strong> - g&#7885;i <code>__eq__</code>, h&#7887;i &#8220;hai c&#225;i c&#243; <em>b&#7857;ng nhau</em> kh&#244;ng&#8221;.</p></li><li><p><code>is</code> so <strong>identity</strong> - h&#7887;i &#8220;c&#243; ph&#7843;i <em>c&#249;ng m&#7897;t object</em> trong b&#7897; nh&#7899; kh&#244;ng&#8221; (c&#249;ng <code>id()</code>- <a href="https://quakebaynghe.substack.com/p/python-object-model-mutable-immutable">&#273;&#7885;c l&#7841;i b&#224;i 2 qua c&#243; n&#243;i v&#7873; ch&#7895; object n&#224;y</a>)</p></li></ul><p><strong>Hai object kh&#225;c nhau m&#224; gi&#225; tr&#7883; b&#7857;ng &#8594; </strong><code>==</code><strong> True nh&#432;ng </strong><code>is</code><strong> False. &#272;&#7915;ng l&#7851;n.</strong></p><h2><strong>Gi&#7843;i c&#225;i &#273;&#7889;: interning</strong></h2><p>CPython, &#273;&#7875; ti&#7871;t ki&#7879;m, <strong>t&#7841;o s&#7861;n v&#224; d&#249;ng chung (cache) c&#225;c s&#7889; nguy&#234;n nh&#7887; t&#7915; -5 t&#7899;i 256</strong>. N&#234;n <code>a = 256</code> v&#224; <code>b = 256</code> c&#249;ng tr&#7887; v&#7873; <strong>m&#7897;t object 256 d&#249;ng chung</strong> &#8594; <code>is</code> ra True. C&#242;n 257 n&#7857;m ngo&#224;i kho&#7843;ng cache &#8594; m&#7895;i ch&#7895; c&#243; th&#7875; l&#224; m&#7897;t object ri&#234;ng &#8594; <code>is</code> ra False.</p><p>T&#432;&#417;ng t&#7921;, m&#7897;t s&#7889; chu&#7895;i ng&#7855;n/gi&#7889;ng t&#234;n bi&#7871;n c&#361;ng &#273;&#432;&#7907;c <strong>intern</strong> (d&#249;ng chung) &#8594; <code>is</code> &#273;&#244;i khi True v&#7899;i string. Nh&#432;ng &#273;&#226;y l&#224; <strong>chi ti&#7871;t hi&#7879;n th&#7921;c c&#7911;a CPython, &#273;&#7893;i theo phi&#234;n b&#7843;n/ng&#7919; c&#7843;nh</strong> - <strong>tuy&#7879;t &#273;&#7889;i &#273;&#7915;ng d&#7921;a v&#224;o</strong>.</p><pre><code><code>a = "hello"; b = "hello"
print(a is b)        # th&#432;&#7901;ng True (interned) &#8212; nh&#432;ng &#273;&#7915;ng tin t&#432;&#7903;ng
print(a == b)        # True &#8212; c&#225;i n&#224;y m&#7899;i &#273;&#225;ng tin
</code></code></pre><h2><strong>Quy t&#7855;c: d&#249;ng c&#225;i n&#224;o khi n&#224;o</strong></h2><ul><li><p><strong>So gi&#225; tr&#7883; &#8594; lu&#244;n d&#249;ng </strong><code>==</code><strong>.</strong> S&#7889;, chu&#7895;i, list, dict... mu&#7889;n bi&#7871;t &#8220;c&#243; b&#7857;ng nhau&#8221; th&#236; <code>==</code>.</p></li><li><p><code>is</code><strong> ch&#7881; d&#249;ng cho singleton:</strong> <code>is None</code>, <code>is True</code>, <code>is False</code>, ho&#7863;c so v&#7899;i m&#7897;t sentinel object b&#226;y c&#7889; t&#236;nh t&#7841;o. M&#7845;y c&#225;i n&#224;y ch&#7881; c&#243; <strong>&#273;&#250;ng m&#7897;t</strong> object trong c&#7843; ch&#432;&#417;ng tr&#236;nh, n&#234;n <code>is</code> m&#7899;i &#273;&#250;ng ngh&#297;a.</p></li></ul><pre><code><code>if x is None:        # &#272;&#218;NG
if x == None:        # tr&#225;nh (d&#249;ng &#273;&#432;&#7907;c m&#224; sai tinh th&#7847;n)
if x is 5:           # SAI &#8212; &#273;&#7915;ng d&#249;ng is cho s&#7889;</code></code></pre><h2><strong>H&#7879; qu&#7843;: bug &#8220;ch&#7841;y l&#250;c test, sai l&#250;c prod&#8221;</strong></h2><p>&#272;&#226;y l&#224; c&#225;i &#273;&#7897;c nh&#7913;t: <code>if ma_loi is 200</code> ch&#7841;y &#273;&#250;ng khi test (s&#7889; nh&#7887;, &#273;&#432;&#7907;c cache) r&#7891;i <strong>sai &#226;m th&#7847;m</strong> khi g&#7863;p s&#7889; l&#7899;n ngo&#224;i kho&#7843;ng cache. Bug ph&#7909; thu&#7897;c chi ti&#7871;t hi&#7879;n th&#7921;c th&#236; c&#7921;c kh&#243; l&#7847;n. <a href="https://quakebaynghe.substack.com/p/python-mutable-default-argument">Nh&#7899; b&#224;i 1:</a> &#7903; &#273;&#243; qua vi&#7871;t <code>gio_hang is None</code> - &#273;&#250;ng v&#236; None l&#224; singleton; n&#7871;u l&#7905; tay vi&#7871;t <code>is</code> cho s&#7889;/chu&#7895;i th&#236; d&#237;nh b&#7851;y n&#224;y.</p><h2><strong>Checklist: b&#226;y n&#7855;m ch&#432;a?</strong></h2><ul><li><p><code>==</code> so c&#225;i g&#236;, <code>is</code> so c&#225;i g&#236;? (<code>==</code> so gi&#225; tr&#7883;; <code>is</code> so identity - c&#249;ng m&#7897;t object kh&#244;ng.)</p></li><li><p>V&#236; sao <code>256 is 256</code> True m&#224; <code>257</code> c&#243; th&#7875; False? (CPython cache s&#7861;n int nh&#7887; -5..256; ngo&#224;i &#273;&#243; l&#224; object ri&#234;ng.)</p></li><li><p>C&#243; n&#234;n d&#7921;a v&#224;o string interning h&#244;ng? (H&#244;ng nha - chi ti&#7871;t hi&#7879;n th&#7921;c, &#273;&#7893;i theo phi&#234;n b&#7843;n.)</p></li><li><p>So gi&#225; tr&#7883; th&#236; lu&#244;n d&#249;ng c&#225;i n&#224;o? (<code>==</code>.)</p></li><li><p><code>is</code> ch&#7881; n&#234;n d&#249;ng cho g&#236;? (Singleton: <code>None</code>, <code>True</code>, <code>False</code>, sentinel.)</p></li><li><p>V&#236; sao <code>if x is 5</code> nguy hi&#7875;m? (&#272;&#250;ng v&#7899;i s&#7889; nh&#7887; &#273;&#432;&#7907;c cache, sai v&#7899;i s&#7889; l&#7899;n &#8594; bug &#226;m th&#7847;m.)</p></li></ul><div><hr></div><p><em>B&#224;i t&#7899;i: &#8220;Shallow vs deep copy - copy c&#225;i dict m&#224; s&#7917;a b&#7843;n sao th&#236; b&#7843;n g&#7889;c c&#361;ng &#273;&#7893;i.&#8221;</em></p>]]></content:encoded></item><item><title><![CDATA[Vì sao gán b = a lại làm đổi luôn cả a? Gốc rễ mô hình Object trong Python]]></title><description><![CDATA[N&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level &#183; Python &#183; B&#224;i 2 - Bi&#7871;n l&#224; c&#225;i nh&#227;n, B&#7843;n ch&#7845;t Mutable vs Immutable, v&#224; Pass-by-Object-Reference.]]></description><link>https://quakebaynghe.substack.com/p/python-object-model-mutable-immutable</link><guid isPermaLink="false">https://quakebaynghe.substack.com/p/python-object-model-mutable-immutable</guid><dc:creator><![CDATA[Chú Út Miền Tây]]></dc:creator><pubDate>Wed, 17 Jun 2026 13:01:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!i3fT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><span>B&#224;i 2 - series </span><em>&#8220;Python cho d&#226;n backend: n&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level&#8221;</em><span>. M&#7903; m&#224;n b&#7857;ng m&#7897;t c&#226;u &#273;&#7889; nh&#432; l&#7847;n tr&#432;&#7899;c nghen:</span></p></blockquote><p>C&#226;u &#273;&#7889; ti&#7871;p n&#7889;i b&#224;i 1:</p><pre><code><code>a = [1, 2, 3]
b = a
b.append(4)
print(a)   # [1, 2, 3, 4] - &#7911;a, tao c&#243; &#273;&#7909;ng a &#273;&#226;u?</code></code></pre><p>B&#226;y g&#225;n <code>b = a</code>, s&#7917;a <code>b</code>, m&#224; <code>a</code> c&#361;ng d&#237;nh. T&#432;&#7903;ng <code>b = a</code> l&#224; sao ch&#233;p m&#7897;t b&#7843;n ri&#234;ng cho <code>b</code> &#8594; tr&#7853;t. Hi&#7875;u c&#225;i n&#224;y l&#224; hi&#7875;u g&#7889;c r&#7877; c&#7911;a n&#7917;a s&#7889; bug &#8220;t&#7921; nhi&#234;n d&#7919; li&#7879;u b&#7883; &#273;&#7893;i&#8221; trong Python.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i3fT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i3fT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png 424w, https://substackcdn.com/image/fetch/$s_!i3fT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png 848w, https://substackcdn.com/image/fetch/$s_!i3fT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png 1272w, https://substackcdn.com/image/fetch/$s_!i3fT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i3fT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png" width="1456" height="1227" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/da77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1227,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:262479,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://quakebaynghe.substack.com/i/202372255?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!i3fT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png 424w, https://substackcdn.com/image/fetch/$s_!i3fT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png 848w, https://substackcdn.com/image/fetch/$s_!i3fT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png 1272w, https://substackcdn.com/image/fetch/$s_!i3fT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda77b189-7b9a-46bb-ad4f-01c76dbfccbf_2920x2460.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>&#272;a s&#7889; ngh&#297;: bi&#7871;n l&#224; c&#225;i h&#7897;p ch&#7913;a gi&#225; tr&#7883;, g&#225;n l&#224; copy</h2><p>Tr&#7853;t l&#7845;t nghe b&#226;y. Trong Python:</p><blockquote><p><strong>Bi&#7871;n l&#224; c&#225;i NH&#195;N (t&#234;n) g&#7855;n v&#224;o m&#7897;t object, kh&#244;ng ph&#7843;i c&#225;i h&#7897;p ch&#7913;a gi&#225; tr&#7883;.</strong> <code>b = a</code> ch&#7881; d&#225;n th&#234;m nh&#227;n <code>b</code> v&#224;o <strong>c&#249;ng object</strong> m&#224; <code>a</code> &#273;ang tr&#7887; t&#7899;i.</p></blockquote><p>N&#234;n <code>a</code> v&#224; <code>b</code> l&#224; hai c&#225;i nh&#227;n tr&#234;n <strong>m&#7897;t</strong> c&#225;i list. S&#7917;a c&#225;i list qua nh&#227;n <code>b</code> th&#236; nh&#227;n <code>a</code> &#8220;th&#7845;y&#8221; li&#7873;n - v&#236; c&#243; m&#7897;t c&#225;i list th&#244;i. Ki&#7875;m b&#7857;ng <code>id(a) == id(b)</code> &#8594; <code>True</code> (c&#249;ng identity).</p><h2>Mutable vs immutable - chia hai th&#7871; gi&#7899;i</h2><p>H&#236;nh dung cho d&#7877;:</p><ul><li><p><strong>Mutable</strong> (<code>list</code>, <code>dict</code>, <code>set</code>) gi&#7889;ng c&#225;i <strong>r&#7893;</strong> - b&#7887; th&#234;m tr&#225;i c&#226;y v&#244; th&#236; v&#7851;n l&#224; c&#225;i r&#7893; c&#361;, ch&#7881; l&#224; trong r&#7893; c&#243; th&#234;m &#273;&#7891;. <strong>S&#7917;a-t&#7841;i-ch&#7895; &#273;&#432;&#7907;c</strong>, n&#234;n m&#7885;i nh&#227;n tr&#7887; t&#7899;i n&#243; &#273;&#7873;u th&#7845;y thay &#273;&#7893;i. &#272;&#226;y l&#224; ch&#7895; g&#226;y b&#7845;t ng&#7901;.</p></li><li><p><strong>Immutable</strong> (<code>int</code>, <code>str</code>, <code>tuple</code>, <code>bool</code>, <code>None</code>) gi&#7889;ng s&#7889; <strong>kh&#7855;c tr&#234;n &#273;&#225;</strong> - mu&#7889;n s&#7889; kh&#225;c ph&#7843;i l&#7845;y <em>c&#7909;c &#273;&#225; kh&#225;c</em>. <strong>Kh&#244;ng s&#7917;a-t&#7841;i-ch&#7895; &#273;&#432;&#7907;c</strong>: &#8220;s&#7917;a&#8221; th&#7921;c ra l&#224; t&#7841;o object m&#7899;i r&#7891;i d&#7901;i nh&#227;n sang &#273;&#243; &#8594; nh&#227;n kia kh&#244;ng h&#7873; h&#7845;n:</p></li></ul><pre><code><code>a = 5
b = a
b = b + 1     # b tr&#7887; object m&#7899;i (6); a v&#7851;n 5
print(a, b)   # 5 6</code></code></pre><h2><code>a += b</code> kh&#225;c <code>a = a + b</code> (v&#7899;i list)</h2><p>C&#225;i n&#224;y hay l&#224;m ng&#432;&#7901;i ta v&#7845;p:</p><pre><code><code>a = [1, 2]
b = a
a += [3]       # S&#7916;A T&#7840;I CH&#7894; list c&#361; (nh&#432; extend) &#8594; b c&#361;ng th&#7845;y
print(b)       # [1, 2, 3]

a = [1, 2]
b = a
a = a + [3]    # T&#7840;O list m&#7899;i, d&#7901;i nh&#227;n a sang &#273;&#243; &#8594; b gi&#7919; list c&#361;
print(b)       # [1, 2]</code></code></pre><p><code>+=</code> tr&#234;n mutable l&#224; s&#7917;a t&#7841;i ch&#7895;; <code>a = a + b</code> l&#224; t&#7841;o m&#7899;i.</p><h2>Truy&#7873;n v&#224;o h&#224;m: &#8220;pass by object reference&#8221;</h2><p>Python kh&#244;ng pass-by-value nh&#432; Go, c&#361;ng kh&#244;ng pass-by-reference ki&#7875;u C++ - n&#243; truy&#7873;n <strong>tham chi&#7871;u t&#7899;i object</strong> (g&#7885;i l&#224; pass-by-assignment). H&#7879; qu&#7843; th&#7921;c t&#7871;:</p><pre><code><code>def sua(lst):
    lst.append(99)     # S&#7916;A object &#8594; b&#234;n ngo&#224;i TH&#7844;Y
def gan_lai(lst):
    lst = [0]          # G&#193;N L&#7840;I t&#234;n c&#7909;c b&#7897; &#8594; b&#234;n ngo&#224;i KH&#212;NG th&#7845;y

x = [1, 2]
sua(x);      print(x)  # [1, 2, 99]
gan_lai(x);  print(x)  # [1, 2, 99] (kh&#244;ng &#273;&#7893;i - ch&#7881; d&#7901;i nh&#227;n c&#7909;c b&#7897;)</code></code></pre><p>S&#7917;a n&#7897;i dung object th&#236; b&#234;n ngo&#224;i th&#7845;y; g&#225;n l&#7841;i c&#225;i t&#234;n (tham s&#7889;) th&#236; ch&#7881; &#273;&#7893;i nh&#227;n c&#7909;c b&#7897; trong h&#224;m, b&#234;n ngo&#224;i kh&#244;ng h&#7873; h&#7845;n.</p><h2>H&#7879; qu&#7843; &amp; li&#234;n h&#7879; Go</h2><p>&#272;&#226;y l&#224; ngu&#7891;n c&#7911;a lo&#7841;i bug &#8220;d&#7919; li&#7879;u b&#7883; &#273;&#7893;i m&#224; kh&#244;ng bi&#7871;t ai &#273;&#7893;i&#8221;. Mu&#7889;n <code>b</code> &#273;&#7897;c l&#7853;p v&#7899;i <code>a</code> th&#236; ph&#7843;i <strong>copy</strong> th&#7853;t (b&#224;i sau) - m&#224; copy c&#361;ng c&#243; b&#7851;y shallow/deep.</p><p>Li&#234;n h&#7879; Go <a href="https://quakebaynghe.substack.com/p/golang-pass-by-value">(series Golang, b&#224;i 1): Go </a><strong><a href="https://quakebaynghe.substack.com/p/golang-pass-by-value">copy value</a></strong><a href="https://quakebaynghe.substack.com/p/golang-pass-by-value"> khi truy&#7873;n tham s&#7889;</a>; Python <strong>truy&#7873;n tham chi&#7871;u t&#7899;i object</strong>. Hai ng&#244;n ng&#7919; ng&#432;&#7907;c nhau, m&#224; c&#249;ng m&#7897;t b&#224;i h&#7885;c s&#7889;ng c&#242;n: <strong>lu&#244;n bi&#7871;t c&#225;i g&#236; &#273;ang &#273;&#432;&#7907;c chia s&#7867;, c&#225;i g&#236; l&#224; b&#7843;n ri&#234;ng.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!x4Cw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!x4Cw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png 424w, https://substackcdn.com/image/fetch/$s_!x4Cw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png 848w, https://substackcdn.com/image/fetch/$s_!x4Cw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png 1272w, https://substackcdn.com/image/fetch/$s_!x4Cw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!x4Cw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png" width="1456" height="610" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:610,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:180140,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://quakebaynghe.substack.com/i/202372255?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!x4Cw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png 424w, https://substackcdn.com/image/fetch/$s_!x4Cw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png 848w, https://substackcdn.com/image/fetch/$s_!x4Cw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png 1272w, https://substackcdn.com/image/fetch/$s_!x4Cw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03717a77-0c10-4899-8bdf-05874a15cd80_2960x1240.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Checklist: b&#226;y n&#7855;m ch&#432;a?</h2><ul><li><p>Bi&#7871;n trong Python l&#224; h&#7897;p gi&#225; tr&#7883; hay nh&#227;n tr&#7887; object? (Nh&#227;n tr&#7887; object.)</p></li><li><p><code>b = a</code> c&#243; copy h&#244;ng? (H&#244;ng &#224; nha- ch&#7881; th&#234;m nh&#227;n v&#224;o c&#249;ng object.)</p></li><li><p>Mutable vs immutable kh&#225;c g&#236; khi g&#225;n/s&#7917;a? (Mutable = r&#7893;, s&#7917;a-t&#7841;i-ch&#7895; &#8594; m&#7885;i nh&#227;n &#273;&#7873;u th&#7845;y; immutable = s&#7889; kh&#7855;c &#273;&#225;, &#8220;s&#7917;a&#8221; l&#224; t&#7841;o m&#7899;i &#8594; d&#7901;i nh&#227;n.)</p></li><li><p><code>a += [3]</code> kh&#225;c <code>a = a + [3]</code> ch&#7895; n&#224;o? (<code>+=</code> s&#7917;a t&#7841;i ch&#7895; list c&#361;; <code>a = a + ...</code> t&#7841;o list m&#7899;i.)</p></li><li><p>S&#7917;a object trong h&#224;m, b&#234;n ngo&#224;i c&#243; th&#7845;y h&#244;ng? G&#225;n l&#7841;i t&#234;n th&#236; sao? (S&#7917;a object: th&#7845;y; g&#225;n l&#7841;i t&#234;n: kh&#244;ng.)</p></li><li><p>Ki&#7875;m hai nh&#227;n c&#249;ng object b&#7857;ng g&#236;? (<code>id()</code> / <code>is</code>.)</p></li></ul><div><hr></div><p><em>B&#224;i t&#7899;i: &#8220;</em><code>is</code><em> vs </em><code>==</code><em> - v&#224; v&#236; sao </em><code>256 is 256</code><em> cho True m&#224; </em><code>257 is 257</code><em> c&#243; th&#7875; False.&#8221;</em></p>]]></content:encoded></item><item><title><![CDATA[Vì sao list mặc định trong Python nhớ lần gọi trước?]]></title><description><![CDATA[N&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level &#183; Python &#183; B&#224;i 1 - B&#7851;y mutable default argument & c&#225;ch di&#7879;t bug r&#242; r&#7881; state]]></description><link>https://quakebaynghe.substack.com/p/python-mutable-default-argument</link><guid isPermaLink="false">https://quakebaynghe.substack.com/p/python-mutable-default-argument</guid><dc:creator><![CDATA[Chú Út Miền Tây]]></dc:creator><pubDate>Wed, 17 Jun 2026 01:34:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IeAC!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d9a847-4b1b-4d5d-89d2-289fb66bdda1_688x688.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p>B&#224;i 1 - series <em>&#8220;Python cho d&#226;n backend: n&#7873;n t&#7843;ng &#273;&#7875; l&#234;n level&#8221;</em>. M&#7903; m&#224;n b&#7857;ng c&#226;u &#273;&#7889; kinh &#273;i&#7875;n nh&#7913;t Python, m&#224; qua c&#225; l&#224; b&#226;y t&#7915;ng d&#237;nh:</p></blockquote><pre><code><code>def them_mon(mon, gio_hang=[]):
    gio_hang.append(mon)
    return gio_hang

print(them_mon("t&#225;o"))   # ['t&#225;o']
print(them_mon("cam"))   # t&#432;&#7903;ng ['cam']... th&#7921;c ra ['t&#225;o', 'cam'] (!)</code></code></pre><p>L&#7847;n g&#7885;i th&#7913; hai b&#226;y kh&#244;ng truy&#7873;n <code>gio_hang</code>, v&#7853;y m&#224; n&#243; &#8220;nh&#7899;&#8221; lu&#244;n qu&#7843; t&#225;o c&#7911;a l&#7847;n tr&#432;&#7899;c. C&#225;i default <code>[]</code> &#273;&#225;ng l&#7869; ph&#7843;i l&#224; list r&#7895;ng m&#7899;i m&#7895;i l&#7847;n ch&#7899;? Tr&#7853;t. V&#224; hi&#7875;u sai ch&#7895; n&#224;y l&#224; r&#7843;i bug kh&#7855;p backend.</p><h2>&#272;a s&#7889; ngh&#297;: m&#7895;i l&#7847;n g&#7885;i h&#224;m, <code>[]</code> t&#7841;o list r&#7895;ng m&#7899;i</h2><p>Sai t&#7915; g&#7889;c r&#7891;i b&#226;y. S&#7921; th&#7853;t l&#224; &#273;&#226;y nha:</p><blockquote><p>Default argument ch&#7881; &#273;&#432;&#7907;c t&#237;nh <strong>M&#7896;T L&#7846;N</strong> - l&#250;c Python &#273;&#7883;nh ngh&#297;a h&#224;m (&#273;&#7885;c d&#242;ng <code>def</code>), kh&#244;ng ph&#7843;i m&#7895;i l&#7847;n g&#7885;i.</p></blockquote><p>C&#225;i list <code>[]</code> &#273;&#432;&#7907;c t&#7841;o m&#7897;t l&#7847;n duy nh&#7913;t l&#250;c &#273;&#7883;nh ngh&#297;a, r&#7891;i d&#249;ng chung cho m&#7885;i l&#7847;n g&#7885;i kh&#244;ng truy&#7873;n tham s&#7889;. M&#7895;i l&#7847;n <code>append</code>, b&#226;y &#273;ang nh&#233;t v&#224;o c&#249;ng m&#7897;t c&#225;i list chung &#273;&#243; - n&#234;n n&#243; t&#237;ch l&#361;y m&#227;i &#273;&#243;.</p><h2>C&#417; ch&#7871;: default n&#7857;m &#7903; &#273;&#226;u?</h2><p>Khi Python &#273;&#7885;c t&#7899;i <code>def them_mon(...)</code>, n&#243; t&#237;nh ngay c&#225;c gi&#225; tr&#7883; m&#7863;c &#273;&#7883;nh r&#7891;i g&#7855;n th&#7859;ng v&#224;o object h&#224;m. Soi th&#7917; nghen:</p><pre><code><code>print(them_mon.__defaults__)   # ([...],) - th&#7845;y &#273;&#250;ng c&#225;i list chung n&#7857;m tr&#7887;ng</code></code></pre><p>M&#7885;i l&#7847;n g&#7885;i kh&#244;ng truy&#7873;n <code>gio_hang</code> &#273;&#7873;u x&#224;i l&#7841;i &#273;&#250;ng c&#225;i list trong <code>__defaults__</code> &#273;&#243;. N&#243; kh&#244;ng sinh ra c&#225;i m&#7899;i - n&#234;n <code>append</code> c&#7913; ch&#7891;ng l&#234;n ho&#224;i.</p><h2>V&#236; sao ch&#7881; list/dict/set d&#237;nh, c&#242;n int/str/None th&#236; kh&#244;ng?</h2><p>V&#236; <code>list</code>, <code>dict</code>, <code>set</code> l&#224; <strong>mutable</strong> - s&#7917;a-t&#7841;i-ch&#7895; &#273;&#432;&#7907;c, n&#234;n tr&#7841;ng th&#225;i t&#237;ch l&#7841;i qua t&#7915;ng l&#7847;n g&#7885;i. C&#242;n <code>int</code>, <code>str</code>, <code>None</code>... l&#224; <strong>immutable</strong>, kh&#244;ng s&#7917;a-t&#7841;i-ch&#7895; &#273;&#432;&#7907;c, n&#234;n d&#249; c&#361;ng &#8220;x&#224;i chung&#8221; th&#236; ch&#7859;ng c&#243; g&#236; &#273;&#7875; t&#237;ch - kh&#244;ng ai th&#7845;y v&#7845;n &#273;&#7873;.</p><blockquote><p>Mutable v&#7899;i immutable l&#224; g&#236;, v&#236; sao immutable &#8220;kh&#244;ng s&#7917;a &#273;&#432;&#7907;c&#8221;, v&#224; chuy&#7879;n &#8220;g&#225;n kh&#244;ng copy&#8221; - qua m&#7893; k&#7929; &#7903; <strong>b&#224;i 2</strong>. &#7902; &#273;&#226;y b&#226;y ch&#7881; c&#7847;n n&#7857;m l&#242;ng m&#7897;t c&#226;u: <strong>default m&#224; l&#224; mutable th&#236; nguy.</strong></p></blockquote><h2>H&#7879; qu&#7843;: bug &#226;m th&#7847;m, c&#7921;c nguy trong backend</h2><p>Kh&#244;ng ph&#7843;i chuy&#7879;n h&#7885;c thu&#7853;t. Trong web backend, m&#7897;t h&#224;m c&#243; default mutable m&#224; d&#249;ng qua nhi&#7873;u request &#8594; state r&#242; r&#7881; gi&#7919;a c&#225;c request, gi&#7919;a c&#225;c user. Ng&#432;&#7901;i A &#273;&#7863;t m&#243;n, ng&#432;&#7901;i B m&#7903; gi&#7887; th&#7845;y lu&#244;n m&#243;n c&#7911;a ng&#432;&#7901;i A. Bug ki&#7875;u n&#224;y kh&#243; l&#7847;n v&#236; code &#8220;nh&#236;n &#273;&#250;ng&#8221;, m&#224; test m&#7897;t ph&#225;t th&#236; ch&#432;a l&#7897;.</p><h2>C&#225;ch s&#7917;a: d&#249;ng <code>None</code> l&#224;m sentinel</h2><p>Quy t&#7855;c v&#224;ng: &#273;&#7915;ng bao gi&#7901; &#273;&#7875; gi&#225; tr&#7883; m&#7863;c &#273;&#7883;nh l&#224; mutable. D&#249;ng <code>None</code>, r&#7891;i t&#7841;o list m&#7899;i b&#234;n trong h&#224;m - ch&#7895; n&#224;y m&#7899;i ch&#7841;y m&#7895;i l&#7847;n g&#7885;i:</p><pre><code><code>def them_mon(mon, gio_hang=None):
    if gio_hang is None:
        gio_hang = []          # t&#7841;o M&#7898;I m&#7895;i l&#7847;n g&#7885;i
    gio_hang.append(mon)
    return gio_hang

print(them_mon("t&#225;o"))   # ['t&#225;o']
print(them_mon("cam"))   # ['cam'] - &#273;&#250;ng r&#7891;i nghen</code></code></pre><p><code>gio_hang={}</code> hay <code>set()</code> l&#224;m default c&#361;ng d&#237;nh y chang - c&#7913; s&#7917;a h&#7871;t th&#224;nh <code>None</code> r&#7891;i t&#7841;o m&#7899;i b&#234;n trong. (&#272;&#7875; &#253; <code>is None</code> ch&#7913; kh&#244;ng <code>== None</code> - l&#253; do &#273;&#7875; d&#224;nh b&#224;i sau.)</p><h2>Checklist: b&#226;y n&#7855;m ch&#432;a?</h2><ul><li><p>Default argument &#273;&#432;&#7907;c t&#237;nh l&#250;c n&#224;o? (M&#7897;t l&#7847;n, l&#250;c &#273;&#7883;nh ngh&#297;a h&#224;m - kh&#244;ng ph&#7843;i m&#7895;i l&#7847;n g&#7885;i.)</p></li><li><p>V&#236; sao <code>gio_hang=[]</code> &#8220;nh&#7899;&#8221; l&#7847;n tr&#432;&#7899;c? (C&#249;ng m&#7897;t list &#273;&#432;&#7907;c d&#249;ng chung cho m&#7885;i l&#7847;n g&#7885;i.)</p></li><li><p>Xem default &#273;ang l&#432;u &#7903; &#273;&#226;u? (<code>ten_ham.__defaults__</code>.)</p></li><li><p>V&#236; sao int/str/None l&#224;m default th&#236; kh&#244;ng d&#237;nh? (Immutable - kh&#244;ng s&#7917;a-t&#7841;i-ch&#7895; &#273;&#432;&#7907;c.)</p></li><li><p>H&#7879; qu&#7843; nguy hi&#7875;m trong web backend? (State r&#242; r&#7881; gi&#7919;a c&#225;c request/user.)</p></li><li><p>C&#225;ch s&#7917;a &#273;&#250;ng? (Default = <code>None</code>, t&#7841;o m&#7899;i b&#234;n trong h&#224;m.)</p></li></ul><div><hr></div><p><em>B&#224;i t&#7899;i (b&#224;i 2): &#8220;G&#225;n kh&#244;ng copy - v&#236; sao </em><code>b = a</code><em> r&#7891;i s&#7917;a </em><code>b</code><em> m&#224; </em><code>a</code><em> c&#361;ng &#273;&#7893;i.&#8221; &#7902; &#273;&#243; qua m&#7893; k&#7929; m&#244; h&#236;nh nh&#227;n &#8594; object v&#7899;i mutable vs immutable.</em></p>]]></content:encoded></item></channel></rss>