不用装任何编程软件,打开浏览器就能跑Python,这样学起来就没那么重的负担。我先说结论:变量和数据类型是Python这座大厦的地基,地基打不牢,后面学函数、写爬虫、做数据分析都会觉得飘。但别被"数据类型"这四个字吓住,它本质上就是给电脑里的数据分门别类,就像你整理衣柜,上衣归上衣、裤子归裤子,你拿的时候才不会翻半天。
这篇Day1打卡我会带着你彻底搞懂两件事:变量到底是个什么东西,以及Python里常见的数据类型各自长什么样。我会把所有概念拆成大白话,配合能直接复制的代码示例,你照着敲一遍就明白了。今天的内容学完,你就能自己写一个简单的个人信息输出程序,比打印"Hello World"有意义多了。
1. 变量就是给数据贴个标签,不是把数据装进盒子
1.1 为什么我们需要变量
很多教程上来就让你写a = 1,然后告诉你"这就是变量",但你心里肯定会嘀咕:这有什么意义?我直接把1写在代码里不行吗?直接从需求端给你解释。
假设你要写一个程序,计算你一个月的零花钱总额。你每天的零花钱是10块,一个月按30天算,那代码可以写成:
print(10 * 30)这样写没什么问题,但第二天零花钱涨到了12块,你得在代码里找到10改成12。如果这个"10"在代码里出现了几十次呢?你得改几十个地方,手一抖漏改一个,计算结果就错了。
如果你用变量:
day_money = 12 days = 30 total = day_money * days print(total)以后想改成15块,只需要改第一行的12,后面全部跟着变。这就是变量的第一个核心价值:让数据有了名字,你修改数据的时候不用大海捞针。
再往深一层想,你的程序从早上跑到晚上,早上你输入的是"早饭5块",中午你输入的是"午饭20块"。同一个位置,不同时刻存放的内容不一样,这个"可以变化的内容"就需要一个容器来装——这就是变量存在的第二个理由:它让程序能在运行过程中记住不停变化的数据。
1.2 把变量理解成"贴了标签的收纳盒",别理解成"盒子本身"
这是我当时学Python时一位老师给我的比喻,一下就通了。
你可以把内存想象成一面墙,上面有一排一排镂空的格子,每个格子都能放东西。变量名就是你在格子上贴的便签纸,比如你贴了一张写着"money"的便签,往里塞一张一百块,之后你只要喊"money",这一百块就递到你手上。
重点来了:标签贴哪个格子是Python解释器帮你安排的,你不用管格子具体在哪。你只需要记住:变量名是标签,标签后面的值才是格子里真正存放的东西。
所以当你做下面这个操作:
a = 10 b = a你的直觉可能是"把a复制了一份给b"。实际上更准确的理解是:"b"这个标签和"a"这个标签,贴到了同一个格子上。现在格子里放着10,你喊a和喊b,拿出来的都是10。
这就是为什么后面你学到"变量指向"这个概念时不会脑袋发晕——变量不是盒子,变量是盒子上的名字。如果你暂时没接触过这个,记住这句话,未来学列表、字典、对象引用时你会回来感谢我。
1.3 Python变量的懒人哲学:不用声明类型,直接赋值
如果你看过C语言或者Java的代码,你会发现它们写变量要提前声明类型:
int money = 10;意思是告诉电脑:"我要放一个整数,这个格子以后永远放整数。"然后你再往这个格子里塞字符串"hello",编译直接报错。
Python特别"懒",你写money = 10,它自动知道你放了个整数;你写money = "hello",它自动知道你放了个字符串。你不说,它自己看,这就是"动态类型"。
这个特性对新手来说简直是福音——你可以把注意力全放在"逻辑对不对"上,不用操心"类型符写没写对"。
但天下没有免费的午餐。动态类型带来的一个经典坑是:变量名在程序运行的不同阶段可能装着不同类型的值。
value = 100 # 此刻是整数 print(value * 2) # 输出200 value = "100" # 此刻变成了字符串 print(value * 2) # 输出100100,字符串"100"重复两次同样的代码value * 2,结果一个200一个100100,很多人第一次看到直接在电脑前呆住了。这不是Python出bug了,是因为value的类型变了:整数20乘2是400,字符串"20"乘2是"2020"(字符串复制两遍)。
结论就一条:写代码时,一个变量尽量从头到尾只存放一种类型的数据。你要是拿它存了数字,就永远存数字;存了字符串,就永远存字符串。这不是Python的强制要求,但这是所有老手默认遵守的规矩。我会在本篇后面专门讲这个坑会怎么咬你。
2. Python五大基础数据类型:数字、字符串、布尔值,加上list和dict
2.1 数字类型:int和float,别把1和1.0混为一谈
Python里的数字主要有两个"选手":整数int和小数float。
age = 18 # int 整数 price = 9.9 # float 小数 temperature = -5 # int 可以是负数 pi = 3.1415926 # float 可以有精度的概念int和float最大的区别,除了有没有小数点之外,还有一个你以后一定会用到的特性:类型转换容易出岔子。
print(10 / 3) print(10 // 3) print(10 % 3)我列一下结果你感受下:
10 / 3结果是3.3333333333333335(float)10 // 3结果是3(整除,只留整数部分)10 % 3结果是1(余数)
很多新手在这里会犯一个迷糊:怎么Python算出来的小数尾巴不是干干净净的3.3333?这是因为计算机用二进制存小数,就像你用十进制没法精确表示三分之一一样,电脑用二进制也没法精确表示0.1。这个属于进阶话题,你现在只需要记住:float的运算结果偶尔会有很长的尾巴是正常的,不是算错了。
下面这些照片,我建议你截图存着,即使现在用不上,未来处理金额、距离、温度时会经常碰到。
2.2 字符串:带引号的一切都是字符串
字符串是你今天要认识的最重要的类型。你用input()从键盘输入的一切,Python一律当成字符串接收。
name = "小明" city = '上海' sentence = "他说:\"好的\""字符串的定义有三个坑你必须今天避开:
第一个坑,单双引号不能随意嵌套混用。上面第三行的写法,内部有英文双引号,外面就用单引号包住,或者转义。你看我写的:
sentence = "他说:\"好的\""我用了反斜杠\对内部的英文双引号做了转义,这是最稳的写法。如果你内部既有单引号又有双引号,还有一种三引号的解法:
long_text = """第一行 第二行 第三行"""三引号可以保留换行,这个以后写多行说明文字会非常实用。
第二个坑,字符串不能直接和数字拼接。你写print("我今年" + 18 + "岁"),Python会毫不留情地报错:can only concatenate str (not "int") to str。翻译过来就是"我只能拼接字符串,不能拼接整数"。解决办法是先类型转换,把18转成字符串"18",这部分我在第4章展开讲。
第三个坑,字符串拼接在循环里特别费资源。你Day1阶段不用管性能,但养成好习惯要趁早:频繁给字符串"加字符",Python会不停创建新字符串然后抛弃旧的,循环一百次就是一百次内存垃圾。简单说,能用格式化就尽量用格式化:
name = "小明" score = 95 print(f"{name}考了{score}分") print("{}考了{}分".format(name, score)) print("%s考了%d分" % (name, score))上面三行分别是f-string、format方法、百分号格式化,效果一模一样,都是输出"小明考了95分"。f-string是现在的主流写法,又直观又好用,你今天就学会用它。
2.3 布尔值:True和False,就是1和0的孪生兄弟
布尔值只有两个:True和False。注意首字母大写,小写true会直接报错。
什么时候会产生布尔值?语法上最常见的两处:比较运算和逻辑运算。
print(3 > 2) # True print(3 == 2) # False print(3 != 2) # True更重要的是,布尔值可以直接参与算术运算:Python里True本质就是整数1,False本质就是整数0。
print(True + True) # 2 print(True * 5) # 5 print(False * 100) # 0看到1和0这对孪生兄弟了吗?将来你学循环里的计数逻辑时,经常会看到count = count + True这种写法,其实就是在给变量加1。
还有一个很隐蔽的特性:很多"空"的东西会被当作False。空字符串""、数字0、空的列表[]、None,放到if的判断条件里时,效果等同于False。
name = "" if name: print("有名字") else: print("名字为空")这段代码输出"名字为空",不用写if name != ""那么啰嗦。这是我建议你从一开始就要习惯的Python特性,很多老手判断数据存不存在,都是直接if 变量:,简洁得很。
2.4 list和dict:一个管顺序,一个管对应关系
Day1阶段,我们把list(列表)和dict(字典)也拉出来见个面。因为后面几乎天天和它们打交道,早点混个眼熟不吃亏。
list(列表)就是一条按顺序排队的队伍:
fruits = ["苹果", "香蕉", "橘子"] print(fruits[0]) # 苹果 print(fruits[1]) # 香蕉 print(fruits[-1]) # 橘子,-1代表倒数第一个下标从0开始,这是我当年第一次算错的地方:我想要第一个水果,却写成了fruits[1],输出的是香蕉。记住,Python第0个才是第一个。
dict(字典)就是一张"名字对应值"的对照表:
student = {"name": "小明", "age": 12, "city": "上海"} print(student["name"]) # 小明 print(student.get("age")) # 12以后你用爬虫爬下来的数据、用API接口取回来的数据、做数据分析时的表格结构,绝大多数都是一层套一层的dict结构。Day1你只要会创建dict、会用键取对应的值就足够了。
我专门把list和dict放出来,是希望你有个心理预期:Day2、Day3就会专门学它们。今天你只需要知道有这两种东西,不用深入研究。
3. 用type()和id()当"显微镜"看透数据的真身
3.1 type():直接问Python"我这是什么类型"
变量的类型不用背,写程序时随时可以问Python:
a = 42 print(type(a)) # <class 'int'> b = 3.14 print(type(b)) # <class 'float'> c = "Python" print(type(c)) # <class 'str'> d = True print(type(d)) # <class 'bool'> e = [1, 2, 3] print(type(e)) # <class 'list'> f = {"name": "小明"} print(type(f)) # <class 'dict'>我强烈建议你每定义一个变量,就随手print(type(变量))看看。这个习惯会让你少走很多弯路。
举个例子,你写了半天input()输入年龄,然后拿它去比较大小,结果怎么都不对。如果当时打印一下type(输入的内容),你会发现它的类型是str而不是int——字符串和整数比较大小,Python会直接报错或者给出让你摸不着头脑的结果。类型一看就明白了。
3.2 id():看变量的内存地址,理解"变更"的本质
id()返回的是变量指向的内存地址,你可以把它理解成"数据在墙上的哪个格子"。同一个数据,id值相同;不同数据,id值不同。
a = 100 print(id(a)) b = a print(id(b)) # 和上面一样,b和a指向同一个格子当你执行b = a之后,b和a的id是一样的。这说明b不是a的"复制品",它们俩贴的标签在同一个格子上。
看一个更有意思的:
x = 5 print(id(x)) x = 10 print(id(x))两次打印的id值不一样。也就是说,x = 10这一步,并不是在原来的格子里把5改成了10,而是把x这张标签撕下来,贴到了另一个放着10的格子上。原来的5那个格子还在,只是没有标签了,过一会儿Python会把它自动回收掉。
这个微观视角能帮你解释很多"玄学Bug"。比如两个变量间的"相互影响"、函数里改了变量但外面没变,真正的根因都是这个"标签"机制。Day1不深究,但你看到id()时心里要有数。
3.3 换行代码怎样实践?
建议你把今天的内容在一个Python文件里敲一遍,每定义一个变量就打印它的type和id:
name = "小明" age = 18 height = 1.75 student = True print(name, type(name)) print(age, type(age)) print(height, type(height)) print(student, type(student))运行之后你会看到一个"体检报告":name是str、age是int、height是float、student是bool,一目了然。这样每个概念都不是纸上谈兵,而是你在屏幕上亲眼看到的。
4. 类型转换:int()、float()、str()三兄弟怎么救你于水火
4.1 为什么要转换类型——input()陷阱
新手碰到最多的场景是:用input()让用户输入年龄。
age = input("请输入你的年龄:") print(type(age)) # 永远是str,不管输入的是18还是"18"input()函数有一个"霸道"的设计:你输入什么,它就按字符串返回什么。你输入18,它返回的是字符串"18",不是数字18。
如果你拿字符串"18"去算"明年多大":
age = input("请输入你的年龄:") print(age + 1)直接报错。因为字符串不能和整数相加。想让你的年龄能计算,得先把字符串转成整数:
age = input("请输入你的年龄:") age = int(age) print(age + 1) # 正常输出明年年龄这样写,整个过程是:读取到字符串"18",int()把它转成整数18,加1得19,最后输出。
4.2 三个转换函数的完整使用手册
我把最常用的三个转换函数列一个表,你能看明白哪边能转、哪边转不了:
| 函数 | 作用 | 成功案例 | 失败案例 |
|---|---|---|---|
int(x) | 把x转成整数 | int("18")得到18,int(3.99)得到3(注意会丢掉小数部分) | int("hello")报错,int("3.14")也会报错,因为它是小数格式的字符串 |
float(x) | 把x转成小数 | float("3.14")得到3.14,float(5)得到5.0 | float("abc")报错 |
str(x) | 把x转成字符串 | str(18)得到"18",str(3.14)得到"3.14" | 几乎不会失败 |
写代码时要特别注意,int("3.14")是无法转换的。如果你真碰到用户输入了小数,你要么用float(),要么写:
value = "3.14" print(int(float(value))) # 先转成3.14,再转成整数3先转float再转int,相当于把小数"截断"成整数,小数部分直接丢掉,不存在四舍五入。
4.3 数字转字符串的真正重点:拼接场景
字符串拼接时,数字不转字符串是真的没法干活。我见过太多新手卡在这一句代码上:
想要输出"我今年18岁":
age = 18 print("我今年" + age + "岁") # 报错,字符串不能和整数拼接正确写法是:
age = 18 print("我今年" + str(age) + "岁")或者更漂亮的f-string写法:
age = 18 print(f"我今年{age}岁")f-string会在内部自动把age从int转成str,不用你手动操作。这也是我说Day1就学会f-string的原因,它帮你省掉了一半的类型转换焦虑。
但别误会,f-string再方便,类型转换你还是要掌握的,因为input()读进来的字符串在做数值计算前,必须手动转成int或float,f-string帮不了这个忙。
5. Day1最容易翻车的三个坑:命名、缩进、和"看得懂但写不出"
5.1 变量命名:别用中文、别用拼音缩写、别用关键字
变量名这件事,Day1不做好,Day2就开始疼。
首先,变量名不能是Python关键字。关键字总共三十几个,比如if、for、while、and、or、not、class、def。你写if = 3,Python直接报语法错误。想判断你用的名字是不是关键字,可以这样:
import keyword print(keyword.kwlist)它会输出Python的全部关键字列表,你对照着看就行。
其次,变量名不能以数字开头。1var是违法的,var1合法。这个描述虽然直接,但很多人真的会栽在这,写着写着就打了2test这种名字。
再次,见名知意。d = 12不如daily_money = 12,因为三个月后再看代码,你绝对忘记d是什么。Python社区惯例是用下划线分隔单词,比如user_name、total_score,不要用userName这种驼峰式——Java风格在Python里不是不行,但大多数Python项目都遵守PEP8约定,你早点适应没坏处。
最后,我再加一条个人感受:不要用拼音缩写。我见过一个项目里到处都是hsl、zt,原作者都说是"负责人"的拼音,但过了一个月他自己都忘了。你哪怕是写hs_l,也不要只写hsl。命名是给未来的自己看的,这个投入永远不亏。
5.2 缩进:在Python里就是代码的"骨架"
很多教程会把缩进放在很后面讲,但我遇到过太多学员第一天就折在缩进上。
Python用缩进表示代码块之间的归属关系。比如:
score = 85 if score >= 60: print("及格了")在if那行后面,print前必须有一个缩进(通常是一个Tab或者四个空格)。你如果不缩进,Python立刻报错:IndentationError: expected an indented block。
你要记住一个容易踩的坑:同一层级的代码块,缩进量必须完全一致。你第一行用四个空格,第二行不小心用了两个空格,Python也报错,因为它在同一层级上看到了不一致的缩进。
最稳妥的做法是:从头到尾统一使用四个空格,且设置编辑器"Tab键转换为空格"。这样你再怎么混,都只会是四个空格,不会产生"看着对齐了其实没对齐"的幽灵问题。
5.3 看得懂但写不出的破解办法:遇到报错就翻译成"人话"
Day1最常见的画面是:我照着教程敲代码,看着明明一样,一运行就报错。然后盯着屏幕发呆。
我建议你把这个流程刻在脑子里:
- 把报错信息整体复制下来,别只瞄一眼。
- 找英文关键词翻译:
SyntaxError是语法错误,NameError是名字未定义(通常是你用了没赋值的变量),TypeError是类型错误(比如字符串和整数混着运算),ValueError是值不对(比如int("abc"))。IndentationError是缩进错误。 - 对照报错信息里指出的行号,找到那一行,重新逐字检查左右引号、括号、冒号、等号。
比如NameError: name 'age' is not defined,就是告诉你:有个叫age的名字你还没定义就拿来用了。大概率是你把age = 20这行注释掉,或者拼成了aeg = 20。这种报错本质上是在帮你抓错,不是Python在惩罚你。
我见过很多人一天能遇到十几个报错,然后就开始怀疑自己。其实报错是学编程里最正常的事情——有报错说明Python在跟你说话,没报错才是真的可怕。
6. Day1打卡实训:做一个能互动的"个人名片"程序
现在把今天学的所有东西用到一个小程序里。这个任务的目标是:你可以和程序对话,它读完你输入的信息后,输出一张格式整齐的个人名片。
完整代码如下,我可以负责地告诉你:它用到且只用到了今天的知识点:
# 一个能互动的个人名片生成器 print("=== 欢迎来到个人名片生成器 ===") name = input("请输入你的名字:") age = input("请输入你的年龄:") height = input("请输入你的身高(米):") city = input("请输入你所在的城市:") # 把字符串转成适合计算的数字 age = int(age) height = float(height) # 打印名片 print("\n--- 你的个人名片 ---") print(f"姓名:{name}") print(f"年龄:{age}岁") print(f"身高:{height}米") print(f"城市:{city}") print("类学习天数:1天") print("--- 名片制作完成! ---\n") # 计算明年年龄和身高是不是有变化 print(f"明年你就是{age + 1}岁了。") print(f"如果每天学到的东西能让你长高,已经长了{height * 1.001:.3f}米这种感觉。")你运行后,会看到程序停下来等你输入,你逐项输入,最后输出一张完整的名片。特别是{height * 1.001:.3f}这种写法,是把number格式化成3位小数,这是f-string的隐藏功能,你Day1就能用上。
这个程序涵盖了今天全部核心点:
- 字符串的输入与输出
- 字符串和数字的转换
- f-string格式化
- 整数和小数的基础运算
- 变量保存和调用
以后每次学的知识点变多,你可以在"名片"基础上一直加东西——比如加个if判断年龄是否成年,加个list存喜欢的学科,加个dict存更多个人信息。Day10的时候翻回来看,会非常有成就感。
我特意把这个练习放在最后一节,就是想让你有一个完整的"我今天学的东西真能用"的感觉。
7. 给Day1学习者的一些执行细节
学完基础知识,再给你上点"公共卫生"——日常练习中大家容易忽略的几个执行细节。
环境方面:如果你还没装Python,直接去官网下载最新稳定版,安装时勾选"Add Python to PATH"。这一步看起来不起眼,不勾的话后续在命令行里敲python会提示找不到命令。如果你不想碰命令行,也可以直接用浏览器搜索"在线Python运行环境",很多网站打开就能运行代码,应对Day1绰绰有余。
编辑器方面:VSCode依然是主流,装好后加装Python扩展插件和Pylance插件,写代码会有提示。但Day1真的不用纠结编辑器高级功能,任何能运行Python的方式都行。
练习时间安排:我建议一次不要超过90分钟。因为变量和数据类型是纯概念性的内容,硬啃很容易疲惫。我的经验是:学30分钟,动手敲20分钟码,玩会儿别的,回来再敲一遍今天的例程。两遍过后,你对"变量""类型"的肌肉记忆就形成了。
遇到报错心态:你在Day1遇到的所有报错,你都可以把它当成"Python在帮你找茬"。每解决一个,你就离真正会写程序近了一步。别因为几个报错就觉得自己不适合学编程,那些写出漂亮程序的人,当年也是从一屏幕报错中活过来的。
根据我带新手学习的经验,Day1放弃的人,绝大多数不是卡在智商上,而是卡在"环境没装好"和"把报错看成了天塌下来"这两件事上。今天你只要把两个小程序都跑通了,就已经赢过了大多数"准备学"但没开始的人。明天Day2,我们正式进入list和dict这些更有意思的容器类型。