添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

2.1 注释

在 Python 中,使用 # 标记注释。注释不会被 Python 解释器执行。注释是开发人员用来提醒自己或他人程序如何工作的重要手段,注释还会用在文档的写作中。

上述代码将会打印出 hello world 字符串。

Python 之中暗含这样一种期望:Python 鼓励每一行使用一句独立语句从而使得代码更加可读。

所谓物理行(Physical Line)是你在编写程序时你所看到的内容。所谓逻辑行(Logical Line)是 Python 所看到的单个语句。Python 会假定每一物理行会对应一个逻辑行。有关逻辑行的一个例子是诸如 print(‘hello world’) 这样的一行语句,如果其本身是一行(正如你在编辑器里所看到的那样),那么它也对应着一行物理行。

2.2 变量

变量(Vaiable)实质上是对内存中地址的命名,在内存中存储着诸多对象,为了方便使用这些对象,便有了变量。把变量和函数的名称我们叫作标识符(Identifier)。

2.2.1 变量名称

在Python中,标识符必须遵守以下规则:

  • 所有标识符必须以字母或者下划线( _ )开头,不能以数字开头。如 my_var 就是一个有效的标识符,而 1digit 就不是。
  • 标识符可以包含字母、数字和下划线。标识符不限长度。
  • 标识符不能是关键字(所谓关键字,就是Python中已经使用并有特定含义的单词)。Python的关键字参见附录Python关键字。
  • 2.2.2 变量赋值

    值(Value)是程序运行过程中的基本元素之一,例如1,3.14,“hello”等等都是值。在编程属于中,它们又被叫作字面量(literals)。字面量拥有不同的类型,如1是整型(int),3.14是浮点型(float),“hello”是字符串(string)。

    在Python中,无需声明变量类型,解释器会根据变量的值自动判断变量类型。使用等于号为变量赋值,等于号也被认为赋值操作符(operator)。以下是变量声明的一些例子:

    注意,变量x中并不储存100自身,它存储的是100(它是一个整型对象)的引用(reference)地址。

    2.2.3 同步赋值

    Python可以使用以下语法对多个变量同步赋值:

    上述声明告诉Python,将表达式右边的值依次赋值给表达式左侧的变量。同步赋值在要交换两个变量的值时非常有用。例如:

    x = 1
    y = 2
    y, x = x, y # 交换x、y的值
    print(x)
    print(y)
    

    2.3.1 查看变量类型

    Python 使用内置函数 type()来查看变量的类型。在Python中,内置了一些高效强大的对象类型,使得开发人员不用从零开始进行编程。实际上,Python中的每样东西都是对象。虽然Python中没有类型声明,但表达式的语法决定了创建和使用的对象的类型。一旦创建了一个对象,它就和操作集合绑定了,这就是所谓的动态类型和强类型语言。即Python自动根据表达式创建类型,一旦创建成功,只能对一个对象进行适合该类型的有效操作。

    2.3.2 整型

    整型(int)字面量在Python中属于int类。

    >>> i = 100
    

    数字可以进行各种运算,如:

    还可以使用数学模块进行更高级的运算,如产生随机数等等:

    import表示引入模块,import random就是引入随机数模块。

    2.3.3 浮点类型

    浮点数(float)是指有小数点的数字。

    2.3.4 复数

    复数(Complex number)由实数和虚数两部分构成,虚数用j表示。我们可以这样定义一个复数:

    让我们再看下面的例子,以便演示优先顺序的另一个问题:

    上述表达式到底先进行加法运算还是减法呢?因为在运算符的优先级别表中我们看到加减运算的优先级别相同。当优先级别相同时,表达式从左向右计算,也就是说,上述的例子将先进行加法运算,再进行减法运算。

    >>> 3 + 4 - 2
    

    同级别运算符从左到右运算,这条规则有个例外,那就是赋值运算( = ),赋值运算是从右向左计算的。例如:

    先将c的值,赋给b,再将b的值赋给a。

    2.4.2 增强赋值运算符

    增强赋值运算符能简化赋值声明语句,例如:

    >>> count = 1
    >>> count = count + 1
    >>> count
    

    使用增强赋值运算符,我们可以将上述代码变为:

    >>> count = 1
    >>> count += 1
    >>> count
    

    类似的增强赋值运算符,除了+=外,还有-=%=/= 等等。

    2.5 序列

    序列(Sequence)是一个包含其他对象的有序集合,序列中的元素包含了一个从左到右的顺序,可以根据元素所在的位置进行存储和读取。Python中内建了6种序列,分别是列表、元组、字符串、unicode字符串、buffer对象和xrange对象。

    序列作为Python的数据结构,有一些操作是通用的,如:索引、分片、加、乘以及检查某个成员是否属于序列的成员(成员资格),另外,还有一些计算长度、找到最大元素等等的内建函数。

    2.5.1 索引

    序列中的所有元素都有编号,从0开始,可以按照编号来访问序列中的元素,这个标号就是索引(indexing)。

    se[0]表示序列se中的第一个元素,se[-1]表示序列中的最后一个元素。

    2.5.2 分片

    分片(Slicing)操作指的是访问序列中一定范围之内的元素。分片通过冒号相隔的两个索引来实现,第一个索引是需要提取部分的第1个元素的编号,而第二个索引是分片之后剩下部分的第1个元素的编号,第二个索引不包含在分片之中:

    上述代码将打印出‘Hello’字符串。但有时,我们需要获取序列的后面几个元素,同时,序列的大小是未知的,我们可以这样写:

    se[-9:]中空了第2个索引,表示一直到最后一个元素。上述代码将打印出‘Pythoner!’字符串。

    进行分片时,分片的开始和结束点需要指定。而另外一个参数步长(step length)通常默认为1,当有必要时,可是指定切片的步长,如每隔1个元素就取出元素:

    上述代码将打印出‘[1, 3, 5, 7, 9]’和‘[2, 4, 6, 8, 10]’,其中的步长都是2。 当然步长也可以设置为负值,这样分片会从后往前进行。

    2.5.3 序列相加

    可以通过加号能对两个相同类型的序列进行连接运算,如字符串:

    上述代码将打印出‘你好yangjh’字符串。

    2.5.4 序列相乘

    序列乘以数字,表示将原有序列重复若干次:

    上述代码将打印出‘你好你好你好’字符串。

    空列表可以使用‘[]’来表示,但是,如果想创建有10个空元素组成的列表,就需要使用None,None是Python内建的一个值,表示什么都没有,因此,要创建含有10个空元素的列表,就可以这样:

    2.5.5 成员资格

    使用in运算符,可以检查某个元素是否存在与指定的序列中。如果元素存在于序列中,则返回True,否则返回False。

    上述代码将打印出布尔值True。

    2.5.6 长度、最小值、最大值

    dir()函数可以输出对象的内置方法。如:dir(‘str’)就可以打印出所有字符串对象的内置方法。

    内建函数len()可以返回序列的大小,如:

    上述代码将打印出numbers序列的长度10和最大值以及最小值。

    2.6 字符串

    Python 中的字符串(Strings)是用单引号或双引号标记的一系列连续字符(characters),换句话说,字符串是由单个字符组成的序列(list)。即便只有一个字符,也是字符串,Python 中没有字符数据类型。记住单引号括起的字符串和双引号括起的字符串是一样的,它们不存在任何区别。

    2.6.1 创建字符串

    我们还可以使用下面的语法创建字符串:

    2.6.2 字符串的不可变性

    在 Python 中,每一个对象都可以分为不可变性或者可变性。在核心类型中,数字、字符串和元组是不可变的。

    字符串在 Python 中一旦创建就不能就地改变,例如不能通过对其某一位置进行赋值而改变字符串。下面的语句就会出现如下语法错误:“TypeError: ‘str’ object does not support item assignment”。

    关于不可变性,我们再看一个例子:

    上述代码中,str1 和 str2 都指向存储在内存中某个地方的字符串对象“welcome”。我们可以通过 id() 函数来测试 str1 和 str2 是否真的指向同一个对象。

    id() 函数可以得到对象在内存中的存储地址。

    我们可以看到,str1 和 str2 都指向同一个内存地址,因此,他们都指向同样的对象“welcome”。下面让我们再编辑 str1 的内容看看:

    我们可以看到,现在变量 str1 指向了一个完全不同的内容地址,这也说明,我们对 str1 的内容操作实际上是新建了一个新的字符串对象。

    2.6.3 字符串操作

    字符串索引开始于 0,因此,我们可以这样获取字符串的第一个字符:

    >>> name = 'yangjh'
    >>> name[0]
    

    在对字符串操作时,还可以从后往前取元素:

    >>> name[-1]
    

    运算符“+”用来连接字符串,运算符“*”用来重复字符串,例如:

    2.6.4 字符串分片

    我们还可以通过“[]”操作符来获取原始字符串的子集,这就是所谓的分片。语法规则如下:

    切分操作将返回字符串的部分内容,起始于 index,结束于 end-1。例如:

    注意:开始索引和结束索引都是可选的,如果忽略,开始索引就是 0,而结束索引就是字符串的最后一个字符对应的索引值。

    2.6.5 in 和 not in 操作符

    我们可以使用 in 和 not in 操作符检查一个字符串是否存在于另一个字符串,in 和 not in 就是所谓的成员资格操作符(membership operator)。

    2.6.6 String 对象的方法

    下表是三个常用的字符串方法:

    2.6.7 比较字符串

    我们可以使用 ( > , < , <= , <= , == , != ) 比较两个字符串。Python 比较字符串是按照编纂字典的方式进行的,也就是使用 ASCII 编码值1

    假设 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’]。

    2.7.4 列表对象常用内置方法

    2.7.4.1 追加列表元素

    。列表提供了在列表尾部追加新对象的方法append。

    2.7.4.2 计数

    count方法统计指定元素在列表中出现的次数,如:

    >>> code = ['to', 'be', 'or', 'not', 'to', 'be']
    >>> print(code.count('to'))
    

    以上代码将统计出列表中‘to’元素出现的次数,结果为2。

    2.7.4.3 合并列表

    extend方法在列表的末尾一次性追加另一个序列中的多个值,如:

    以上代码将把b列表追加到a列表中,打印出的a列表的值为[1, 2, 3, 4, 5, 6]。和序列加运算不同,extend方法将改变原有列表的内容,而加运算却不会。例如:

    上述代码结果显示为[4, 5, 6],b列表的内容并没有改变。

    2.7.4.4 元素索引

    index方法用于从列表中找出指定值第一次匹配的索引值。例如:

    以上代码运行结果为0,即第一个1出现的索引为0。

    2.7.4.5 插入元素

    insert方法用于将对象插入到列表中,例如:

    运行结果为[1, 2, 2.5, 3],insert方法的两个参数值很好理解,第一个参数为在哪个元素后插入,表示位置,第二个参数为插入的内容。

    2.7.4.6 pop

    pop方法会移除列表中的一个元素,默认为最后一个,和append方法刚好相反,并且返回该元素的值。例如:

    运行结果为3和[1, 2],当然,pop方法也可以指定移除某个索引的元素。

    2.7.4.7 remove

    remove方法用于移除列表中某个值的第一个匹配项:

    运行结果为None和[‘to’, ‘be’, ‘not’, ‘to’, ‘be’]。这说明remove方法并不返回匹配到的内容。

    2.7.4.8 reverse

    reverse方法将倒序排列列表元素:

    运行结果为[3, 2, 1]。

    2.7.4.9 sort

    sort方法用于对列表排序,如:

    运行结果为:[1, 2, 3, 4, 6, 8]。需要注意的是,sort方法没有返回值,并且改变列表的内容,如果你不但要排序,而且还要保持原有数据的内容,解决的方法之一是将原有内容赋值到另外一个变量中保存。

    2.8 字典

    字典(Dictionary)是Python中的一种数据类型,用来存储键(key)值(value)对。字典数据能够使用键名快速取回、添加、删除、编辑值。字典和其他语言中的数组(array)或者哈希表(hash)非常相似。字典是可变(mutable)序列。

    2.8.1 创建字典

    使用花括弧 {}就可创建字典。字典中的每一个项目都由键名、冒号:和值组成,多个项目之间用逗号,分割。让我们看一个实例:

    friends = {
    'tom'   : '66666666',
    'jerry' : '88888888'
    

    上面的变量friends是一个含有两个项目的字典。需要注意的一点是,键名必须是可哈希类型,而值可以是任意类型。字典中的键名必须是唯一的。

    2.8.2 获取、修改和添加字典元素

    获取字典中的项目,使用如下语法:

    如果字典中存在指定的键名,则返回对应的值,否则抛出键名异常。

    添加和编辑项目,使用如下语法:

    删除字典中的项目使用如下语法:

    2.8.3 遍历字典

    我们可以使用循环遍历字典中的所有项目。

    2.8.3.1 字典比较

    使用 ==!= 操作符判断字典是否包含相同的项目。

    >>> d1 = {"mike":41, "bob":3}
    >>> d2 = {"bob":3, "mike":41}
    >>> d1 == d2
    >>> d1 != d2
    False
    

    不能使用其它的关系操作符(< , > , >= , <= )比较字典类型变量。

    2.8.4 字典常用方法

    Python提供了多个内置的方法,用来操作字典,常用方法见下表:

    2.8.5 字典的排序

    字典的排序,可以使用sorted()函数,语法如下:

  • iterable表示可以迭代的对象,例如可以是dict.items()dict.keys()等;
  • key是一个函数,用来选取参与比较的元素;
  • reverse则是用来指定排序是倒序还是顺序,reverse=true则是倒序,reverse=false时则是顺序,默认时reverse=false。
  • 2.8.5.1 sorted函数按key值对字典排序

    直接使用sorted(d.keys())就能按key值对字典排序,这里是按照顺序对key值排序的,如果想按照倒序排序的话,则只要将reverse置为true即可。

    2.8.5.2 sorted函数按value值对字典排序

    要对字典的value排序则需要用到key参数,常使用lambda表达式的方法,如下:

    这里的dd.items()实际上是将dd转换为可迭代对象,items()方法将字典的元素转化为了元组,而这里key参数对应的lambda表达式的意思则是选取元组中的第二个元素作为比较对象,如果写作key=lambda item:item[0]的话则是选取第一个元素作为比较对象,也就是key值作为比较对象。

    注意排序函数sorted()返回值是一个list,而原字典中的名值对被转换为了list中的元组。

    2.9.2 元组相关方法

    元组也是序列,因此序列能使用的方法,如max , min , len , sum方法元组也能使用。

    在第一次循环时,值 1 被传递给 i,第二次循环时,值 2 被传递给 i。循环一直到列表变量 mylist 没有更多元素时停止。运行结果为:

    2.11.2 范围循环

    range() 函数能够指定循环的起始值和结束值,从而让循环体在指定的范围内循环。例如:

    range() 函数只有 1 个参数时,表示从 0 开始循环;两个参数时,第一个参数是起始值,第二个参数是结束值;三个参数时,第三个参数表示循环步长。

    2.11.3 while 循环

    While 循环会一直执行循环体内部的声明,直到条件变成 false。每次循环都会检查判断条件,如果为真,就继续循环。例如:

    这段代码将会打印出 0-9,直到 count 等于 10。

    2.11.4 中断循环

    使用 break 语句,可以中断循环,例如:

    运行结果为:

    2.11.5 继续循环

    当循环体内部出现 continue 声明时,会结束本次循环,跳转到循环体开始位置,开始下一次循环。例如:

    运行结果将打印出 1,3,5,7,9。

    Python使用def关键词创建函数,语法如下:

    空白区在 Python 中十分重要。实际上,空白区在各行的开头非常重要。这被称作缩进(Indentation)。在逻辑行的开头留下空白区(使用空格或制表符)用以确定各逻辑行的缩进级别,而后者又可用于确定语句的分组。

    这意味着放置在一起的语句必须拥有相同的缩进。每一组这样的语句被称为块(block)。有一件事你需要记住:错误的缩进可能会导致错误。

    所有在函数内部的声明,都必须使用相等的缩进。函数可以没有参数,也可以有多个参数。多个参数之间用逗号隔开。还可以使用pass关键字忽略掉函数主题的声明。

    我们看一个函数的例子,下面的函数将计算指定范围的整数之和:

    在上面的代码中,我们定义了一个叫作sum()的函数,该函数有两个参数(startend),该函数将从start开始,累加到end,最后打印出累积之和。代码运行的结果为55。

    2.12.2 函数返回值

    上文定义的函数只是简单地在控制台打印出结果,如果我们想要将计算结果赋值给变量,以便做更深入的处理时应该怎么办?当我们遇到这种情况时,可使用return语句,将返回函数计算结果并且退出函数。例如:

    在上面这段代码中,我们定义了有返回值的函数sumReturn(),并将其结果赋值给变量a。上面代码的运行结果为15。

    当然,return语句也可以不返回值,而是用来退出函数(实际上会返回None,为NoneType对象)。每一个函数都在其末尾隐含了一句 return None,除非你写了你自己的 return 语句。

    上述代码的运行结果如下:

    在Python中,如果你不指定return的返回值,则会返回None值。

    2.12.3 全局变量和局域变量

    全局变量指的是不属于任何函数,但又可以在函数内外访问的变量。而局域变量指的是在函数内部声明的变量,局域变量只能在函数内部使用,无法在函数外访问(函数执行完后,会销毁内部定义的局部变量)。

    下面我们通过例子来演示这两者的区别:

    上述代码将会出现错误:

    我们再看一个例子:

    该代码显示的结果是200,不是100。

    使用global关键字,可以将局部变量同全局变量绑定在一起。例如:

    使用global关键字声明全局变量时,无法直接赋值,比如“global t = 1”的写法存在语法错误。

    2.12.4 参数的默认值

    为参数指定默认值,只需在定义函数时使用赋值语句即可。例如:

    上述定义的函数func()有两个参数i和j。j的默认值为100,这意味着我们在调用这个函数的时候可以忽略掉j的值,比如func(2),运行结果为2 100。

    2.12.5 关键字参数

    为函数传递参数值的方法有两种:位置参数和关键字参数。我们之前调用函数的时候都使用的是位置参数。下面我们看如何使用关键字参数:

    上述代码运行结果都是“hello jim”。

    关键字参数使用“name=value”的名称、值对传递数据,正如上面代码演示的那样,使用关键字参数的时候,参数的顺序是可以调换的,而且位置参数和关键字参数可以混合使用(只能先使用位置参数,后使用关键字参数)。

    2.12.6 返回多个值

    我们可以通过在return语句中使用逗号,将多个值返回,这种返回值的类型是元组。例如:

    运行结果为:

    2.12.7 函数文档字符串

    Python 有一个甚是优美的功能称作文档字符串(Documentation Strings),在称呼它时通常会使用另一个短一些的名字docstrings。DocStrings 是一款你应当使用的重要工具,它能够帮助你更好地记录程序并让其更加易于理解。令人惊叹的是,当程序实际运行时,我们甚至可以通过一个函数来获取文档!

    该文档字符串所约定的是一串多行字符串,其中第一行以某一大写字母开始,以句号结束。第二行为空行,后跟的第三行开始是任何详细的解释说明。强烈建议你的文档字符串中都遵循这一约定。

    我们可以通过使用函数的 __doc__(注意其中的双下划线)属性(属于函数的名称)来获取函数 print_max 的文档字符串属性。

    2.12.8 lambda表达式

    Lambda表达式(或者Lambda形式)用来创建匿名函数。语法如下:

    个人认为,lambda 是为了减少单行函数的定义而存在的,能够提高代码的简洁性。比如:

    2.12.9 *args**kwargs

    *args**kwargs是两个魔法变量。那么它们到底是什么? *args**kwargs 主要用于函数定义。 你可以将不定数量的参数传递给一个函数。

    首先,并不是必须写成*args**kwargs。 只有变量前面的 *(星号)才是必须的. 你也可以写成*var**vars。而写成*args**kwargs只是一个通俗的命名约定。

    2.12.9.1 *args 的用法

    *args 是用来发送一个非键值对的可变数量的参数列表给一个函数.

    这里有个例子帮你理解这个概念:

    这会产生如下输出:

    2.12.9.2 **kwargs 的用法

    **kwargs 允许你将不定长度的键值对, 作为参数传递给一个函数。 如果你想要在一个函数里处理带名字的参数, 你应该使用**kwargs

    这里有个让你上手的例子:

    现在你可以看出我们怎样在一个函数里, 处理了一个键值对参数了。

    2.12.9.3 使用 *args**kwargs 来调用函数

    那现在我们将看到怎样使用*args**kwargs 来调用一个函数。 假设,你有这样一个小函数:

    你可以使用*args**kwargs来给这个小函数传递参数。 下面是怎样做:

    2.12.9.4 标准参数与*args**kwargs在使用时的顺序

    如果你想在函数里同时使用所有这三种参数, 顺序是这样的:

    2.12.10 参考资料

    Python进阶