Scope & arguments
Python Basics Lesson 11 3:04 English narration · English + 中文 subtitles burned in
Chapters
Transcript
Think of your program as a room, and every function call as a smaller room inside it.
把你的程序想象成一个房间,每一次函数调用是里面的一个小房间。
A variable made inside the function belongs to that small room: it is created when the call starts and thrown away when the call ends.
在函数里创建的变量属于那个小房间:调用开始时它被创建,调用结束时被丢掉。
Outside, that name simply does not exist, and asking for it gives a NameError.
在外面,那个名字根本不存在,去访问它会得到 NameError。
This is good news, not a restriction — it means two functions can both use a variable called total without ever interfering.
这是好事,不是限制——它意味着两个函数都可以使用一个叫 total 的变量, 而彼此永远不会打架。
A name defined at the top level of the file is global, and a function can read it happily — a pass mark or a tax rate is a fair thing to look up.
在文件最外层定义的名字是全局的,函数可以放心地读它—— 像及格线或者税率这种东西,去查一下是很合理的。
But if you assign to it inside a function, Python does something surprising: it makes a brand-new local name with the same spelling, and the global is untouched.
但如果你在函数里面给它赋值,Python 会做一件让人意外的事: 它会新建一个拼写相同的局部名字,而全局的那个毫发无损。
So the habit worth building is to pass it in as a parameter and return the result.
所以值得养成的习惯是:把它作为参数传进去,再把结果返回出来。
Then a function's answer depends only on what you handed it.
这样函数的答案就只取决于你交给它的东西。
A parameter can carry a fallback value, written with an equals sign in the definition.
形参可以带一个默认值,在定义里用等号写出来。
Then the caller may leave it out, and the fallback is used — greet of Mia gives Hi, Mia.
这样调用者可以把它省略,用的就是默认值——greet("Mia") 得到 "Hi, Mia!"。
Or they may supply your own greeting, and that wins.
调用者也可以自己给一个问候语,那就用他给的。
One rule of grammar: parameters with defaults must come last in the list, because Python matches the ones without defaults by position first.
有一条语法规则:带默认值的形参必须放在最后, 因为 Python 会先按位置去匹配那些没有默认值的形参。
Now the part that quietly surprises people.
现在说那个悄悄让人吃惊的地方。
Pass a number and the function gets a copy: adding one inside changes nothing outside, so x is still five.
传一个数字,函数拿到的是副本: 在里面加 1,外面什么也没变,x 还是 5。
Pass a list and the function gets the same list, not a copy — appending inside really does change the caller's list.
传一个列表,函数拿到的就是同一个列表,不是副本—— 在里面 append,调用者的列表真的会被改变。
That is often exactly what you want, and it is a bug when you did not expect it.
这常常正是你想要的,而在你没预料到时它就是个 bug。
If you need to keep the original, make a copy first.
如果需要保留原来的列表,先复制一份。
Now the lesson's third task: a function that says whether x lies between low and high, boundaries included.
现在做课程里的第三道题:写一个函数,判断 x 是否在 low 和 high 之间,包含边界。
The body is one line — low at most x, and x at most high — and you return the comparison itself, because a comparison already IS True or False.
函数体只有一行——low 小于等于 x,并且 x 小于等于 high—— 而且你直接把这个比较返回出去,因为比较的结果本身就是 True 或 False。
Test three values: one comfortably inside gives True, one on the boundary also gives True because the test uses at-most, and one just outside gives False.
测三个值:一个稳稳在里面的,得到 True; 一个正好落在边界上的,也得到 True,因为用的是小于等于; 一个刚刚超出去的,得到 False。
Four things to take with you.
带走四点。
One: a name made inside a function dies with the call, which is why two functions never clash.
第一:函数里创建的名字随着这次调用一起消失, 所以两个函数永远不会撞名。
Two: a global can be read inside a function, but assigning to it makes a local instead — prefer passing it in.
第二:全局变量可以在函数里读,但给它赋值只会造出一个局部变量—— 更好的做法是把它传进去。
Three: a default value lets a caller leave an argument out.
第三:默认值让调用者可以省略某个实参。
Four: numbers and strings are copied into a call, while a list is shared, so a function can change it.
第四:数字和字符串是被复制进调用的,而列表是共享的,所以函数能改动它。
Now do the three tasks.
现在去做那三道题。