基础部分
变量用于存储数据,你定义的每个变量都有一个值与它联系起来。
下面的代码中,我们定义了名叫“message”的变量,它与"Hello,world!"相关联。
message = "Hello,world!"
print(message)
显而易见,这段代码依然会输出“Hello,world!”,只是用了变量的途径。
变量的命名的规则
对于初学者,你只需要知道”一般情况下,变量的名称由数字、下划线、字母组成,不能以数字开头“就可以了,如感兴趣请看进阶部分。
错误示范:
123abc = "Hello,world!"
-abc = "Hello,world!"
运行结果如图所示(“Process finished with exit code 1”代表程序异常退出)
正确示范:
hello_world = "Hello,world!"
_hello_world_ = "Hello,world!"
__helloworld_ = "Hello,world!"
_123_ = "Hello,world!"
_1abc_3 = "Hello,world!"
print(hello_world)
print(_hello_world_)
print(__helloworld_)
print(_123_)
print(_1abc_3)
如图,运行结果正确
进阶部分
变量不是盒子
有时候,为了促使初学者快速理解,一些教程会告诉你“变量是盒子,值在盒子内”,诚然,这的确有助于快速入门,然而,等你学得更加深入之后,你会发现,这种说法并不一定成立。
举个列表引用的例子
li1 = [1, 2, 3] # 如果li1是一个盒子,那么现在li1中装有一个列表
li2 = li1 # 变量li2引用了li1
li2[0] = 42 # 通过变量li2修改列表
print(li1) # 发现li1也受到了影响
如果变量是一个盒子,那么li1和li2这两个变量代表了两个不同的盒子。
那么问题来了:我只是操作了li2这个盒子,li1作为另一个盒子,为什么也会受到影响?
因此,“变量是盒子”的说法并不严谨,无法正确描述变量的作用。
应该把变量视作便利贴(可能有些人会觉得有点陌生,对吧?请不要停在这里思考,继续往下看)
在《流畅的Python》第二版这一书中,引用了Lynn Stein 教授和Stein 教授的观点,详细讲解了把变量视作便利贴,以及类似“是给变量分配对象,还是给对象分配变量”?的一些相关问题。
在这里碍于篇幅,我只对便利贴这一方面做简单解释。
如果你读过《百年孤独》,你也许会想起一个情景:书中的人们为了对抗遗忘,给各种物体贴上了便利贴,甚至一个物体贴多个便利贴。
你可以照着这个思路理解,一个变量,是一个便利贴,就像刚刚提到的小说中的物体一样,往同一个对象上贴上多个便利贴。
图片来源于《流畅的Python》第二版的图6-1
使用字母、数字、下划线之外的字符
在Python3中,即使使用中文和一些其它外文,程序也可能不会报错,但非常不推荐这么做,因为这非常可能会导致程序出现乱码,还有其它不愉快的问题。
下面的代码依然能输出”Hello,world!“,但非常不推荐这么做,因为这大概率会引发一些编码问题1。
你好素晴らしいせかいworld = "Hello,world!"
print(你好素晴らしいせかいworld)
引起Pycharm红色警告,运行却不报错的方式
Python的命名空间其实是一个字典,我们可以直接使用给全局变量的字典定义键值对的方式定义全局变量。(其实一般情况下也没必要这么做,主要是为了加深对Python的理解)
globals()['a'] = "Hello,world!"
print(a)
利用闭包,防止污染全局变量
滥用全局变量并不是什么好事情。
有时候,你会注意到一些想用的变量名称已经被占用了,这时你将不得不换一个相对不好的名称来定义变量。
其实你可以利用闭包,这样就可以利用局部变量来随心所欲地定义一个想要的名称了。
闭包代码示例:
def func():
a = 1
def inner_func(num):
nonlocal a
a += num
print(a)
return inner_func
func_obj = func()
func_obj(1)
func_obj(2)
func_obj(3)
a = 114514
print(a)
1:关于Python的编码问题,读者可以阅读《流畅的Python》第二版的第四章以获取详细信息。