Python基本语法

2015/04/03 Python

Python基本语法

Python语法简单、优雅,如同阅读英语一般,即使是非科班出身的用户,也能很快理解Python语句的含义。

变量

有计算机基础的读者都知道,计算机在工作过程中所产生的数据都是在内存中存储和读取的。内存类似于工厂的仓库,数据作为零件存储在仓库(内存)中不同的地方。仓库那么大,怎样才能快速找到这些零件(数据)呢?我们可以给每个零件贴上“标签”,根据标签名称,就可以找到它们了。 这些标签,就是传说中的“变量”。使用“变量”可以快速定位数据、操作数据。

变量(variable)是程序设计语言中最基本的角色,也就是在程序设计中由编译程序分配的一块具有名称的内存单元,用来存储可变动的数据内容。

Python是面向对象的语言,所有的数据都看成是对象,在变量的处理上也是用对象引用(Object reference)的方法,变量的类型是在赋予初始值时决定的,所以不需要事先声明数据类型。变量的值是使用“=”来赋值的。 声明变量的语法如下:

变量名称 = 变量值

比如,存储同学cathy的个人信息:

name = "cathy"                                          # 变量名name,存储姓名
age = 10                                                # 变量名age,存储年龄
height = 138.5                                          # 变量名height,存储身高
is_student = True                                       # 变量名is_student,存储是否是学生的标记
score1 = None                                           # 变量名score1,存储成绩
  • 变量名包含英文、数字及下划线,但不能以数字开头。后续字符可以搭配其他的大小写英文字母、数字、下画线“_”或中文,不能使用空格符。
  • =用来给变量赋值,如变量name的值为cathy。
  • 变量在使用前必须赋值。
  • #代表行内注释。
  • 不能使用Python内建的保留字(或称为关键字)。

数据类型

Python的基本数据类型包括整数、浮点数、布尔型和字符串,并提供了int类、float类、bool类和str类这四个内置类与之相对应。这也体现了Python“万物皆对象”的特点。

可以使用type()函数查看一个变量的类型。比如查看同学cathy的各个变量的类型:

type(name)                                              # 字符串:<class 'str'>
type(age)                                               # 整数:<class 'int'>
type(height)                                            # 浮点数:<class 'float'>
type(is_student)                                        # 布尔型:<class 'bool'>
type(score1)                                            # NoneType:<class 'NoneType'>
  • 注释中的尖括号是执行type()函数后输出的结果。
  • 结果中的class意味着Python中一切皆对象,后面会讲到。
  • score1的类型是NoneType,不是0,也不是空。很多情况下,API执行失败会返回None。
  • 变量不需要声明类型,Python会自动识别。

整型

整型数据就是数学上的整数,包括正整数、负整数和零。Python的整型不像C语言和C++语言那样分了长短很多种,几乎不用担心整数超过系统限制。

下面这个计算阶乘的函数,很容易就算出了100的阶乘,其结果位数长达158位。

def factorial(n):
        if n == 0:
            return 1
        return n*factorial(n-1)
factorial(100)      

有时为了可读性的需要,我们可以使用不同的数字系统来表示整数值,例如存储数据的内存地址就经常是以十六进制来表示的。整数包含正整数或负整数,除了用十进制(decimal)来表示外,也可以用二进制(binary)、十六进制(hexadecimal)、八进制(octal)来表示,只要分别在数字之前加上0b、0x、0o指定进制系统即可。

浮点型

天地茫茫,宇宙无限,星际距离动辄以万亿公里计;然而若专注于微观世界,人类认知已经进入了纳米范围。如果使用定点数表示如此巨大的动态范围,势必耗费大量的存储资源,因此浮点数就应运而生了。所谓浮点数,简单理解就是科学记数法。

浮点数(floating point)数据类型指的是带有小数点的数字,也就是数学上所指的实数(real number)。除了一般小数点的常规表示方法外,也可以使用科学记数法以指数形式表示,例如6e-2,其中6称为有效数,-2称为指数。 浮点型数据既可以表示很大的数,也可以表示很小的数。精度是浮点型数据最重要的指标,也最容易出问题。Python的浮点数为双精度浮点数,使用8字节、共64位表示一个浮点数,其中符号占1位,指数占11位,尾数占52位。 Python的浮点型数据精度很高,足以满足一般需求。如果对精度有要求,decimal模块可以提供更高的计算精度。

>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3 # 判断浮点数是否相等,需要留心此类意外情况
False

以上代码演示了因为精度问题导致浮点数计算出现的意外情况。不只Python如此,所有浮点数规范遵从IEEE754二进制浮点数算术标准(ANSI/IEEE Std 754-1985)的编程语言,如C语言,都会如此。如果想在C语言环境中验证,需要使用double类型。

  • 使用decimal模块进行小数运算 decimal模块是Python标准模块库,使用它之前需要先用import指令导入这个模块,而后才能使用。正确导入这个模块之后,我们就可以使用decimal.Decimal类来存储精确的数字,如果参数为非整数,就必须以字符串形式传入参数,例如:
    import decimal
    num = decimal.Decimal("0.1") + decimal.Decimal("0.2")
    

    这样运算后得到的结果就会是0.3。

  • 使用round()函数强制小数点的指定位数 round(x[,n])是内建函数,会返回参数x最接近的数值,n用来指定返回的小数点位数,例如:
    num =  0.1 + 0.2
    print( round(num, 1) )
    

    上面的程序语句是将变量num取到小数点后1位,因此会得到0.3的结果。

布尔型

布尔数据类型(bool)是一种表示逻辑的数据类型,是int的子类,只有真值(True)与假值(False)。布尔数据类型通常用于程序流程控制中的逻辑判断。Python语言定义了两个常量True和False,用来表示布尔型的真和假。True表示真、非空、非零等概念,False表示假、空、零等概念。

>>> bool(0)
False
>>> bool(None)
False
>>> bool('')
False
>>> bool([])
False
>>> bool(5)
True
>>> bool('x')
True
>>> bool([False])
True

字符串

字符串是Python语言的处理对象之一。Python将单引号(’)、双引号(”)、三引号(’'’或””“)前后封闭起来的字符集视为字符串对象,并提供了一系列处理方法。字符串里可以包含数字、字母和符号。

下面都是Python合法的字符串的例子。

>>> '人生苦短,我用Python'
'人生苦短,我用Python'
>>> "人生苦短,我用Python"
'人生苦短,我用Python'
>>> '''人生苦短,我用Python'''
'人生苦短,我用Python'
>>> """人生苦短,我用Python"""
'人生苦短,我用Python'

在Python语言中,必须是相同的数据类型才能直接进行运算,例如字符串与整数不能直接相加,必须将字符串转换为整数,如果参加运算的都是数值类型,那么Python会自动进行类型转换,而不需要指定强制转换类型,例如:

num = 5 + 0.3   #结果num=5.3 (浮点数)

Python会自动将整数转换为浮点数再进行运算。另外,布尔值也可以当成数值来运算,True代表1,False代表0,例如:

num = 5 + True  #结果num=6 (整数)

如果想把字符串转换为布尔值,可以通过bool函数来进行转换。

常数

常数是指程序在整个执行过程中不能被改变的数值。例如整数常数:45、-36、10005、0等,或者浮点数常数:0.56、-0.003、1.234E2,等等。常数拥有固定的数据类型和数值。变量(variable)与常数(constant)最大的差异在于变量的内容会随着程序的执行而改变,常数则固定不变。

Python的常数是指字面常数(literal),也就是该常数字面上的意义,例如12就代表整数12。所谓字面常数,就是直接写进Python程序的数值。字面常数如果按数据类型来区分,会有不同的分类,例如:1234、65、963、0都是整数字面常数(integer literal)。而带小数点的数值则为浮点数类型(floating-point type)的字面常数,例如3.14、0.8467、744.084。至于以单引号(’)或双引号(”)引起来的字符都是字符串字面常数(string literal),例如”Hello World”、”0932545212”都是字符串字面常数。

表达式与运算符

计算机主要的特点之一就是具有强大的计算能力,把从外界得到的数据输入计算机,并通过程序来进行运算,最后输出所要的结果。

算术运算符

算术运算符(Arithmetic Operator)是程序设计语言中使用率最高的运算符,常用于一些四则运算,像加法运算符、减法运算符、乘法运算符、除法运算符、余数运算符、整除运算符、指数运算符等。+、-、*和/运算符与我们常用的数学运算方法相同,而正负号运算符主要用于表示操作数的正/负值,通常设置常数为正数时可以省略+号,例如“a=5”与“a=+5”的含义是相同的。特别要提醒大家的是,因为负数也是使用“-”运算符来表示的,当负数参与减法运算时,为了避免与减法运算符混淆,最好用小括号“()”分隔开负数。

“/”与“//”都是除法运算符,“/”的运算结果是浮点数,“//”则会将除法计算结果中的小数部分去掉,只取整数,“%”运算符是求余数,例如:

a = 5
b = 2
print(a / b)    #结果为浮点数2.5
print(a // b)   #结果为整数2
print(a % b)    #结果为余数1

如果运算的结果并不赋值给其他变量,那么运算结果的数据类型将以操作数中数据类型占用内存空间最大的变量为主。另外,当操作数都为整数且运算结果会产生小数时,Python会自动以小数方式输出结果,我们无须担心数据类型的转换问题。

但是,如果运算结果要赋值给某个变量,那么该变量占用的内存空间必须足够大,以避免运算结果数据过长的部分被舍去。例如运算的结果为浮点数,而被赋值给整数变量,那么运算结果的小数部分将被舍去。

算术运算符中的除法“/”运算符是常规的除法,经运算后所求的商数是浮点数,如果要将该商数以整数表示,那么可以调用int()函数。

int(15/7)   #输出2

“**”是乘幂运算,例如要计算2的4次方:

print(2 ** 4)   #结果为16

注意,算术运算符+、-、*和/的优先级为“先乘除后加减”,下面举例说明:

5+2*3

上式的运算结果是11。

在表达式中,括号的优先级高于乘除,如果上式改为(5+2)*3的话,运算结果就会是21。如果遇到相同优先级的运算符,那么按照从左到右的顺序来运算。

赋值运算符

赋值运算符“=”至少由两个操作数组成,功能是将“=”号右边的值赋给等号左边的变量。许多程序设计语言的初学者最不能理解的就是等号“=”在程序设计语言中的含义,很容易将它和数学上的等于功能混淆。在程序设计语言中,“=”号主要用于赋值,而我们从数学角度来理解,“=”以往都认为是“等于”的概念。

例如下面的程序语句:

sum = 0;
sum = sum + 1;

上述程序语句中的sum=0还容易理解其所代表的意义,但是对于sum=sum+1这条语句,许多初学者往往无法想通这条语句所代表的含义。

其实Python程序设计语言中的“=”主要用于“赋值”(assignment),我们可以想象:当声明变量时会分配内存并安排好内存的地址,等到使用赋值运算符“=”把具体的数值设置给这个变量时,才会让这个内存地址对应的内存空间来存储这个具体的数值。也就是说,sum=sum+1可以看成是将sum内存地址中存储的原数据值加1后的结果,再重新赋值给sum内存地址对应的内存空间。

在赋值运算符“=”的右侧可以是常数、变量或表达式,最终都将把值赋给左侧的变量;而运算符左侧只能是变量,不能是数值、函数或表达式等。例如,表达式X-Y=Z就是不合法的程序语句。

Python赋值运算符有两种赋值方式,即单一赋值和复合赋值。

  • 单一赋值 将赋值运算符“=”右侧的值赋给左侧的变量,例如:
    a = 10
    

    赋值运算符除了一次赋一个数值给变量外,还能够同时将同一个数值赋给多个变量。如果要让多个变量同时具有相同的变量值,我们就可以一起赋予变量值。

例如,想让变量x、y、z的值都为100,赋值语句可以如下编写:

x = y = z = 100

当我们想要在同一行程序语句中给多个变量赋值时,可以使用“,”分隔变量。例如,要让变量x的值为10,变量y的值为20,变量z的值为30,编写赋值语句如下:

x, y, z =10, 20, 30

Python还允许在一行里以“;”来连续编写几条不同的程序语句,分隔不同的表达式。例如以下两行程序代码:

sum = 10
index = 12

可以使用“;”将上述两行语句写在同一行。请看以下示范:

Sum = 10; index = 12        #在一行里以分号串接两条程序语句或表达式
  • 复合赋值 复合赋值运算符是由赋值运算符“=”与其他运算符结合而成的。先决条件是“=”右侧的源操作数必须有一个和左边接收赋值的操作数相同,如果一个表达式含有多个复合赋值运算符,那么运算过程必须从右侧开始,逐步进行到左侧,例如:
    a += 1     #相当于a = a + 1
    a -= 1      #相当于a = a - 1
    

    以“A+=B;”复合赋值语句为例,它是赋值语句“A=A+B;”的精简写法,也就是先执行A+B的计算,接着将计算结果赋值给变量A。表3-2中除了第一个“=”运算符以外,其他赋值运算符都是复合赋值运算符。

在Python中,单个等号“=”表示赋值,连续两个等号“==”才是关系比较运算符的“相等”,不可混用。

注意,使用赋值运算符时,如果要将一个变量赋值给另一个变量,第一个变量必须先设置初值,否则就会出现错误。 例如num=num*10,因为还没为num变量赋初值,如果直接使用赋值运算符,就会出现错误,因为num变量没有被设置过任何初值。接下来是赋值运算符综合应用的范例程序。

比较运算符

比较运算符也被称为关系运算符,用来判断条件表达式左右两侧的操作数是否相等、大于或小于。当使用关系运算符时,所运算的结果有成立或者不成立两种,对应布尔值的True或者False。

如果表达式成立,就会得到“真”(True),不成立会得到“假”(False)。

比较运算符也可以串联使用,例如a<b<=c相当于a<b,而且b<=c。注意,表示相等关系使用两个连续的等号“==”,而单个等号“=”表示的是赋值运算符,前文已经再三强调,这种差距很容易造成编写程序代码时的疏忽,日后调试程序时,这可是非常热门的小“Bug”。

# -*- coding: utf-8 -*-
"""
比较运算符练习
"""
a = 56
b = 24
c = 38
num1 = (a == b)  #判断a是否等于b
num2 = (b != c)  #判断b是否不等于c
num3 = (a >= c)  #判断a是否大于等于c
print('a是否等于b: ',num1) #将num1显示出来
print('b是否不等于c: ',num2) #将num2显示出来
print('a是否大于等于c: ',num3) #将num3显示出来

逻辑运算符

逻辑运算符(Logical Operator)用来判断基本的逻辑运算,可控制程序运行的流程。逻辑运算符经常与关系运算符配合使用,运算的结果仅有“真”(True)与“假”(False)两种值。逻辑运算符包含and、or、not等。

  • 逻辑and(与) 逻辑and必须左右两个操作数都成立,运算结果才为真,任何一边为假(False)时,执行结果都为假。例如下面的指令的逻辑运算结果为真:
    a = 10
    b = 20
    a < b and a != b  #True
    
  • 逻辑or(或) 逻辑or只要左右两边的操作数中的任何一个成立,运算结果就为真,例如下面的逻辑运算为真:
    a = 10
    b = 20
    a < b or a == b  #True
    

    左边的式子a<b成立,运算结果就为真,不需要再判断右边的关系比较表达式。

  • 逻辑not(非) 逻辑not是逻辑否定,用法稍微不一样,只有1个操作数就可以运算,它加在操作数左边,当操作数为真时,not运算结果为假;当操作数为假时,not运算结果为真。例如下面的逻辑运算结果为真:
    a = 10
    b = 20
    not a<5  #True
    

    原本a<5不成立(结果为假),前面加一个not就否定了,所以运算结果为真。

补充说明一点,在Python程序设计语言中,当使用and、or运算符进行逻辑运算时,会采用所谓的“短路运算”(Short-Circuit)。我们以and运算符为例来说明,短路运算的判断原则是,如果第一个操作数返回True,才会继续第二个运算的判断,也就是说,如果第一个操作数返回False,就不需要再往下判断了,这样可以加快程序的执行速度,例如:

print (15>8) and (58>35)  #第一个运算结果返回True,会继续往下判断

另外,如果短路运算应用于or运算符,当第一个操作数返回False时,才会接着进行第二个操作数的判断。但是,如果第一个操作数返回True,就不需要再往下判断了,同样可以加快程序的执行速度。

位运算符

计算机在底层实际处理的数据其实只有0与1两种,也就是采取二进制形式,二进制的每一个位(bit)也称为比特。因此,我们可以使用位运算符(bitwise operator)来进行位与位之间的逻辑运算。

位逻辑运算符特别针对整数中的位值进行计算。在Python语言中提供了4种位逻辑运算符,分别是&、 、^与~
  • &(AND,位逻辑“与”运算符) 执行AND运算时,对应的两个二进制位都为1,运算结果才为1,否则为0。

例如,a=12,b=38,则a&b得到的结果为4,因为12的二进制表示法为0000 1100,38的二进制表示法为0010 0110,两者执行AND运算后,结果为十进制的4

  • ^(XOR,位逻辑“异或”运算符) 执行XOR运算时,对应的两个二进制位其中任意一个为1(true),运算结果即为1(true),不过当两者同时为1(true)或0(false)时,结果为0(false)。

例如a=12,b=38,则a^b得到的结果为42

  • |(OR) 执行OR运算时,对应的两个二进制位其中任意一个为1,运算结果为1,也就是只有两个都为0时,结果才为0。

例如a=12,b=38,则a|b得到的结果为46

  • ~(NOT) NOT的作用是取1的补码,即所有二进制位取反,也就是所有位的0与1互换。

例如a=12,二进制表示法为0000 1100,取补码后,由于所有位的0与1都会进行互换,因此运算后的结果为-13

位位移运算符

位位移运算符将整数值的二进制各个位向左或向右移动指定的位数。Python语言提供了两种位位移运算符

  • «(左移运算符)

左移运算符(«)可将操作数向左移动n位,左移后超出存储范围的位舍去,右边空出的位则补0。语法格式如下:

a<<n

例如,表达式“12«2”,数值12的二进制值为00001100,向左移动2位后成为00110000,也就是十进制的48

  • (右移运算符) 右移运算符(»)与左移运算符相反,可将操作数内容右移n位,右移后超出存储范围的位舍去。留意这时右边空出的位,如果这个数值是正数,就补0,负数则补1。语法格式如下:

    a>>n
    

    例如,表达式“12»2”,数值12的二进制值为00001100,向右移动2位后成为00000011,也就是十进制的3

运算符的优先级

一个表达式中往往包含许多运算符,运算符优先级会决定程序执行的顺序,这对执行结果有重大影响,不可不慎。如何安排运算符彼此间执行的先后顺序呢?这时需要按照优先级来建立运算规则。当表达式使用超过一个运算符时,例如z=x+3*y,就必须考虑运算符的优先级。这个表达式会先执行3*y的运算,再把运算结果与x相加,最后才会将相加的结果赋值给z。记得我们小时候上数学课时,最先背诵的口诀就是“先乘除,后加减”,这就是优先级的基本概念。

当我们遇到一个Python的表达式时,首先区分出运算符与操作数,接下来按照运算符的优先级进行整理。例如,当表达式中有超过一种运算符时,会先执行算术运算符,其次是比较运算符,最后才是逻辑运算符。比较运算符的优先级都是相同的,会从左到右按序执行,而不同的算术运算符和逻辑运算符则有优先级的差别。

当然也可以使用“()”括号来改变优先级。最后从左到右考虑运算符的结合性,也就是遇到相同优先等级的运算符会从最左边的操作数开始处理。括号运算符拥有最高的优先级,需要先执行的运算就加上括号“()”,括号“()”内的表达式会优先执行,例如:

x = 100 * (90 - 30 + 45)

上面的表达式中有5个运算符:=、、-和+,根据运算符优先级的规则,括号内的运算会先执行,优先级为-、+、、=。

运算符优先级的综合应用

# -*- coding: utf-8 -*-
"""
运算符优先级的综合应用
"""
x = 2; y = 3
z = 9*(21/x + (9+x)/y)
print("x=", x)
print("y=", y)
print("9*(4/x + (9+x)/y)=", z)

Search

    微信好友

    博士的沙漏

    Table of Contents