对象是python语言中最基本的概念,在python中处理的一切都是对象。
python中有许多内置对象可供编程者使用,内置对象可直接使用,如数字、字符串、列表等。
非内置对象需要导入模块才能使用,如正弦函数sin(x),随机数产生函数random( )等。
在Python中,不需要事先声明变量名及其类型,直接赋值即可创建各种类型的对象变量。这一点适用于Python任意类型的对象。
赋值语句的执行过程是:首先把等号右侧表达式的值计算出来,然后在内存中寻找一个位置把值存放进去,最后创建变量并指向这个内存地址。
Python中的变量并不直接存储值,而是存储了值的内存地址或者引用,这也是变量类型随时可以改变的原因。
在Python中,允许多个变量指向同一个值,例如:
>>> x = 3
>>> id(x)
1786684560
>>> y = x
>>> id(y)
1786684560
>>> x += 6
>>> id(x)
1786684752
>>> y
3
>>> id(y)
1786684560
Python采用的是基于值的内存管理方式,如果为不同变量赋值为相同值(仅适用于-5至256的整数和短字符串),这个值在内存中只有一份,多个变量指向同一块内存地址。
>>> x = 3
>>> id(x)
10417624
>>> y = 3
>>> id(y)
10417624
>>> x = [1, 1, 1, 1]
>>> id(x[0]) == id(x[1])
True
Python属于强类型编程语言,Python解释器会根据赋值或运算来自动推断变量类型。Python还是一种动态类型语言,变量的类型也是可以随时变化的
>>> x = 3
>>> print(type(x))
<class 'int'>
>>> x = 'Hello world.'
>>> print(type(x)) #查看变量类型
<class 'str'>
>>> x = [1,2,3]
>>> print(type(x))
<class 'list'>
>>> isinstance(3, int) #测试对象是否是某个类型的实例
True
>>> isinstance('Hello world', str)
True
Python支持任意大的数字,具体可以大到什么程度仅受内存大小的限制。
由于精度的问题,对于实数运算可能会有一定的误差,应尽量避免在实数之间直接进行相等性测试,而是应该以二者之差的绝对值是否足够小作为两个实数是否相等的依据。
在数字的算术运算表达式求值时会进行隐式的类型转换,如果存在复数则都变成复数,如果没有复数但是有实数就都变成实数,如果都是整数则不进行类型转换。
>>> 9999 ** 99 #这里**是幂乘运算符,等价于内置函数pow()
990148353526723487602263124753282625570559528895791057324326529121794837894053513464422176826916433932586924386677766244032001623756821400432975051208820204980098735552703841362304669970510691243800218202840374329378800694920309791954185117798434329591212159106298699938669908067573374724331208942425544893910910073205049031656789220889560732962926226305865706593594917896276756396848514900989999
>>> 0.3 + 0.2 #实数相加
0.5
>>> 0.4 - 0.1 #实数相减,结果稍微有点偏差
0.30000000000000004
>>> 0.4 - 0.1 == 0.3 #应尽量避免直接比较两个实数是否相等
False
>>> abs(0.4-0.1 - 0.3) < 1e-6 #这里1e-6表示10的-6次方
True
>>> import math
>>> math.isclose(0.4-0.1,0.3)
True
Python内置支持复数类型及其运算,并且形式与数学上的复数完全一致
>>> x = 3 + 4j #使用j或J表示复数虚部
>>> y = 5 + 6j
>>> x + y #支持复数之间的加、减、乘、除以及幂乘等运算
(8+10j)
>>> x * y
(-9+38j)
>>> abs(x) #内置函数abs()可用来计算复数的模
5.0
>>> x.imag #虚部
4.0
>>> x.real #实部
3.0
>>> x.conjugate() #共轭复数
(3-4j)
Python 3.6.x支持在数字中间位置使用单个下划线作为分隔来提高数字的可读性,类似于数学上使用逗号作为千位分隔符。
在Python数字中单个下划线可以出现在中间任意位置,但不能出现开头和结尾位置,也不能使用多个连续的下划线。
>>> 1_000_000
1000000
>>> 1_2_3_4
1234
>>> 1_2 + 3_4j
(12+34j)
>>> 1_2.3_45
12.345
在Python中,没有字符常量和变量的概念,只有字符串类型的常量和变量,单个字符也是字符串。使用==单引号、双引号、三单引号、三双引号作为定界符(delimiter)==来表示字符串,并且不同的定界符之间可以互相嵌套。
Python 3.x全面支持中文,中文和英文字母都作为一个字符对待,甚至可以使用中文作为变量名。
>>> x = 'Hello world.' #使用单引号作为定界符
>>> x = "Python is a great language." #使用双引号作为定界符
>>> x = '''Tom said, "Let's go."''' #不同定界符之间可以互相嵌套
>>> print(x)
Tom said, "Let's go."
>>> x = 'good ' + 'morning' #连接字符串
>>> x
'good morning'
>>> x = 'good ''morning' #连接字符串,仅适用于字符串常量
>>> x
'good morning'
对str类型的字符串调用其encode()方法进行编码得到bytes字节串,对bytes字节串调用其decode()方法并指定正确的编码格式则得到str字符串。
>>> type('Hello world') #默认字符串类型为str
<class 'str'>
>>> type(b'Hello world') #在定界符前加上字母b表示字节串
<class 'bytes'>
>>> 'Hello world'.encode('utf8') #使用utf8编码格式进行编码
b'Hello world'
>>> 'Hello world'.encode('gbk') #使用gbk编码格式进行编码
b'Hello world'
>>> '烟台'.encode('utf8') #对中文进行编码
b'\xe7\x83\x9f\xe5\x8f\xb0\xe5\xa4\xa7\xe5\xad\xa6'
>>> _.decode('utf8') #一个下划线表示最后一次正确输出结果
'烟台'
>>> '烟台'.encode('gbk')
b'\xd1\xcc\xcc\xa8\xb4\xf3\xd1\xa7'
>>> _.decode('gbk') #对bytes字节串进行解码
'烟台'
>>> x_list = [1, 2, 3] #创建列表对象
>>> x_tuple = (1, 2, 3) #创建元组对象
>>> x_dict = {'a':97, 'b':98, 'c':99} #创建字典对象
>>> x_set = {1, 2, 3} #创建集合对象
>>> print(x_list[1]) #使用下标访问指定位置的元素
2
>>> print(x_tuple[1]) #元组也支持使用序号作为下标
2
>>> print(x_dict['a']) #字典对象的下标是“键”
97
>>> 3 in x_set #成员测试
True
在Python中,单个常量或变量可以看作最简单的表达式,使用除赋值运算符之外的其他任意运算符和函数调用连接的式子也属于表达式
(1)+运算符除了用于算术加法以外,还可以用于列表、元组、字符串的连接,但不支持不同类型的对象之间相加或连接。
>>> [1, 2, 3] + [4, 5, 6] #连接两个列表
[1, 2, 3, 4, 5, 6]
>>> (1, 2, 3) + (4,) #连接两个元组
(1, 2, 3, 4)
>>> 'abcd' + '1234' #连接两个字符串
'abcd1234'
>>> 'A' + 1 #不支持字符与数字相加,抛出异常
TypeError: Can't convert 'int' object to str implicitly
>>> True + 3 #Python内部把True当作1处理
4
>>> False + 3 #把False当作0处理
3
(2)*运算符除了表示算术乘法,还可用于列表、元组、字符串这几个序列类型与整数的乘法,表示序列元素的重复,生成新的序列对象。字典和集合不支持与整数的相乘,因为其中的元素是不允许重复的。
>>> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> (1, 2, 3) * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3)
>>> 'abc' * 3
'abcabcabc'
3)运算符/和//在Python中分别表示算术除法和算术求整商(floor division)。
>>> 3 / 2 #数学意义上的除法
1.5
>>> 15 // 4 #如果两个操作数都是整数,结果为整数
3
>>> 15.0 // 4 #如果操作数中有实数,结果为实数形式的整数值
3.0
>>> -15//4 #向下取整
-4
4)%运算符可以用于整数或实数的求余数运算,还可以用于字符串格式化,但是这种用法并不推荐。
>>> 789 % 23 #余数
7
>>> 123.45 % 3.2 #可以对实数进行余数运算,注意精度问题
1.849999999999996
>>> '%c, %d' % (65, 65) #把65分别格式化为字符和整数
'A, 65'
>>> '%f,%s' % (65, 65) #把65分别格式化为实数和字符串
'65.000000,65'
5)** 运算符表示幂乘:
>>> 3 ** 2 #3的2次方,等价于pow(3, 2)
9
>>> pow(3, 2, 8) #等价于(3**2) % 8
1
>>> 9 ** 0.5 #9的0.5次方,平方根
3.0
>>> (-9) ** 0.5 #可以计算负数的平方根
(1.8369701987210297e-16+3j)
Python关系运算符最大的特点是可以连用,其含义与我们日常的理解完全一致。使用关系运算符的一个最重要的前提是,操作数之间必须可比较大小。例如把一个字符串和一个数字进行大小比较是毫无意义的,所以Python也不支持这样的运算。
>>> 1 < 3 < 5 #等价于1 < 3 and 3 < 5
True
>>> import math
>>> math.isclose(0.4-0.1,0.3)
True
>>> 'Hello' > 'world' #比较字符串大小
False
>>> [1, 2, 3] < [1, 2, 4] #比较列表大小
True
>>> {1, 2, 3} < {1, 2, 3, 4} #测试是否子集
True
>>> {1, 2, 3} == {3, 2, 1} #测试两个集合是否相等
True
>>> {1, 2, 4} > {1, 2, 3} #集合之间的包含测试
False
成员测试运算符in用于成员测试,即测试一个对象是否为另一个对象的元素。
>>> 3 in [1, 2, 3] #测试3是否存在于列表[1, 2, 3]中
True
>>> 5 in range(1, 10, 1) #range()是用来生成指定范围数字的内置函数
True
>>> 'abc' in 'abcdefg' #子字符串测试
True
>>> for i in (3, 5, 7): #循环,成员遍历
print(i, end='\t')
3 5 7
同一性测试运算符is用来测试两个对象是否是同一个,如果是则返回True,否则返回False。如果两个对象是同一个,二者具有相同的内存地址。
>>> 3 is 3
True
>>> x = [300, 300, 300]
>>> x[0] is x[1] #基于值的内存管理,同一个值在内存中只有一份
True
>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> x[0] is y[0]
True
位运算符只能用于整数,其内部执行过程为:首先将整数转换为二进制数,然后右对齐,必要的时候左侧补0,按位进行运算,最后再把计算结果转换为十进制数字返回。
位与运算规则为1&1=1、1&0=0&1=0&0=0,位或运算规则为1|1=1|0=0|1=1、0|0=0,位异或运算规则为11=00=0、10=01=1。
左移位时右侧补0,每左移一位相当于乘以2;右移位时左侧补0,每右移一位相当于整除以2。
>>> 3 << 2 #把3左移2位
12
>>> 3 & 7 #位与运算
3
>>> 3 | 8 #位或运算
11
>>> 3 ^ 5 #位异或运算
集合的交集、并集、对称差集等运算借助于位运算符来实现,而差集则使用减号运算符实现(注意,并集运算符不是加号)。
>>> {1, 2, 3} | {3, 4, 5} #并集,自动去除重复元素
{1, 2, 3, 4, 5}
>>> {1, 2, 3} & {3, 4, 5} #交集
{3}
>>> {1, 2, 3} ^ {3, 4, 5} #对称差集
{1, 2, 4, 5}
>>> {1, 2, 3} - {3, 4, 5} #差集
{1, 2}
逻辑运算符and、or、not常用来连接条件表达式构成更加复杂的条件表达式,并且and和or具有惰性求值或逻辑短路的特点,当连接多个表达式时只计算必须要计算的值。
另外要注意的是,运算符and和or并不一定会返回True或False,而是得到最后一个被计算的表达式的值,但是运算符not一定会返回True或False。
>>> 3>5 and a>3 #注意,此时并没有定义变量a
False
>>> 3>5 or a>3 #3>5的值为False,所以需要计算后面表达式
NameError: name 'a' is not defined
>>> 3<5 or a>3 #3<5的值为True,不需要计算后面表达式
True
>>> 3 and 5 #最后一个计算的表达式的值作为整个表达式的值
5
>>> 3 and 5>2
True
>>> 3 not in [1, 2, 3] #逻辑非运算not
False
>>> 3 is not 5 #not的计算结果只能是True或False之一
True
>>> not 3
False
>>> not 0
True
Python还有赋值运算符=和+=、-=、*=、/=、//=、**=、|=、^=等大量复合赋值运算符。例如,x += 3在语法上等价(注意,在功能的细节上可能会稍有区别)于x = x + 3。
Python不支持++和–运算符,虽然在形式上有时候似乎可以这样用,但实际上是另外的含义,要注意和其他语言的区别。
>>> i = 3
>>> ++i #正正得正
3
>>> +(+3) #与++i等价
3
>>> i++ #Python不支持++运算符,语法错误
SyntaxError: invalid syntax
>>> --i #负负得正,等价于-(-i)
3
>>> ---i #等价于-(-(-i))
-3
>>> i-- #Python不支持--运算符,语法错误
SyntaxError: invalid syntax
Python关键字只允许用来表达特定的语义,不允许通过任何方式改变它们的含义,也不能用来做变量名、函数名或类名等标识符。