🎯 What this lesson gives you · สิ่งที่คุณจะได้จากบทเรียนนี้ · 本课能给你什么
🇬🇧 English
Every program holds data. A student. A booking. A price. Python gives you three tools for this job.
Data classes come free with Python. attrs and Pydantic are libraries you install.
People argue about which is best. The argument is not useful. Each one does a different job.
By the end you will know that job. You will also have a rule you can use at work.
Every result on this page was run on real Python 3.12. Nothing here is guessed.
🇹🇭 ไทย
ทุกโปรแกรมต้องเก็บข้อมูล นักเรียนหนึ่งคน การจองหนึ่งรายการ ราคาหนึ่งราคา Python มีเครื่องมือสามตัวสำหรับงานนี้
Data classes มากับ Python ฟรี ส่วน attrs และ Pydantic เป็นไลบรารีที่ต้องติดตั้งเอง
คนชอบเถียงกันว่าตัวไหนดีที่สุด การเถียงนั้นไม่มีประโยชน์ แต่ละตัวทำงานคนละอย่าง
อ่านจบแล้วคุณจะรู้ว่างานนั้นคืออะไร และจะได้กฎง่าย ๆ ไปใช้ทำงานจริง
ผลลัพธ์ทุกอันในหน้านี้รันจริงบน Python 3.12 ไม่มีอันไหนเดาเอา
🇨🇳 中文
每个程序都要装数据。一个学生、一笔预订、一个价格。Python 为这件事准备了三样工具。
数据类(data class)是 Python 自带的,免费。attrs 和 Pydantic 是要自己安装的库。
大家爱争哪个最好。这种争论没什么用。它们各做各的事。
读完你就知道那件事是什么,还能拿到一条可以直接在工作中用的规则。
本页每一个结果都在真实的 Python 3.12 上跑过,没有一处是猜的。
1️⃣ The words you need first · คำศัพท์ที่ต้องรู้ก่อน · 先要懂的词
🇬🇧 English
Two words in this list do all the work: validate and coerce.
To validate is to check. To coerce is to change. They are not the same thing.
Click any card to hear it said aloud.
🇹🇭 ไทย
ในรายการนี้มีสองคำที่สำคัญที่สุด คือ validate กับ coerce
validate คือตรวจสอบ ส่วน coerce คือแปลงค่า สองอย่างนี้ไม่เหมือนกัน
คลิกที่การ์ดเพื่อฟังเสียงอ่าน
🇨🇳 中文
这一组词里,最重要的是两个:validate(校验)和 coerce(转换)。
validate 是检查,coerce 是改。两者不是一回事。
点任意卡片可以听发音。
Student is a class. Ploy is one object.做对象的图纸。Student 是类,Ploy 是一个对象。แบบแปลนสำหรับสร้างอ็อบเจกต์ Student คือคลาส ส่วน Ploy คืออ็อบเจกต์หนึ่งตัวage is a field.类里的一项数据。age 就是一个字段。ข้อมูลหนึ่งชิ้นในคลาส เช่น age คือฟิลด์หนึ่งage: int is a type hint.写明该放什么类型的值。age: int 就是类型注解。หมายเหตุบอกว่าควรใส่ค่าชนิดไหน เช่น age: int"28" becomes number 28.把值改成正确的类型。文本 "28" 变成数字 28。แปลงค่าให้เป็นชนิดที่ถูก เช่น ข้อความ "28" กลายเป็นตัวเลข 28pip install it, then import it.别人写好的代码。先 pip install,再 import。โค้ดที่คนอื่นเขียนไว้ ต้อง pip install ก่อน แล้วค่อย import2️⃣ The problem all three solve · ปัญหาที่ทั้งสามตัวแก้ให้ · 三者共同解决的问题
🇬🇧 English
You want to hold three things about a student. A name, an age, a city.
Old Python made you write every name three times. Once in the line, once on the left, once on the right.
Then you had to add more. Printing was ugly. Two equal students did not look equal.
That is a lot of typing. The box holds only three values.
🇹🇭 ไทย
คุณอยากเก็บข้อมูลนักเรียนสามอย่าง ชื่อ อายุ และเมือง
Python แบบเก่าบังคับให้พิมพ์ชื่อฟิลด์สามรอบ ในบรรทัดแรก ฝั่งซ้าย และฝั่งขวา
แล้วยังต้องเขียนเพิ่มอีก การพิมพ์ออกมาดูไม่สวย นักเรียนสองคนที่ข้อมูลเหมือนกันกลับไม่เท่ากัน
พิมพ์เยอะมาก สำหรับกล่องที่เก็บแค่สามค่า
🇨🇳 中文
你想存学生的三项信息:姓名、年龄、城市。
老式 Python 逼你把每个名字写三遍:参数一遍、左边一遍、右边一遍。
然后还得再加东西。打印出来很难看,两个一样的学生还判定为不相等。
为了一个只装三个值的盒子,打字量太大了。
name.
วิธีแบบเก่า ลองนับว่าต้องพิมพ์คำว่า name กี่ครั้ง
老写法。数一数 name 这个词要打几遍。
__repr__ and a working ==. If that is all you want, stop here. Use a data class. It is already in the box.
เรื่องนี้ไม่ใช่ประเด็นที่ต้องเถียง ทั้งสามตัวช่วยลดการพิมพ์เท่ากัน ให้ __repr__ ที่ดีและ == ที่ใช้ได้เหมือนกัน ถ้าคุณต้องการแค่นี้ หยุดตรงนี้แล้วใช้ data class ได้เลย เพราะมันมีอยู่แล้วในกล่อง
这一段不是争论的焦点。三者省下的打字量一样多,都给你好看的 __repr__ 和能用的 ==。如果你只要这些,就到此为止,用数据类,因为它本来就在盒子里。
3️⃣ The same student, three ways · นักเรียนคนเดียวกัน เขียนสามแบบ · 同一个学生,三种写法
🇬🇧 English
Here is one student written three times. Read them side by side.
They are almost the same. The shape of the class does not change much.
Look at the age line in each one. That is where they part.
🇹🇭 ไทย
นี่คือนักเรียนคนเดียวกันเขียนสามแบบ ลองอ่านเทียบกัน
แทบจะเหมือนกันเลย รูปร่างของคลาสแทบไม่ต่างกัน
ให้ดูบรรทัด age ของแต่ละแบบ นั่นคือจุดที่มันแยกทางกัน
🇨🇳 中文
这是同一个学生的三种写法,并排读一读。
它们几乎一模一样,类的形状差别不大。
看每一段里的 age 那行。它们就是在那里分道扬镳的。
4️⃣ The one real difference — try it · ข้อต่างที่แท้จริงข้อเดียว ลองเล่นดู · 唯一真正的区别 —— 动手试试
🇬🇧 English
Here is the whole lesson in one screen. We send each class a bad age.
Pick an input below. Watch what the three classes do with it.
The second button is the important one. A web form always sends text, never numbers.
🇹🇭 ไทย
บทเรียนทั้งบทอยู่ในหน้าจอเดียวนี้ เราจะส่งค่า age ที่ไม่ดีเข้าไปในทั้งสามคลาส
เลือกค่าที่จะส่งด้านล่าง แล้วดูว่าแต่ละคลาสทำอะไรกับมัน
ปุ่มที่สองสำคัญที่สุด เพราะฟอร์มบนเว็บส่งมาเป็นข้อความเสมอ ไม่เคยส่งเป็นตัวเลข
🇨🇳 中文
整堂课就在这一屏里。我们往三个类里各塞一个有问题的 age。
在下面选一个输入,看看三个类分别怎么处理。
第二个按钮最关键。网页表单送来的永远是文本,绝不是数字。
age:
เลือกค่าที่ส่งเข้ามาเป็น age:
选一个作为 age 传进来的值:
"28" into 28 is usually a gift. Sometimes it is not. If you need Pydantic to refuse text, turn repair off with model_config = {"strict": True}. Then "28" fails too.
การที่ Pydantic ซ่อม "28" ให้เป็น 28 มักเป็นเรื่องดี แต่บางครั้งก็ไม่ดี ถ้าคุณอยากให้มันปฏิเสธข้อความไปเลย ให้ปิดการซ่อมด้วย model_config = {"strict": True} แล้ว "28" จะไม่ผ่านเหมือนกัน
Pydantic 把 "28" 修成 28 通常是好事,但有时不是。如果你要它拒绝文本,就用 model_config = {"strict": True} 关掉自动修复,这样 "28" 也会报错。
5️⃣ Data classes — the one already in the box · Data classes — ตัวที่มีอยู่แล้วในกล่อง · 数据类 —— 盒子里本来就有的那个
🇬🇧 English
Data classes came with Python 3.7, in 2018. They are part of Python itself.
That is their great strength. No install. No new dependency. Nothing to keep updated.
They check nothing at all. For data your own code made, that is fine. You already trust it.
They are also the fastest of the three. They do the least work.
🇹🇭 ไทย
Data classes มากับ Python 3.7 เมื่อปี 2018 เป็นส่วนหนึ่งของตัว Python เอง
นั่นคือจุดแข็งที่สุดของมัน ไม่ต้องติดตั้ง ไม่เพิ่ม dependency ไม่ต้องคอยอัปเดต
มันไม่ตรวจอะไรเลย ถ้าข้อมูลมาจากโค้ดของคุณเอง ก็ไม่เป็นไร เพราะคุณเชื่อใจมันอยู่แล้ว
และมันเร็วที่สุดในสามตัว เพราะมันทำงานน้อยที่สุด
🇨🇳 中文
数据类随 Python 3.7 在 2018 年到来,是 Python 本身的一部分。
这是它最大的优点:不用装、不加依赖、不用维护更新。
它什么都不检查。如果数据是你自己的代码造的,这没问题,反正你信得过。
它也是三者中最快的,因为它做的事最少。
guests: list = []. Python refuses it, and it is right to. One list would be shared by every booking you make. Use field(default_factory=list), which builds a fresh list each time.
อย่าเขียน guests: list = [] เด็ดขาด Python จะปฏิเสธ และมันปฏิเสธถูกแล้ว เพราะลิสต์ก้อนเดียวจะถูกใช้ร่วมกันทุกการจอง ให้ใช้ field(default_factory=list) ซึ่งสร้างลิสต์ใหม่ทุกครั้ง
千万别写 guests: list = []。Python 会拒绝,而且拒绝得对:那样所有预订会共用同一个列表。请用 field(default_factory=list),它每次都新建一个列表。
6️⃣ attrs — the older, quieter one · attrs — ตัวที่เก่ากว่าและเงียบกว่า · attrs —— 更老、更低调的那个
🇬🇧 English
Most people meet attrs last. In fact it came first, in 2015.
Data classes were built later. The Python team looked at attrs first. attrs is the parent.
So why use it now? Because it kept going. It does things data classes still cannot do.
It gives you checks per field, and it never coerces. If you say int, text is refused, even "28".
🇹🇭 ไทย
คนส่วนใหญ่รู้จัก attrs เป็นตัวสุดท้าย แต่จริง ๆ มันมาก่อนใคร ตั้งแต่ปี 2015
Data classes ถูกสร้างทีหลัง และทีม Python ก็ดู attrs เป็นต้นแบบตอนสร้าง attrs จึงเป็นรุ่นพ่อ
แล้วทำไมยังใช้มันอยู่ เพราะมันพัฒนาต่อไม่หยุด มันทำสิ่งที่ data classes ยังทำไม่ได้
มันให้คุณตรวจค่าทีละฟิลด์ และมันไม่แปลงค่าให้เลย ถ้าคุณบอกว่า int ข้อความจะถูกปฏิเสธ แม้แต่ "28"
🇨🇳 中文
多数人最后才认识 attrs。其实它最早,2015 年就有了。
数据类是后来才做的,Python 团队当时参考了 attrs。attrs 是长辈。
那现在为什么还用它?因为它一直在往前走,做得到数据类至今做不到的事。
它让你按字段做检查,而且从不做转换。你说 int,文本就会被拒绝,连 "28" 也一样。
converter=. On a big team this is a feature. You read the class. You know what it will do.
นั่นคือนิสัยของ attrs ไม่มีอะไรเกิดขึ้นเองแบบเวทมนตร์ การแปลงค่าเกิดเฉพาะที่คุณเขียน converter= ไว้ ในทีมใหญ่ นี่คือข้อดี คุณอ่านคลาสแล้วรู้ทันทีว่ามันจะทำอะไร
这就是 attrs 的性格。没有任何魔法。只有你写了 converter= 的地方才会转换。在大团队里这是优点:读一遍类,就知道它会做什么。
7️⃣ Pydantic — the guard at the door · Pydantic — ยามที่เฝ้าประตู · Pydantic —— 守门的那一个
🇬🇧 English
Pydantic has one job. It stands at the door of your program.
Data from outside is never safe. A web form. A JSON file. Another company's API.
Pydantic reads that mess. It checks every field. It hands you a clean object. Or it refuses, and tells you which field was wrong.
This is why FastAPI is built on it. A web server is all door.
🇹🇭 ไทย
Pydantic มีหน้าที่เดียว มันยืนเฝ้าอยู่ที่ประตูของโปรแกรมคุณ
ข้อมูลจากข้างนอกไม่เคยปลอดภัย ทั้งฟอร์มบนเว็บ ไฟล์ JSON หรือ API ของบริษัทอื่น
Pydantic อ่านของรก ๆ นั้น ตรวจทุกฟิลด์ แล้วส่งอ็อบเจกต์ที่สะอาดให้คุณ หรือไม่ก็ปฏิเสธ พร้อมบอกว่าฟิลด์ไหนผิด
นี่คือเหตุผลที่ FastAPI สร้างอยู่บนมัน เพราะเว็บเซิร์ฟเวอร์คือประตูล้วน ๆ
🇨🇳 中文
Pydantic 只有一个任务:站在你程序的门口。
外面来的数据从来不安全:网页表单、JSON 文件、别家公司的 API。
Pydantic 读那堆乱东西,逐个字段检查,然后交给你一个干净的对象;或者拒绝,并告诉你哪个字段错了。
这就是 FastAPI 建在它上面的原因 —— 一个 web 服务器,全身都是门。
8️⃣ What does the checking cost? · การตรวจสอบมีราคาเท่าไร · 做检查要付出多少代价
🇬🇧 English
Checking is work, and work takes time. So Pydantic is slower. How much slower?
We built the same small object 100,000 times in each. Python 3.12, Pydantic 2.13, attrs 26.1.
Pydantic took about 6 times as long as a data class. That sounds bad. Look at the real number.
It is 0.75 millionths of a second per object. For data coming off a network, this cost is nothing.
It only matters in a tight loop over millions of rows. Then reach for a data class.
🇹🇭 ไทย
การตรวจสอบคืองาน และงานก็กินเวลา Pydantic จึงช้ากว่า แต่ช้ากว่าเท่าไร
เราสร้างอ็อบเจกต์เล็ก ๆ ตัวเดียวกัน 100,000 ครั้งในแต่ละตัว บน Python 3.12, Pydantic 2.13, attrs 26.1
Pydantic ใช้เวลาราว 6 เท่า ของ data class ฟังดูแย่ แต่ลองดูตัวเลขจริง
มันคือ 0.75 ในล้านวินาที ต่ออ็อบเจกต์หนึ่งตัว สำหรับข้อมูลที่มาจากเครือข่าย ราคานี้เท่ากับศูนย์
มันจะสำคัญก็ต่อเมื่อคุณวนลูปข้อมูลหลายล้านแถว ตอนนั้นค่อยหันไปใช้ data class
🇨🇳 中文
检查是活儿,干活要花时间,所以 Pydantic 更慢。慢多少?
我们用三者各建同一个小对象 10 万次。Python 3.12、Pydantic 2.13、attrs 26.1。
Pydantic 花的时间约为数据类的 6 倍。听着很糟,但看看真实数字。
每个对象 0.75 微秒。对于从网络上来的数据,这点代价等于零。
只有在几百万行的紧密循环里才要紧。那时候再用数据类。
timeit, 100,000 builds each, on Python 3.12.10. Your machine will differ. The shape will not.
วัดด้วย timeit อย่างละ 100,000 ครั้ง บน Python 3.12.10 เครื่องคุณจะได้ตัวเลขต่างออกไป แต่สัดส่วนจะเหมือนเดิม
用 timeit 各测 10 万次,Python 3.12.10。你的机器数字会不同,但比例不会。
9️⃣ So which one do I use? · แล้วจะใช้ตัวไหนดี · 那我到底该用哪个
🇬🇧 English
There is one question that matters most. Where did this data come from?
Data your own code made is safe. You wrote it. Trust it, and use a data class.
Data from outside is not safe. Check it at the door, with Pydantic.
Answer the three questions below. Watch the answer change.
🇹🇭 ไทย
มีคำถามหนึ่งที่สำคัญที่สุด ข้อมูลนี้มาจากไหน
ข้อมูลที่โค้ดของคุณสร้างเองนั้นปลอดภัย คุณเขียนมันเอง เชื่อใจได้ ใช้ data class ไปเลย
ข้อมูลจากข้างนอกไม่ปลอดภัย ต้องตรวจตั้งแต่ที่ประตู ด้วย Pydantic
ลองตอบสามคำถามด้านล่าง แล้วดูคำตอบเปลี่ยนไป
🇨🇳 中文
最要紧的只有一个问题:这份数据是哪来的?
你自己代码造的数据是安全的。是你写的,信得过,用数据类就行。
外面来的数据不安全。要在门口就查,用 Pydantic。
回答下面三个问题,看答案怎么变。
| Questionหัวข้อ项目 | 🧊 dataclasses | 🛠️ attrs | 🛡️ Pydantic |
|---|---|---|---|
| Need to install it?ต้องติดตั้งไหม需要安装吗 | No — it is in Pythonไม่ — มากับ Python不用 —— Python 自带 | Yesต้อง要 | Yesต้อง要 |
| Checks types?ตรวจชนิดข้อมูลไหม检查类型吗 | Neverไม่เลย从不 | If you askถ้าคุณสั่ง你要求才查 | Alwaysตลอดเวลา总是 |
Changes "28" to 28?แปลง "28" เป็น 28 ไหม把 "28" 变 28 吗 |
Noไม่不 | Only with a converterเฉพาะเมื่อใส่ converter加了 converter 才会 | Yes, by defaultใช่ เป็นค่าเริ่มต้น是,默认就会 |
| Reads JSON in one step?อ่าน JSON ได้ในขั้นตอนเดียวไหม一步读 JSON 吗 | No, by handไม่ ต้องทำเอง不,要手写 | No, by handไม่ ต้องทำเอง不,要手写 | Yesได้可以 |
| Speed building objectsความเร็วในการสร้างอ็อบเจกต์建对象的速度 | 0.12 µs | 0.11 µs | 0.75 µs |
| Best forเหมาะกับ最适合 | Data you already trustข้อมูลที่เชื่อใจอยู่แล้ว你已经信得过的数据 | Careful classes, no surprisesคลาสที่ควบคุมเองทุกอย่าง要精确控制、不要意外 | Data from outsideข้อมูลจากข้างนอก从外面来的数据 |
🔟 You can use two of them together · ใช้สองตัวร่วมกันก็ได้ · 两个可以一起用
🇬🇧 English
This is not a fight. Most real programs use two.
Pydantic guards the door. Data classes hold everything inside.
Pydantic also has a bridge. It can add checking to a normal data class.
Use the bridge if you have data classes already. It adds checks without a rewrite.
🇹🇭 ไทย
นี่ไม่ใช่การแข่งกัน โปรแกรมจริงส่วนใหญ่ใช้สองตัว
Pydantic เฝ้าประตู ส่วน data class เก็บข้อมูลทุกอย่างข้างใน
Pydantic ยังมีสะพานเชื่อมด้วย มันเพิ่มการตรวจสอบให้ data class ธรรมดาได้
ใช้สะพานนี้เมื่อคุณมี data class อยู่แล้ว และอยากได้การตรวจสอบโดยไม่ต้องเขียนใหม่
🇨🇳 中文
这不是一场比武。多数真实程序会同时用两个。
Pydantic 守门,数据类在里面装东西。
Pydantic 还给了一座桥:它能给普通数据类加上检查。
如果你已经有一堆数据类,又想要检查但不想重写,就走这座桥。
1️⃣1️⃣ Real job: Gmail and Yahoo logins · งานจริง: การล็อกอิน Gmail และ Yahoo · 实战:Gmail 和 Yahoo 的登录
🇬🇧 English
Now use the lesson on a real job. Your program must read and send email.
To do that it needs a login. That login comes from outside your code.
So this is Pydantic's job. It is the door again.
Never put a password in your code. Never commit one to git.
🇹🇭 ไทย
ทีนี้เอาบทเรียนไปใช้กับงานจริง โปรแกรมของคุณต้องอ่านและส่งอีเมล
มันจึงต้องมีข้อมูลล็อกอิน และข้อมูลนั้นมาจากข้างนอกโค้ด
นี่จึงเป็นงานของ Pydantic มันคือประตูอีกครั้ง
อย่าใส่รหัสผ่านไว้ในโค้ด และอย่า commit ขึ้น git เด็ดขาด
🇨🇳 中文
现在把这堂课用到真活儿上。你的程序要读邮件、发邮件。
那就需要一份登录信息。这份信息来自代码外面。
所以这是 Pydantic 的活儿。又是那道门。
绝不要把密码写进代码,也绝不要提交到 git。
2. Go to
myaccount.google.com/apppasswords3. Name it
python. Google shows 16 letters.4. Copy them now. Google will not show them again. 1. เปิด 2-Step Verification ก่อน ถ้าไม่เปิด Google จะซ่อนเมนูนี้ไว้
2. ไปที่
myaccount.google.com/apppasswords3. ตั้งชื่อว่า
python แล้ว Google จะแสดงตัวอักษร 16 ตัว4. คัดลอกทันที Google จะไม่แสดงให้ดูอีก 1. 先开启两步验证。不开的话,Google 不会显示这个入口。
2. 打开
myaccount.google.com/apppasswords3. 命名为
python,Google 会给你 16 个字母。4. 立刻复制。Google 不会再显示第二次。
login.yahoo.com/account/security2. Click Generate app password.
3. Name it
python. Yahoo shows 16 letters.4. Yahoo shows them in four groups. The spaces do not matter. 1. ไปที่
login.yahoo.com/account/security2. กด Generate app password
3. ตั้งชื่อว่า
python แล้ว Yahoo จะแสดงตัวอักษร 16 ตัว4. Yahoo แสดงเป็นสี่กลุ่ม ช่องว่างไม่มีผล ลบออกได้ 1. 打开
login.yahoo.com/account/security2. 点 Generate app password。
3. 命名为
python,Yahoo 会给你 16 个字母。4. Yahoo 分成四组显示。空格没有影响,可以删掉。
.env file. This file sits next to your code. It never goes into git.
ขั้นที่ 2 — เก็บไว้ในไฟล์ .env ไฟล์นี้วางไว้ข้าง ๆ โค้ด และไม่ขึ้น git เด็ดขาด
第 2 步 —— 放进 .env 文件。这个文件放在代码旁边,永远不进 git。
.env file, and the program stops at once. It names every field that is missing.
ถ้าลืมไฟล์ .env โปรแกรมจะหยุดทันที พร้อมบอกชื่อทุกฟิลด์ที่ขาดไป
如果忘了 .env,程序立刻停下,并点名每一个缺失的字段。
SecretStr is for
🙈 SecretStr มีไว้ทำอะไร
🙈 SecretStr 是干什么的
Logs leak passwords. SecretStr stops that. We tested all three ways out. None of them printed the password.
ล็อกไฟล์คือจุดที่รหัสผ่านรั่ว SecretStr ช่วยกันไว้ เราทดสอบทางออกทั้งสามทางแล้ว ไม่มีทางไหนพิมพ์รหัสผ่านออกมาเลย
日志是密码泄露的地方。SecretStr 挡住了它。三条出口我们都测过,没有一条会把密码打出来。
| Serviceบริการ服务 | Send (SMTP)ส่ง (SMTP)发送 (SMTP) | Read (IMAP)อ่าน (IMAP)读取 (IMAP) | Loginการล็อกอิน登录方式 |
|---|---|---|---|
| 📧 Gmail | smtp.gmail.com:465 SSL |
imap.gmail.com:993 SSL |
App passwordApp password应用专用密码 |
| 💜 Yahoo | smtp.mail.yahoo.com:465 SSL |
imap.mail.yahoo.com:993 SSL |
App passwordApp password应用专用密码 |
credentials.json and a token.json file. There is no password at all. That token also expires, so it needs renewing. Yahoo has no such option — the app password is the only road.
ทุกอย่างข้างบนใช้ SMTP และ IMAP ซึ่งเป็นโปรโตคอลอีเมลแบบเดิม app password ก็เพียงพอแล้ว แต่ Gmail API ต่างออกไป มันใช้ OAuth พร้อมไฟล์ credentials.json และ token.json ไม่มีรหัสผ่านเลย และโทเคนนั้นหมดอายุได้ ต้องต่ออายุเป็นระยะ ส่วน Yahoo ไม่มีทางเลือกนี้ app password คือทางเดียว
上面全部走 SMTP 和 IMAP,也就是老牌邮件协议,用应用专用密码就够。Gmail API 不一样:它走 OAuth,要 credentials.json 和 token.json 两个文件,根本没有密码。那个 token 还会过期,需要续期。Yahoo 没有这个选项,应用专用密码是唯一的路。
1️⃣2️⃣ Check yourself · ทดสอบตัวเอง · 自我检测
age = "28" as text. Which one silently stores the text?@dataclassage holds the string '28', and nothing warns you. The bug appears later, when you try to do maths with it."28". What does Pydantic do by default?28None"28" becomes 28. This is what makes it good at web forms. Turn it off with model_config = {"strict": True}.validator=validators.instance_of(int). What happens with "28"?TypeError — attrs never coerces28, like Pydanticint and got a str, so it raises. If you want repair, add converter=int yourself.guests: list = [] in a data class. What happens?default_factoryValueError: mutable default <class 'list'> ... use default_factory. Python stops you, because one shared list would be a real bug. Write field(default_factory=list).dict