上述代码将会打印出
hello world
字符串。
Python 之中暗含这样一种期望:Python 鼓励每一行使用一句独立语句从而使得代码更加可读。
所谓物理行(Physical Line)是你在编写程序时你所看到的内容。所谓逻辑行(Logical Line)是 Python 所看到的单个语句。Python 会假定每一物理行会对应一个逻辑行。有关逻辑行的一个例子是诸如 print(‘hello world’) 这样的一行语句,如果其本身是一行(正如你在编辑器里所看到的那样),那么它也对应着一行物理行。
变量
变量(Vaiable)实质上是对内存中地址的命名,在内存中存储着诸多对象,为了方便使用这些对象,便有了变量。把变量和函数的名称我们叫作标识符(Identifier)。
变量名称
在Python中,标识符必须遵守以下规则:
所有标识符必须以字母或者下划线(
_
)开头,不能以数字开头。如 my_var 就是一个有效的标识符,而 1digit 就不是。
标识符可以包含字母、数字和下划线。标识符不限长度。
标识符不能是关键字(所谓关键字,就是Python中已经使用并有特定含义的单词)。Python的关键字参见附录Python关键字。
变量赋值
值(Value)是程序运行过程中的基本元素之一,例如1,3.14,“hello”等等都是值。在编程属于中,它们又被叫作字面量(literals)。字面量拥有不同的类型,如1是整型(int),3.14是浮点型(float),“hello”是字符串(string)。
在Python中,无需声明变量类型,解释器会根据变量的值自动判断变量类型。使用等于号为变量赋值,等于号也被认为赋值操作符(operator)。以下是变量声明的一些例子:
x = 1
y = 2
y, x = x, y # 交换x、y的值
print(x)
print(y)
查看变量类型
Python 使用内置函数 type()
来查看变量的类型。在Python中,内置了一些高效强大的对象类型,使得开发人员不用从零开始进行编程。实际上,Python中的每样东西都是对象。虽然Python中没有类型声明,但表达式的语法决定了创建和使用的对象的类型。一旦创建了一个对象,它就和操作集合绑定了,这就是所谓的动态类型和强类型语言。即Python自动根据表达式创建类型,一旦创建成功,只能对一个对象进行适合该类型的有效操作。
整型
整型(int)字面量在Python中属于int
类。
>>> i = 100
数字可以进行各种运算,如:
还可以使用数学模块进行更高级的运算,如产生随机数等等:
import
表示引入模块,import random
就是引入随机数模块。
浮点类型
浮点数(float)是指有小数点的数字。
复数
复数(Complex number)由实数和虚数两部分构成,虚数用j表示。我们可以这样定义一个复数:
让我们再看下面的例子,以便演示优先顺序的另一个问题:
上述表达式到底先进行加法运算还是减法呢?因为在运算符的优先级别表中我们看到加减运算的优先级别相同。当优先级别相同时,表达式从左向右计算,也就是说,上述的例子将先进行加法运算,再进行减法运算。
>>> 3 + 4 - 2
同级别运算符从左到右运算,这条规则有个例外,那就是赋值运算( = ),赋值运算是从右向左计算的。例如:
先将c的值,赋给b,再将b的值赋给a。
增强赋值运算符
增强赋值运算符能简化赋值声明语句,例如:
>>> count = 1
>>> count = count + 1
>>> count
使用增强赋值运算符,我们可以将上述代码变为:
>>> count = 1
>>> count += 1
>>> count
类似的增强赋值运算符,除了+=
外,还有-=
,%=
,/=
等等。
序列
序列(Sequence)是一个包含其他对象的有序集合,序列中的元素包含了一个从左到右的顺序,可以根据元素所在的位置进行存储和读取。Python中内建了6种序列,分别是列表、元组、字符串、unicode字符串、buffer对象和xrange对象。
序列作为Python的数据结构,有一些操作是通用的,如:索引、分片、加、乘以及检查某个成员是否属于序列的成员(成员资格),另外,还有一些计算长度、找到最大元素等等的内建函数。
索引
序列中的所有元素都有编号,从0开始,可以按照编号来访问序列中的元素,这个标号就是索引(indexing)。
se[0]表示序列se中的第一个元素,se[-1]表示序列中的最后一个元素。
分片
分片(Slicing)操作指的是访问序列中一定范围之内的元素。分片通过冒号相隔的两个索引来实现,第一个索引是需要提取部分的第1个元素的编号,而第二个索引是分片之后剩下部分的第1个元素的编号,第二个索引不包含在分片之中:
上述代码将打印出‘Hello’字符串。但有时,我们需要获取序列的后面几个元素,同时,序列的大小是未知的,我们可以这样写:
se[-9:]中空了第2个索引,表示一直到最后一个元素。上述代码将打印出‘Pythoner!’字符串。
进行分片时,分片的开始和结束点需要指定。而另外一个参数步长(step length)通常默认为1,当有必要时,可是指定切片的步长,如每隔1个元素就取出元素:
上述代码将打印出‘[1, 3, 5, 7, 9]’和‘[2, 4, 6, 8, 10]’,其中的步长都是2。
当然步长也可以设置为负值,这样分片会从后往前进行。
序列相加
可以通过加号能对两个相同类型的序列进行连接运算,如字符串:
上述代码将打印出‘你好yangjh’字符串。
序列相乘
序列乘以数字,表示将原有序列重复若干次:
上述代码将打印出‘你好你好你好’字符串。
空列表可以使用‘[]’来表示,但是,如果想创建有10个空元素组成的列表,就需要使用None,None是Python内建的一个值,表示什么都没有,因此,要创建含有10个空元素的列表,就可以这样:
成员资格
使用in运算符,可以检查某个元素是否存在与指定的序列中。如果元素存在于序列中,则返回True,否则返回False。
上述代码将打印出布尔值True。
长度、最小值、最大值
dir()函数可以输出对象的内置方法。如:dir(‘str’)就可以打印出所有字符串对象的内置方法。
内建函数len()可以返回序列的大小,如:
上述代码将打印出numbers
序列的长度10
和最大值以及最小值。
字符串
Python 中的字符串(Strings)是用单引号或双引号标记的一系列连续字符(characters),换句话说,字符串是由单个字符组成的序列(list)。即便只有一个字符,也是字符串,Python 中没有字符数据类型。记住单引号括起的字符串和双引号括起的字符串是一样的,它们不存在任何区别。
创建字符串
我们还可以使用下面的语法创建字符串:
字符串的不可变性
在 Python 中,每一个对象都可以分为不可变性或者可变性。在核心类型中,数字、字符串和元组是不可变的。
字符串在 Python 中一旦创建就不能就地改变,例如不能通过对其某一位置进行赋值而改变字符串。下面的语句就会出现如下语法错误:“TypeError: ‘str’ object does not support item assignment”。
关于不可变性,我们再看一个例子:
上述代码中,str1 和 str2 都指向存储在内存中某个地方的字符串对象“welcome”。我们可以通过 id() 函数来测试 str1 和 str2 是否真的指向同一个对象。
id()
函数可以得到对象在内存中的存储地址。
我们可以看到,str1 和 str2 都指向同一个内存地址,因此,他们都指向同样的对象“welcome”。下面让我们再编辑 str1 的内容看看:
我们可以看到,现在变量 str1 指向了一个完全不同的内容地址,这也说明,我们对 str1 的内容操作实际上是新建了一个新的字符串对象。
字符串操作
字符串索引开始于 0,因此,我们可以这样获取字符串的第一个字符:
>>> name = 'yangjh'
>>> name[0]
在对字符串操作时,还可以从后往前取元素:
>>> name[-1]
运算符“+”用来连接字符串,运算符“*”用来重复字符串,例如:
字符串分片
我们还可以通过“[]”操作符来获取原始字符串的子集,这就是所谓的分片。语法规则如下:
切分操作将返回字符串的部分内容,起始于 index,结束于 end-1。例如:
注意:开始索引和结束索引都是可选的,如果忽略,开始索引就是 0,而结束索引就是字符串的最后一个字符对应的索引值。
in 和 not in 操作符
我们可以使用 in 和 not in 操作符检查一个字符串是否存在于另一个字符串,in 和 not in 就是所谓的成员资格操作符(membership operator)。
String 对象的方法
下表是三个常用的字符串方法:
比较字符串
我们可以使用 ( > , < , <= , <= , == , != ) 比较两个字符串。Python 比较字符串是按照编纂字典的方式进行的,也就是使用 ASCII 编码值
假设 str1 的值为“Jane”,str2 的值为“Jake”,首先比较这两个字符串的第一个字符“J”,如果相等,就继续比较第二个字符(a 和 a),因为相同,所以继续比较第三个字符(n 和 k),因为 n 的 ASCII 编码值大于 k,因此 str1 大于 str2。更多例子参见下面的代码:
上述代码中的list函数是Python内置函数,其作用是将字符串转换为列表。
运行结果显示,通过分片赋值,将原有列表[‘P’, ‘y’, ‘t’, ‘h’, ‘o’, ‘n’],修改为[‘P’, ‘y’, ‘d’, ‘a’, ‘t’, ‘a’]。
分片赋值还可以用来插入元素,如:
结果显示将原有列表[‘P’, ‘y’, ‘t’, ‘h’, ‘o’, ‘n’],修改为[‘P’, ‘-’, ‘-’, ‘y’, ‘d’, ‘a’, ‘t’, ‘a’]。
列表对象常用内置方法
追加列表元素
。列表提供了在列表尾部追加新对象的方法append。
计数
count方法统计指定元素在列表中出现的次数,如:
>>> code = ['to', 'be', 'or', 'not', 'to', 'be']
>>> print(code.count('to'))
以上代码将统计出列表中‘to’元素出现的次数,结果为2。
合并列表
extend方法在列表的末尾一次性追加另一个序列中的多个值,如:
以上代码将把b列表追加到a列表中,打印出的a列表的值为[1, 2, 3, 4, 5, 6]。和序列加运算不同,extend方法将改变原有列表的内容,而加运算却不会。例如:
上述代码结果显示为[4, 5, 6],b列表的内容并没有改变。
元素索引
index方法用于从列表中找出指定值第一次匹配的索引值。例如:
以上代码运行结果为0,即第一个1出现的索引为0。
插入元素
insert方法用于将对象插入到列表中,例如:
运行结果为[1, 2, 2.5, 3],insert方法的两个参数值很好理解,第一个参数为在哪个元素后插入,表示位置,第二个参数为插入的内容。
pop
pop方法会移除列表中的一个元素,默认为最后一个,和append方法刚好相反,并且返回该元素的值。例如:
运行结果为3和[1, 2],当然,pop方法也可以指定移除某个索引的元素。
remove
remove方法用于移除列表中某个值的第一个匹配项:
运行结果为None和[‘to’, ‘be’, ‘not’, ‘to’, ‘be’]。这说明remove方法并不返回匹配到的内容。
reverse
reverse方法将倒序排列列表元素:
运行结果为[3, 2, 1]。
sort
sort方法用于对列表排序,如:
运行结果为:[1, 2, 3, 4, 6, 8]。需要注意的是,sort方法没有返回值,并且改变列表的内容,如果你不但要排序,而且还要保持原有数据的内容,解决的方法之一是将原有内容赋值到另外一个变量中保存。
字典
字典(Dictionary)是Python中的一种数据类型,用来存储键(key)值(value)对。字典数据能够使用键名快速取回、添加、删除、编辑值。字典和其他语言中的数组(array)或者哈希表(hash)非常相似。字典是可变(mutable)序列。
创建字典
使用花括弧 {}
就可创建字典。字典中的每一个项目都由键名、冒号:
和值组成,多个项目之间用逗号,
分割。让我们看一个实例:
friends = {
'tom' : '66666666',
'jerry' : '88888888'
上面的变量friends是一个含有两个项目的字典。需要注意的一点是,键名必须是可哈希类型,而值可以是任意类型。字典中的键名必须是唯一的。
获取、修改和添加字典元素
获取字典中的项目,使用如下语法:
如果字典中存在指定的键名,则返回对应的值,否则抛出键名异常。
添加和编辑项目,使用如下语法:
删除字典中的项目使用如下语法:
遍历字典
我们可以使用循环遍历字典中的所有项目。
字典比较
使用 ==
和 !=
操作符判断字典是否包含相同的项目。
>>> d1 = {"mike":41, "bob":3}
>>> d2 = {"bob":3, "mike":41}
>>> d1 == d2
>>> d1 != d2
False
不能使用其它的关系操作符(<
, >
, >=
, <=
)比较字典类型变量。
字典常用方法
Python提供了多个内置的方法,用来操作字典,常用方法见下表:
>>> friends = {'tom': '111-222-333', 'bob': '888-999-666', 'jerry': '666-33-111'}
>>> friends.popitem()
('tom', '111-222-333')
>>> friends.clear()
>>> friends
>>> friends = {'tom': '111-222-333', 'bob': '888-999-666', 'jerry': '666-33-111'}
>>> friends.keys()
dict_keys(['tom', 'bob', 'jerry'])
>>> friends.values()
dict_values(['111-222-333', '888-999-666', '666-33-111'])
>>> friends.get('tom')
'111-222-333'
>>> friends.get('mike', 'Not Exists')
'Not Exists'
>>> friends.pop('bob')
'888-999-666'
>>> friends
{'tom': '111-222-333', 'jerry': '666-33-111'}
字典的排序
字典的排序,可以使用sorted()函数,语法如下:
iterable
表示可以迭代的对象,例如可以是dict.items()
、dict.keys()
等;
key
是一个函数,用来选取参与比较的元素;
reverse
则是用来指定排序是倒序还是顺序,reverse=true则是倒序,reverse=false时则是顺序,默认时reverse=false。
sorted函数按key值对字典排序
直接使用sorted(d.keys())
就能按key值对字典排序,这里是按照顺序对key
值排序的,如果想按照倒序排序的话,则只要将reverse
置为true
即可。
>>> dd = {'borisakunin': 4691, 'doctor_liza': 3046, 'tareeva': 2970, 'cheger': 2887, 'karial': 2717, 'snorapp': 2707, 'masha_koroleva': 2683, 'elladkin': 2616, 'samoleg': 2597}
>>> sorted(dd.keys())
['borisakunin', 'cheger', 'doctor_liza', 'elladkin', 'karial', 'masha_koroleva', 'samoleg', 'snorapp', 'tareeva']
>>> sorted(dd.keys(),reverse=True)
['tareeva', 'snorapp', 'samoleg', 'masha_koroleva', 'karial', 'elladkin', 'doctor_liza', 'cheger', 'borisakunin']
sorted函数按value值对字典排序
要对字典的value排序则需要用到key参数,常使用lambda表达式的方法,如下:
>>> sorted(dd.items(),key=lambda item:item[1])
[('samoleg', 2597), ('elladkin', 2616), ('masha_koroleva', 2683), ('snorapp', 2707), ('karial', 2717), ('cheger', 2887), ('tareeva', 2970), ('doctor_liza', 3046), ('borisakunin', 4691)]
>>> sorted(dd.items(),key=lambda item:item[1],reverse=True)
[('borisakunin', 4691), ('doctor_liza', 3046), ('tareeva'
, 2970), ('cheger', 2887), ('karial', 2717), ('snorapp', 2707), ('masha_koroleva', 2683), ('elladkin', 2616), ('samoleg', 2597)]
这里的dd.items()
实际上是将dd
转换为可迭代对象,items()
方法将字典的元素转化为了元组,而这里key
参数对应的lambda
表达式的意思则是选取元组中的第二个元素作为比较对象,如果写作key=lambda item:item[0]
的话则是选取第一个元素作为比较对象,也就是key
值作为比较对象。
注意排序函数sorted()
返回值是一个list
,而原字典中的名值对被转换为了list
中的元组。
元组相关方法
元组也是序列,因此序列能使用的方法,如max , min , len , sum方法元组也能使用。
在第一次循环时,值 1 被传递给 i,第二次循环时,值 2 被传递给 i。循环一直到列表变量 mylist 没有更多元素时停止。运行结果为:
范围循环
range() 函数能够指定循环的起始值和结束值,从而让循环体在指定的范围内循环。例如:
range() 函数只有 1 个参数时,表示从 0 开始循环;两个参数时,第一个参数是起始值,第二个参数是结束值;三个参数时,第三个参数表示循环步长。
while 循环
While 循环会一直执行循环体内部的声明,直到条件变成 false。每次循环都会检查判断条件,如果为真,就继续循环。例如:
这段代码将会打印出 0-9,直到 count 等于 10。
中断循环
使用 break 语句,可以中断循环,例如:
运行结果为:
继续循环
当循环体内部出现 continue 声明时,会结束本次循环,跳转到循环体开始位置,开始下一次循环。例如:
运行结果将打印出 1,3,5,7,9。
Python使用def关键词创建函数,语法如下:
空白区在 Python 中十分重要。实际上,空白区在各行的开头非常重要。这被称作缩进(Indentation)。在逻辑行的开头留下空白区(使用空格或制表符)用以确定各逻辑行的缩进级别,而后者又可用于确定语句的分组。
这意味着放置在一起的语句必须拥有相同的缩进。每一组这样的语句被称为块(block)。有一件事你需要记住:错误的缩进可能会导致错误。
所有在函数内部的声明,都必须使用相等的缩进。函数可以没有参数,也可以有多个参数。多个参数之间用逗号隔开。还可以使用pass关键字忽略掉函数主题的声明。
我们看一个函数的例子,下面的函数将计算指定范围的整数之和:
在上面的代码中,我们定义了一个叫作sum()
的函数,该函数有两个参数(start
和end
),该函数将从start
开始,累加到end
,最后打印出累积之和。代码运行的结果为55。
函数返回值
上文定义的函数只是简单地在控制台打印出结果,如果我们想要将计算结果赋值给变量,以便做更深入的处理时应该怎么办?当我们遇到这种情况时,可使用return
语句,将返回函数计算结果并且退出函数。例如:
在上面这段代码中,我们定义了有返回值的函数sumReturn()
,并将其结果赋值给变量a
。上面代码的运行结果为15。
当然,return语句也可以不返回值,而是用来退出函数(实际上会返回None,为NoneType对象)。每一个函数都在其末尾隐含了一句 return None,除非你写了你自己的 return 语句。
上述代码的运行结果如下:
在Python中,如果你不指定return的返回值,则会返回None值。
全局变量和局域变量
全局变量指的是不属于任何函数,但又可以在函数内外访问的变量。而局域变量指的是在函数内部声明的变量,局域变量只能在函数内部使用,无法在函数外访问(函数执行完后,会销毁内部定义的局部变量)。
下面我们通过例子来演示这两者的区别:
上述代码将会出现错误:
我们再看一个例子:
该代码显示的结果是200,不是100。
使用global
关键字,可以将局部变量同全局变量绑定在一起。例如:
使用global
关键字声明全局变量时,无法直接赋值,比如“global t = 1”的写法存在语法错误。
参数的默认值
为参数指定默认值,只需在定义函数时使用赋值语句即可。例如:
上述定义的函数func()有两个参数i和j。j的默认值为100,这意味着我们在调用这个函数的时候可以忽略掉j的值,比如func(2),运行结果为2 100。
关键字参数
为函数传递参数值的方法有两种:位置参数和关键字参数。我们之前调用函数的时候都使用的是位置参数。下面我们看如何使用关键字参数:
上述代码运行结果都是“hello jim”。
关键字参数使用“name=value”的名称、值对传递数据,正如上面代码演示的那样,使用关键字参数的时候,参数的顺序是可以调换的,而且位置参数和关键字参数可以混合使用(只能先使用位置参数,后使用关键字参数)。
返回多个值
我们可以通过在return语句中使用逗号,将多个值返回,这种返回值的类型是元组。例如:
运行结果为:
函数文档字符串
Python 有一个甚是优美的功能称作文档字符串(Documentation Strings),在称呼它时通常会使用另一个短一些的名字docstrings。DocStrings 是一款你应当使用的重要工具,它能够帮助你更好地记录程序并让其更加易于理解。令人惊叹的是,当程序实际运行时,我们甚至可以通过一个函数来获取文档!
该文档字符串所约定的是一串多行字符串,其中第一行以某一大写字母开始,以句号结束。第二行为空行,后跟的第三行开始是任何详细的解释说明。强烈建议你的文档字符串中都遵循这一约定。
我们可以通过使用函数的 __doc__
(注意其中的双下划线)属性(属于函数的名称)来获取函数 print_max 的文档字符串属性。
lambda表达式
Lambda表达式(或者Lambda形式)用来创建匿名函数。语法如下:
个人认为,lambda 是为了减少单行函数的定义而存在的,能够提高代码的简洁性。比如:
*args
和 **kwargs
*args
和**kwargs
是两个魔法变量。那么它们到底是什么? *args
和 **kwargs
主要用于函数定义。 你可以将不定数量的参数传递给一个函数。
首先,并不是必须写成*args
和**kwargs
。 只有变量前面的 *(星号)
才是必须的. 你也可以写成*var
和**vars
。而写成*args
和**kwargs
只是一个通俗的命名约定。
*args
的用法
*args
是用来发送一个非键值对的可变数量的参数列表给一个函数.
这里有个例子帮你理解这个概念:
这会产生如下输出:
**kwargs
的用法
**kwargs
允许你将不定长度的键值对, 作为参数传递给一个函数。 如果你想要在一个函数里处理带名字的参数, 你应该使用**kwargs
。
这里有个让你上手的例子:
现在你可以看出我们怎样在一个函数里, 处理了一个键值对参数了。
使用 *args
和 **kwargs
来调用函数
那现在我们将看到怎样使用*args
和**kwargs
来调用一个函数。 假设,你有这样一个小函数:
你可以使用*args
或**kwargs
来给这个小函数传递参数。 下面是怎样做:
标准参数与*args
、**kwargs
在使用时的顺序
如果你想在函数里同时使用所有这三种参数, 顺序是这样的:
参考资料
Python进阶