2.1 变量
变量是高级语言中的一个概念,在高级语言中,它是一个符号,可以通过给它赋予不同的值,让它在程序中参与运算,而且其命名应该遵循一定的规则,具备良好的可读性。
注意 什么是可读性?
可读性是程序设计的一个概念,表示开发者理解代码片段的难易程度。在我参加工作后,第一个项目经理说过这样一段话,让我至今印象深刻。他说:“在保证程序正确的情况下,应该尽量保证程序代码的可读性,除非你写出的代码能够提升几十倍的性能,否则就不要考虑破坏代码可读性。真正的高手写的代码应该是容易读懂的,如果写了一大堆代码,功能虽然实现了,但令人费解,那么这些就是垃圾代码,他的水平也不怎么样,而这些代码对日后的维护和扩展也是非常棘手的。”
可读性是程序编码在保证正确性的基础上的首要原则,是每个开发者都应该遵循的原则。要写出简单且容易理解的代码,就需要开发者在实践中不断地积累和探索。当然,还需要按照一定的规范编写代码,不同的公司可能存在不同的规范。本书会尽可能按照一般程序设计规范编写代码,以保证程序的可读性。
约翰·克鲁伊夫曾经说过:“踢足球非常简单,难的是踢简单的足球。”而我要说的是:“写程序非常简单,难的是写简单的程序。”
2.1.1 变量的使用
前面提及Python是一种弱类型的语言,不需要声明变量的类型。这里的变量在Python中是一个符号,可以先为其赋予不同类型的值,然后存储在内存中,如代码清单2-1所示。
代码清单2-1:变量的使用
在这段代码中,首先声明了一个变量x,接着赋值为字符串“人生苦短,我用Python”,并使用print函数将其输出;然后赋值为字符串“hello world!!”,并使用print函数将其输出;最后将其赋值为整数1,这是不同数据类型的赋值。由此说明Python是一种弱类型的语言,比较灵活。运行这段代码,可以看到以下输出结果:
在代码中,可以重新为变量赋值,而这些值都存储在内存中,所以变量的值会随着程序运行而发生变化。
2.1.2 变量的命名
在命名变量时应该遵循一些规则,这样可以有效提高程序的可读性。将两个产品的名称定义为变量,如代码清单2-2所示。
代码清单2-2:变量的命名
代码清单2-2中的两个变量为“x”和“product_name_2”。在看到“x”时,我们并不知道它表达的是什么意思,需要看到注释才能明白它代表产品1的名称。但是在看到“product_name_2”时,通过命名就可以知道它是产品2的名称。显然“product_name_2”具备更高的可读性,更容易读懂,所以应该优先选择这样的方式对变量进行命名。
在保证正确性的前提下为了提高可读性,Python中变量的命名应该遵循以下规则。
• 变量名称只能包含字符、下画线和数字,并且变量名称只允许以字母或下画线作为开头,如上述变量可以命名为“product_name_2”,不可以命名为“2_product_name”。
• 变量名之间不能存在空格,否则会引发错误,如果需要使用多个单词命名,一般以下画线“_”代替空格。
• 不要使用Python的关键字和内置函数名称命名变量,使用关键字会导致错误,使用内置函数名称会覆盖原有的内置函数,具体的关键字和内置函数的名称可以参考附录B。
• 变量名称应该简短并且可以描述其表达的含义。例如,上面命名的“product_name_2”还可以命名为“prd_name_2”,这里的“prd”是“product”的简写,但不能简写为“p_n_2”,因为这样就无法理解其表达的业务含义。
• 命名时慎用数字“1”和大写字母“O”,因为在代码中数字“1”和字母“l”与数字“0”和大写字母“O”经常是难以分辨的。
需要注意的是,在Python中变量的命名是严格区分大小写的,如变量“a”和“A”是完全不同的。建立良好的命名规则有利于自己和其他开发者对代码的阅读,一段命名糟糕的代码,在多日以后自己可能都不愿意读,其他的开发者就更难读懂。那些命名混乱的代码往往也是很难维护的,在实际开发中,这些难以维护的代码被称为垃圾代码。即使代码是正确且可运行的,也可能会被要求重写,以提高代码的可读性。
说明 其他变量的命令方法
上面介绍了Python中变量的命名方法,事实上,在程序开发中还有一种被广泛使用的驼峰式命名方法。例如,“prd_name_2”的驼峰式命名可以写成“prdName2”,可以看到第一个单词的首字母为小写,第二个单词的首字母为大写,这样一高一低,就如同驼峰一般,因此人们把这样的命名方式称为驼峰式命名。驼峰式命名也是一种可读性高的命名方法,在C/C++、Java等主流语言中广泛使用。
只是在Python中,由于早期开发库都广泛使用下画线作为多个单词的分隔符,因此Python官方也建议使用下画线作为分隔符,以保持一致。而在多个单词的命名中,应该尽可能使用小写字母进行命名,并且将下画线作为分隔符,避免使用大写字母。
2.1.3 变量的存储
在计算机中的变量是存放在内存中的,而计算机会通过地址返回变量的值。在Python解释器工作的过程中,它会创建一张表来存放变量符号及其相关内容,每个变量都存放在这张表中,并且表中还保存变量所指向的地址。在Python中存在一个内置函数id,其功能是返回变量的内存地址,下面通过代码清单2-3展开介绍。
代码清单2-3:变量存放的地址
上述代码中定义了变量a、b、c和d,其中a=b=1,运行这段代码输出的结果如下:
可以看到,a和b的地址是相同的,因为它们的值都是1。因此,有必要解释Python中变量的内存情况。
a和b在Python中都是变量符号,Python解释器在运行时会创建一张变量表来管理它们。在这张表中,除了存放变量符号,还会存放变量指向的地址,如图2-1所示。
在图2-1中,左边的变量表存放的是变量符号和指向的内存地址,这样在Python解释器的运行过程中,就可以通过指向的内存地址访问到具体的变量值。而变量a和b的值都是1,所以它们存放的内存地址是相同的,都指向了内存中的1。这里需要注意的是,在Python中,变量表存放的不是值本身,而是一个内存地址,程序可以通过这个内存地址找到它的值,把这样的变量称为引用。从这个角度来说,Python的变量都是引用,引用相当于一个别名。例如,假设有一位小伙子的名字叫作张全,他母亲叫他阿全,而隔壁邻居叫他小张,阿全和小张都是他的别名,都是指这位名为张全的小伙子。
图2-1 代码清单2-3中各个变量的存放情况
说明 引用和指针
在C/C++中,除了引用,还存在指针的概念。正如上述所言,引用相当于一个别名,多个引用可以都指向同一个对象。而指针是一个内存地址,它将直接指向内存的某个区域,这样开发者就可以通过地址来操作对象。为了追求简单和安全,很多语言(如Java和Python)就把C++中的指针进行屏蔽,这是因为指针操作起来是复杂和难以理解的,同时直接使用地址操作变量也容易失误,并且引发严重的错误,因此指针也是危险的。
在Python中修改变量只是修改变量的引用,如代码清单2-4所示。
代码清单2-4:修改变量的值
运行上述代码得到的输出结果如下:
下面用图来展示这个过程,如图2-2所示。
图2-2 修改变量的过程
变量表中x的内存地址发生了变化,最初赋值为1时,它的内存地址为140708783511200,执行代码x=100后,它的内存地址变为140708783514368,这个时候它引用的是100这个数字。而此时变量y的内存地址仍旧是140708783511200,所以内存中的1并未被删除。由此可知,修改变量只是修改内存地址指向新的对象,而不是修改对象本身。
还可以将变量删除,如代码清单2-5所示。
代码清单2-5:删除变量
这里的“del”是Python的关键字,代表删除这个变量的引用。运行上述代码得到的输出结果如下:
需要注意加粗的输出,说明变量“prd_name”没有定义,因为del关键字已经把它删除了。
注意 正确理解del关键字
del是Python的关键字,表示删除变量表的某个变量符号,而不是删除对象本身。正如代码清单2-5中,是将“prd_name”这个变量符号从变量表中删除的,这样后续就不能再使用“prd_name”这个变量符号,而“产品名称”这个字符串依旧在内存中,并未被删除,将由Python解释器进行处理。
实际上,变量还可以使用如下代码进行定义:
只是这样可读性较低,所以本书不采用这样的方式来定义和使用变量,毕竟在保证正确性的前提下,还应该保证可读性。
除此之外,还可以通过“is”或“is not”运算符来判定两个对象是否引用了同一个对象,如下所示:
运行上述代码得到的输出结果如下:
Python中存在多种数据类型,所以读者有必要进行学习,而本章只是介绍那些简单的数据类型,这是编写Python程序的基础。