Python基本语法

基本语法与运算符

注释#

基本数据类型

int可以是任何大小的整数

变量名的第一个字符必须是字母或下划线;变量名区分大小写;

使用单/双引号指定字符串,所有引号内的字符,包括空格与制表符都将原样保留。两种引号工作机制相同

输出格式

三引号用于指定多行字符串("""或'''均可以)
例如:

1
2
3
print('''this is the first line
and this is the second
hhahahah''')

就会原样输出3行

有时候我们会想要从其他信息中构建字符串。这正是 format() 方法大有用武之地的地方。
例如:

1
2
3
4
age = 20
name = 'Swaroop'
print('{} was {} years old when he wrote this book'.format(name, age))
print('Why is {} playing with that python?'.format(name))

Python 中 format 方法所做的事情便是将每个参数值替换至格式所在的位置。这之中可以有 更详细的格式,例如:

1
2
3
4
5
6
7
8
9
# 对于浮点数 '0.333' 保留小数点(.)后三位
print('{0:.3f}'.format(1.0/3))
# 或者省略花括号里面那个0也是可以的
print('{:.3f}'.format(1.0/3))
# 使用下划线填充文本,并保持文字处于中间位置
# 使用 (^) 定义 '___hello___'字符串长度为 11
print('{0:_^11}'.format('hello'))
# 基于关键词输出 'Swaroop wrote A Byte of Python'
print('{name} wrote {book}'.format(name='Swaroop', book='A Byte of Python'))

由于我们正在讨论格式问题,就要注意 print 总是会以一个不可见的“新一行”字符( \n ) 结尾,因此重复调用 print 将会在相互独立的一行中分别打印。为防止打印过程中出现这一 换行符,你可以通过 end 指定其应以空白结尾:

1
2
print('a', end='')
print('b', end=' ')#以空格结尾

转义序列

如果希望生成一串包含单引号( ‘ )的字符串,你应该如何指定这串字符串? 例如,你想要的字符串是 “What’s your name?” 。你不能指定 ‘What’s your name?’ ,因为这 会使 Python 对于何处是字符串的开始、何处又是结束而感到困惑。所以,你必须指定这个单引号不代表这串字符串的结尾。这可以通过转义序列(Escape Sequence) 来实现。你通过\ 来指定单引号:要注意它可是反斜杠。现在,你可以将字符串指定为 ‘What\’s your name?’
另一种指定这一特别的字符串的方式是这样的: “What’s your name?” ,如这个例子般使用 双引号。类似地, 你必须在使用双引号括起的字符串中对字符串内的双引号使用转义序列。 同样,你必须使用转义序列 \ 来指定反斜杠本身。
如果你想指定一串双行字符串该怎么办?一种方式即使用如前所述的三引号字符串,或者你 可以使用一个表示新一行的转义序列——\n 来表示新一行的开始。(与cpp类似)

在一个字符串中,一个放置在末尾的反斜杠表示字符串将在下一行继续,但不会添加新的一行。来看看例子:

1
2
"This is the first sentence. \
This is the second sentence."

相当于"This is the first sentence. This is the second sentence."

基础语法

所谓物理行(Physical Line)是你在编写程序时 你所看到的内容。所谓逻辑行(Logical Line)是 Python 所看到 的单个语句。Python 会假定每一物理行会对应一个逻辑行。如果你希望在一行物理行中指定多行逻辑行,那么你必须通过使用分号( ; )来明确表明逻辑行或语句的结束。

空白区在 Python 中十分重要。实际上,空白区在各行的开头非常重要。这被称作 缩进 (Indentation)。在逻辑行的开头留下空白区(使用空格或制表符)用以确定各逻辑行的缩 进级别,而后者又可用于确定语句的分组。这意味着放置在一起的语句必须拥有相同的缩进。每一组这样的语句被称为 块(block)。

Attention:使用四个空格来缩进。这是来自 Python 语言官方的建议。好的编辑器会自动为你完成这 一工作。请确保你在缩进中使用数量一致的空格,否则你的程序将不会运行,或引发不 期望的行为。

运算符与优先级

需要注意的运算符

** (乘方)
返回 x 的 y 次方。
3**4 输出 81 (即 3 3 3* 3 )。

/(除)
x 除以 y
13 / 3 输出 4.333333333333333 。

// (整除)
x 除以 y 并对结果向下取整至最接近的整数。 13 // 3 输出 4 。
-13 // 3 输出 -5 。

< (小于) > (大于)
返回 x 是否小于 y。所有的比较运算符返回的结果均为 TrueFalse 。请注意这 些名称之中的大写字母
5<3 输出 False ,3<6 输出 True 。
比较可以任意组成链接: 3 < 5 < 7 返回 True 。
如果两个操作数均为数字,它们首先将会被转换至一种共同的类型。否则,它将总是返回 False 。

not (布尔“非”) 对应cpp的!
and (布尔“与”) 对应cpp的&
or (布尔“或”) 对应cpp的|

其余运算符与cpp基本一致

优先级

以下运算符优先级由低至高排序
lambda :Lambda 表达式 if - else :条件表达式 or :布尔“或”
and:布尔“与”
not x :布尔“非”
in, not in, is, is not, <, <=, >, >=, !=, == :比较,包括成员资格测试 (Membership Tests)和身份测试(Identity Tests)。
| :按位或
^ :按位异或
& :按位与
<<, >> :移动
+, -:加与减
*, /, //, %:乘、除、整除、取余
+x, -x, ~x :正、负、按位取反
** :求幂
x[index], x[index:index], x(arguments...), x.attribute :下标、切片、调用、属性引 用
(expressions...), [expressions...], {key: value...}{expressions...}:表示绑定或元 组、表示列表、表示字典、表示集合

控制与循环

If…else…

例子如下,注意缩进:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
number = 23
guess = int(input('Enter an integer : '))
if guess == number:
# 新块从这里开始
print('Congratulations, you guessed it.')
print('(but you do not win any prizes!)')
# 新块在这里结束
elif guess < number:
# 另一代码块
print('No, it is a little higher than that')
# 你可以在此做任何你希望在该代码块内进行的事情
else:
print('No, it is a little lower than that')
# 你必须通过猜测一个大于(>)设置数的数字来到达这里。

print('Done')
# 这最后一句语句将在
# if 语句执行完毕后执行。

Python 中不存在 switch 语句。你可以通过使用 if..elif..else 语句来实现同样的事情

while循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
number = 23
running = True
while running:
guess = int(input('Enter an integer : '))
if guess == number:
print('Congratulations, you guessed it.')
# 这将导致 while 循环中止
running = False
elif guess < number:
print('No, it is a little higher than that.')
else:
print('No, it is a little lower than that.')
else:
print('The while loop is over.')
# 在这里你可以做你想做的任何事

print('Done')

注意:你可以在 while 循环中使用 else 从句。

for循环

1
2
3
4
for i in range(1, 5):
print(i)
else:
print('The for loop is over')

注意range里面是前闭后开的区间!

else 部分是可选的。当循环中包含他时,它总会在 for 循环结束后开始执 行,除非程序遇到了 break 语句。

在这里我们所要做的事情是提供两个数字,而 range 将会返回一个数字序列,从第一个数字 开始,至第二个数字结束。举个例子, range(1,5) 将输出序列 [1, 2, 3, 4] 。在默认情况下,range 将会以 1 逐步递增。如果我们向 range 提供第三个数字,则这个数字将成为逐 步递增的加数。 同样举个例子来说明range(1,5,2) 将会输出 [1, 3] 。要记住这一序列扩 展直到第二个数字,也就是说,它不会包括第二个数字在内。

break

1
2
3
4
5
6
while True:
s = input('Enter something : ')
if s == 'quit':
break
print('Length of the string is', len(s))
print('Done')

有一点需要尤其注意,如果你 中断 了一个 for 或 while 循环,任何相应循环中的 else块都将不会被执行。

continue

continue 语句用以告诉 Python 跳过当前循环块中的剩余语句,并继续该循环的下一次迭代。

1
2
3
4
5
6
7
8
9
while True:
s = input('Enter something : ')
if s == 'quit':
break
if len(s) < 3:
print('Too small')
continue
print('Input is of sufficient length')
# 自此处起继续进行其它任何处理

函数

函数可以通过关键字 def 来定义。这一关键字后跟一个函数的标识符名称,再跟一对圆括号,其中可以包括一些变量的名称,再以冒号结尾,结束这一行。随后而来的语句块是函数的一部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
def print_max(a, b):
if a > b:
print(a, 'is maximum')
elif a == b:
print(a, 'is equal to', b)
else:
print(b, 'is maximum')
# 直接传递字面值
print_max(3, 4)
x=5
y=7
# 以参数的形式传递变量
print_max(x, y)

global语句

如果你想给一个在程序顶层的变量赋值(也就是说它不存在于任何作用域中,无论是函数还 是类),那么你必须告诉 Python 这一变量并非局部的,而是全局(Global)的。我们需要通 过 global 语句来完成这件事。因为在不使用 global 语句的情况下,不可能为一个定义于 函数之外的变量赋值。

说人话就是,Python的函数中如果想用函数外部的变量的话,必须在函数中声明这个变量是global的,不然会在函数内创建一个同名的局部变量,并且局部变量与外部变量并没有什么关系。也就是说,全局变量其实并不是很好用;
例子:

声明global的情况:
1
2
3
4
5
6
7
8
9
x=50
def func():
global x
x=10
print('x is', x)
x=2
print('Changed global x to', x)
func()
print('Value of x is', x)

输出:

1
2
3
x is 50
Changed global x to 2
Value of x is 10

不声明global的情况:
1
2
3
4
5
6
7
8
9
x=50
def func():
#global x
x=10
print('x is', x)
x=2
print('Changed global x to', x)
func()
print('Value of x is', x)

输出:

1
2
3
x is 50
Changed global x to 2
Value of x is 2

默认参数值

对于一些函数来说,你可能为希望使一些参数可选并使用默认的值,以避免用户不想为他们 提供值的情况。默认参数值可以有效帮助解决这一情况。你可以通过在函数定义时附加一个 赋值运算符( = )来为参数指定默认参数值。
要注意到,默认参数值应该是常数。更确切地说,默认参数值应该是不可变的
例子:

1
2
3
4
def say(message, times=1):
print(message * times)
say('Hello')
say('World', 5)

输出:

1
2
3
$ python function_default.py
Hello
WorldWorldWorldWorldWorld

注意!

只有那些位于参数列表末尾的参数才能被赋予默认参数值,意即在函数的参数列表中拥有默认参数值的参数不能位于没有默认参数值的参数之前。这是因为值是按参数所处的位置依次分配的。举例来说,def func(a, b=5) 是有效的, 但 def func(a=5, b) 是无效的。

关键字参数

如果你有一些具有许多参数的函数,而你又希望只对其中的一些进行指定,那么你可以通过 命名它们来给这些参数赋值——这就是关键字参数(Keyword Arguments)——我们使用命名(关键字)而非位置(一直以来我们所使用的方式)来指定函数中的参数。
这样做有两大优点——其一,我们不再需要考虑参数的顺序,函数的使用将更加容易。其二,我们可以只对那些我们希望赋􏰀的参数以赋值,只要其它的参数都具有默认参数值。
例子:

1
2
3
4
5
def func(a, b=5, c=10):
print('a is', a, 'and b is', b, 'and c is', c)
func(3, 7)
func(25, c=24)
func(c=50, a=100)

输出:

1
2
3
4
$ python function_keyword.py
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50

可变参数

留空待补

return语句

大体与Cpp的类似,例子:

1
2
3
4
5
6
7
8
def maximum(x, y):
if x > y:
return x
elif x == y:
return 'The numbers are equal'
else:
return y
print(maximum(2, 3))

要注意到如果 return 语句没有搭配任何一个值则代表着 返回 None 。 None 在 Python 中一 个特殊的类型,代表着虚无。

每一个函数都在其末尾隐含了一句return None ,除非你写了你自己的 return 语句。

Python 中的 pass 语句用于指示一个没有内容的语句块。

DocStrings文档字符串

Python 有一个甚是优美的功能称作文档字符串(Documentation Strings),在称呼它时通常 会使用另一个短一些的名字docstrings。DocStrings 是一款你应当使用的重要工具,它能够帮 助你更好地记录程序并让其更加易于理解。

函数的第一行逻辑行中的字符串是该函数的 文档字符串(DocString)。这里要注意文档字符串也适用于后面相关章节将提到的模块(Modules)与类(Class) 。

该文档字符串所约定的是一串多行字符串,其中第一行以某一大写字母开始,以句号结束。 第二行为空行,后跟的第三行开始是任何详细的解释说明。在此强烈建议你在你所有重要功 能的所有文档字符串中都遵循这一约定。
但是事实上,像例子中的那样,只要是函数第一行开始的多行字符串里面的内容都没什么问题

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def print_max(x, y):
'''233打印两个数值中的最大数。
233
wewe这两个数都应该是整数
dsfsvsg'''
# 如果可能,将其转换至整数类型
x = int(x)
y = int(y)
if x > y:
print(x, 'is maximum')
else:
print(y, 'is maximum')
print_max(3, 5)
print(print_max.__doc__)#我们可以通过使用函数的 __doc__ (注意其中的双下划綫)属性(属于函数的名称)来获取 函数 print_max 的文档字符串属性。

输出:

1
2
3
4
5
6
7
5 is maximum
233打印两个数值中的最大数。
233
wewe这两个数都应该是整数
dsfsvsg

Process finished with exit code 0

模块

编写模块有很多种方法,其中最简单的一种便是创建一个包含函数与变量、以 .py 为后缀的 文件。
另一种方法是使用撰写 Python 解释器本身的本地语言来编写模块。举例来说,你可以使用 C 语言来撰写 Python 模块,并且在编译后,你可以通过标准 Python 解释器在你的 Python 代 码中使用它们。
一个模块可以被其它程序导入并运用其功能。我们在使用 Python 标准库的功能时也同样如 此。首先,我们要了解如何使用标准库模块。
例子:

1
2
3
4
5
import sys
print('The command line arguments are:')
for i in sys.argv:
print(i)
print('\n\nThe PYTHONPATH is', sys.path, '\n')

当 Python 运行 import sys 这一语句时,它会开始寻找 sys 模块。在这一案例中,由于其 是一个内置模块,因此 Python 知道应该在哪里找到它。
如果它不是一个已编译好的模块,即用 Python 编写的模块,那么 Python 解释器将从它的 sys.path 变量所提供的目录中进行搜索。

from…import…

如果你希望直接将 argv 变量导入你的程序 (为了避免每次都要输入 sys.),那么你可以通过使用 from sys import argv 语句来实现这一点。

警告:一般来说,你应该尽量避免使用 from…import 语句,而去使用 import 语句。这是为了避免在你的程序中出现名称冲突,同时也为了使程序更加易读。

eg:

1
2
from math import sqrt
print("Square root of 16 is", sqrt(16))

模块的 __name__ (不甚明确)

每个模块都有一个名称,而模块中的语句可以找到它们所处的模块的名称。这对于确定模块是独立运行的还是被导入进来运行的这一特定目的来说大为有用。
每一个 Python 模块都定义了它的 name 属性。如果它与 main 属性相同则代表这一 模块是由用户独立运行的,因此我们便可以采取适当的行动。

1
2
3
4
if __name__ == '__main__':
print('This program is being run by itself')
else:
print('I am being imported from another module')

编写自己的模块

编写自己的模块很简单,这是因为每一个 Python 程序同时也是一个模块。你只需要保证它以 .py 为扩展名即可。下面的案例会作出清晰的解释。
例子:test1.py

1
2
3
4
5
def say_hi():
print('hi!This is my first module!')

__version__='0.1'
#say_hi()

上方所呈现的就是一个简单的模块。正如你所看见的,与我们一般所使用的 Python 的程序相 比其实并没有什么特殊的区别。我们接下来将看到如何在其它 Python 程序中使用这一模块。
要记住该模块应该放置于与其它我们即将导入这一模块的程序相同的目录下,或者是放置在 sys.path 所列出的其中一个目录下。
test2.py:

1
2
3
4
import test1

test1.say_hi()
print('Version:',test1.__version__)

输出:

1
2
hi!This is my first module!
('Version:', '0.1')

当然也可以采用from...import...的做法:

1
2
3
4
from test1 import say_hi,__version__

say_hi()
print('Version:',__version__)

在这里需要注意的是,如果导入到 mymodule 中的模块里已经存在了 version 这一名 称,那将产生冲突。这可能是因为每个模块通常都会使用这一名称来声明它们各自的版本号。

还可以使用:from test1 import * 这将导入诸如 say_hi 等所有公共名称,但不会导入 version 名称,因为后者以双下划线开头。

dir函数

内置的 dir() 函数能够返回由对象所定义的名称列表。 如果这一对象是一个模块,则该列表会包括函数内所定义的函数、类与变量。
该函数接受参数。 如果参数是模块名称,函数将返回这一指定模块的名称列表。 如果没有提供参数,函数将返回当前模块的名称列表。
例子:(在上面的test2中调用这一函数)

1
2
3
4
5
import test1
import sys

print(dir(test1))
print(dir())

输出:

1
2
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__version__', 'say_hi']
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'sys', 'test1']

数据结构

Python 中有四种内置的数据结构——列表(List)、元组(Tuple)、字典(Dictionary)和集合(Set)

列表

列表 是一种用于保存一系列有序项目的集合.(比较类似于cpp中的list)
注意列表使用[]来体现这是一个列表而不是元组

项目的列表应该用方括号括起来,这样Python才能理解到你正在指定一张列表。一旦你创建了一张列表,你可以添加、移除或搜索列表中的项目。既然我们可以添加或删除项目,我们 会说列表是一种可变的(Mutable)数据类型,意即,这种类型是可以被改变的。
例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# This is my shopping list
shoplist = ['apple', 'mango', 'carrot', 'banana']
print('I have', len(shoplist), 'items to purchase.')
print('These items are:',end=' ')
for item in shoplist:
print(item, end=' ')
#使用 for...in 循环来遍历列表中的每一个项目。
print('\nI also have to buy rice.')
shoplist.append('rice')
#可以添加任意类型
print('My shopping list is now', shoplist)
print('I will sort my list now')
shoplist.sort()
#按照字典序从小到大排序
print('Sorted shopping list is', shoplist)
print('The first item I will buy is', shoplist[0])
olditem = shoplist[0]
del shoplist[0]
#删除列表中的第一项
print('I bought the', olditem)
print('My shopping list is now', shoplist)

可以向同一个列表中添加任何类型的 对象,包括数字,甚至是其它列表。(但是此时如果要sort必须定义比较函数,否则int与字符类型比较会出错)

元组

元组与列表比较类似,但是使用的括号(标识符)不同,并且,元组不能进行更改。
注意:元组使用()或者不使用任何括号来体现

比较正式的说法:
元组(Tuple)用于将多个对象保存到一起。你可以将它们近似地看作列表,但是元组不能提供列表类能够提供给你的广泛的功能。元组的一大特征类似于字符串,它们是不可变的,也就是说,你不能编辑或更改元组。
元组是通过特别指定项目来定义的,在指定项目时,你可以给它们加上括号,并在括号内部用逗号进行分隔。(也就是说可以不加括号)
例子:

1
2
3
4
5
6
7
8
9
zoo= ('python', 'elephant', 'penguin')
print('Number of animals in the zoo is', len(zoo))
new_zoo = 'monkey', 'camel', zoo#注意此处元组中以另一个元组作为自己的一个项
print('Number of cages in the new zoo is', len(new_zoo))#此时作为项的元组总体视为一项
print('All animals in new zoo are', new_zoo)
print('Animals brought from old zoo are', new_zoo[2])
print('Last animal brought from old zoo is', new_zoo[2][2])#注意类似数组的用法
print('Number of animals in the new zoo is',
len(new_zoo)-1+len(new_zoo[2]))

输出:

1
2
3
4
5
6
Number of animals in the zoo is 3
Number of cages in the new zoo is 3
All animals in new zoo are ('monkey', 'camel', ('python', 'elephant', 'penguin'))
Animals brought from old zoo are ('python', 'elephant', 'penguin')
Last animal brought from old zoo is penguin
Number of animals in the new zoo is 5

包含 0 或 1 个项目的元组
一个空的元组由一对圆括号构成,就像 myempty = () 这样。然而,一个只拥有一个项目的元组并不像这样简单。你必须在第一个(也是唯一一个)项目的后面加上一个逗号 来指定它,如此一来 Python 才可以识别出在这个表达式想表达的究竟是一个元组还是只 是一个被括号所环绕的对象,也就是说,如果你想指定一个包含项目 2的元组,你必 须指定 singleton = (2, )。当然,你甚至可以把只有一个项目的元组的括号也省略掉!(空的元组显然不行,不然解释器并不知道你在定义什么…)

字典

字典提供的功能是将键值(Keys)(即姓名)与值(Values)(即地址等详细信息)联立到一起。在这里要注意到键值必须是唯一的。(类似map,不提供multimap功能)
另外要注意的是你只能使用不可变的对象(如字符串)作为字典的键值,但是你可以使用可变或不可变的对象作为字典中的值。基本上这段话也可以翻译为你只能使用简单对象作为键值。
在字典中,你可以通过使用符号构成d = {key : value1 , key2 : value2} 这样的形式,来成 对地指定键值与值。在这里要注意到成对的键值与值之间使用冒号分隔,而每一对键值与值 则使用逗号进行区分,它们全都由一对花括号括起。另外需要记住,字典中的成对的键值—值配对不会以任何方式进行排序。如果你希望为它们安排一个特别的次序,只能在使用它们之前自行进行排序。
例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# “ab”是地址(Address)簿(Book)的缩写
ab = {
'Swaroop': 'swaroop@swaroopch.com',
'Larry': 'larry@wall.org',
'Matsumoto': 'matz@ruby-lang.org',
'Spammer': 'spammer@hotmail.com',
6:234#可以同时添加几种类型
}
print("Swaroop's address is", ab['Swaroop'])
# 删除一对键值—值配对
del ab['Spammer']
print('\nThere are {} contacts in the address-book\n'.format(len(ab)))
for name, address in ab.items():#注意name,address这两个关键字,这两个字用a,b也没用关系,是自己指定的
print('Contact {} at {}'.format(name, address))
# 添加一对键值—值配对
ab['Guido'] = 'guido@python.org'#类似map的插入功能
if 'Guido' in ab:#检测是否存在这一键值
print("\nGuido's address is", ab['Guido'])

输出:

1
2
3
4
5
6
7
8
9
10
Swaroop's address is swaroop@swaroopch.com

There are 4 contacts in the address-book

Contact Swaroop at swaroop@swaroopch.com
Contact Larry at larry@wall.org
Contact Matsumoto at matz@ruby-lang.org
Contact 6 at 234

Guido's address is guido@python.org

可以通过del 语句—来删除某一 键值—值 配对。我们只需指定字典、包含需要删除的键值名称的索引算符,并将其传递给del 语句。这一操作不需要你知道与该键值相对应的值。
可以使用in运算符来检查某对键值-键配对是否存在

序列

序列的主要功能是资格测试(Membership Test)(也就是 in 与 not in 表达式)和索引操作(Indexing Operations),它们能够允许我们直接获取序列中的特定项目。

上面所提到的序列的三种形态——列表、元组与字符串,同样拥有一种切片(Slicing)运算符,它能够允许我们序列中的某段切片——也就是序列之中的一部分。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
shoplist = ['apple', 'mango', 'carrot', 'banana']
name = 'swaroop'

print('Item 0 is', shoplist[0])
print('Item 1 is', shoplist[1])
print('Item 2 is', shoplist[2])
print('Item 3 is', shoplist[3])
print('Item -1 is', shoplist[-1])
print('Item -2 is', shoplist[-2])
print('Character 0 is', name[0])

print('Item 1 to 3 is', shoplist[1:3])
print('Item 2 to end is', shoplist[2:])
print('Item 1 to -1 is', shoplist[1:-1])
print('Item start to end is', shoplist[:])
# 从某一字符串中切片 #
print('characters 1 to 3 is', name[1:3])
print('characters 2 to end is', name[2:])
print('characters 1 to -1 is', name[1:-1])
print('characters start to end is', name[:])

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Item 0 is apple
Item 1 is mango
Item 2 is carrot
Item 3 is banana
Item -1 is banana
Item -2 is carrot
Character 0 is s
Item 1 to 3 is ['mango', 'carrot']
Item 2 to end is ['carrot', 'banana']
Item 1 to -1 is ['mango', 'carrot']
Item start to end is ['apple', 'mango', 'carrot', 'banana']
characters 1 to 3 is wa
characters 2 to end is aroop
characters 1 to -1 is waroo
characters start to end is swaroop

使用说明:

如上所示,每当你在方括号中为序列指定一个数字,Python 将 获取序列中与该位置编号相对应的项目。要记得 Python 从 0 开始计数。因此 shoplist[0] 将获得 shoplist 序列中的第一个项目,而 shoplist[3] 将获得第四个项目。
索引操作也可以使用负数,在这种情况下,位置计数将从队列的末尾开始。 因此,shoplist[-1] 指的是序列的最后一个项目,shoplist[-2] 将获取序列中倒数第二个项目。

在序列中切片

在切片操作中,第一个数字(冒号前面的那位)指的是切片开始的位置,第二个数字(冒号后面的那位)指的是切片结束的位置。如果第一位数字没有指定,Python 将会从序列的起始处开始操作。如果第二个数字留空,Python 将会在序列的末尾结束操作。要注意的是切片操作会在开始处返回 start,并在 end 前面的位置结束工作。也就是说,序列切片将包括起始位置,但不包括结束位置。
因此, shoplist[1:3] 返回的序列的一组切片将从位置 1 开始,包含位置 2 并在位置 3 时结束,因此,这块切片返回的是两个项目。类似地,shoplist[:] 返回的是整个序列。
你同样可以在切片操作中使用负数位置。使用负数时位置将从序列末端开始计算。例 如,shoplist[:-1] 强返回一组序列切片,其中不包括序列的最后一项项目,但其它所有项目都包含其中。 但是诸如shoplist[-1:1]这样的操作是不行的。

切片的步长

你同样可以在切片操作中提供第三个参数,这一参数将被视为切片的步长(Step)(在默认情况下,步长大小为 1):
例如:

1
2
3
4
5
6
7
8
9
>>> shoplist = ['apple', 'mango', 'carrot', 'banana']
>>> shoplist[::1]
['apple', 'mango', 'carrot', 'banana']
>>> shoplist[::2]
['apple', 'carrot']
>>> shoplist[::3]
['apple', 'banana']
>>> shoplist[::-1]
['banana', 'carrot', 'mango', 'apple']

你会注意到当步长为 2 时,我们得到的是第 0、2、4…… 位项目。当步长为 3 时,我们得到的是第 0、3……位项目。

集合

集合(Set)是简单对象的无序集合(Collection)。当集合中的项目存在与否比起次序或其出 现次数更加重要时,我们就会使用集合。
通过使用集合,你可以测试某些对象的资格或情况,检查它们是否是其它集合的子集,找到两个集合的交集,等等。
例子:

1
2
3
4
5
6
7
8
9
10
11
12
>>> bri = set(['brazil', 'russia', 'india'])
>>> 'india' in bri
True
>>> 'usa' in bri
False
>>> bric = bri.copy()
>>> bric.add('china')
>>> bric.issuperset(bri)
True
>>> bri.remove('russia')
>>> bri & bric # OR bri.intersection(bric)
{'brazil', 'india'}

引用

看起来这个引用与CPP中的&并没有太大区别,只不过Python中声明似乎更简单一些,直接令mylist=shoplist即可,注意这并不是声明另一个同类型的对象并进行拷贝赋值的意思。
例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
print('Simple Assignment')
shoplist = ['apple', 'mango', 'carrot', 'banana']
# mylist 只是指向同一对象的另一种名称
mylist = shoplist #注意这个引用声明的方式
# 我购买了第一项项目,所以我将其从列表中删除
del shoplist[0]
print('shoplist is', shoplist)
print('mylist is', mylist)
# 注意到 shoplist 和 mylist 二者都
# 打印出了其中都没有 apple 的同样的列表,以此我们确认
# 它们指向的是同一个对象
print('Copy by making a full slice')
# 通过生成一份完整的切片制作一份列表的副本 mylist = shoplist[:]
# 删除第一个项目
del mylist[0]
print('shoplist is', shoplist)
print('mylist is', mylist)
# 注意到现在两份列表已出现不同

输出:

1
2
3
4
5
6
Simple Assignment
shoplist is ['mango', 'carrot', 'banana']
mylist is ['mango', 'carrot', 'banana']
Copy by making a full slice
shoplist is ['carrot', 'banana']
mylist is ['carrot', 'banana']

注意:记住,如果希望创建一份诸如序列等复杂对象的副本(而非整数这种简单的对象 (Object)),你必须使用切片操作来制作副本。如果你仅仅是将一个变量名赋予给另一个名称,那么它们都将“查阅”同一个对象,也就是相当于声明了一个原对象的引用!

如果需要拷贝序列等复杂对象,应该像下面这样:

1
mylist1=shoplist[:]

面向对象编程

一个类(Class)能够创建一种新的类型 (Type),其中对象(Object)就是类的实例(Instance)。可以这样来类比:你可以拥有 类型 int 的变量,也就是说存储整数的变量是 int 类的实例(对象)。

对象可以使用属于它的普通变量来存储数据。这种从属于对象或类的变量叫作字段 (Field)。对象还可以使用属于类的函数来实现某些功能,这种函数叫作类的方法 (Method)。

字段有两种类型——它们属于某一类的各个实例或对象,或是从属于某一类本身。它们被分别称作实例变量(Instance Variables)与类变量(Class Variables)。通过 class 关键字可以创建一个类。这个类的字段与方法可以在缩进代码块中以列出。

self

类的方法(大概相当于类的成员函数)与普通函数只有一种特定的区别——前者必须多加一个参数在参数列表开头,这个名字必须添加到参数列表的开头,但是你不用在你调用这个功能时为这个参数赋值,Python 会为它提供。这种特定的变量引用的是对象本身,按照惯例,它被赋予self 这一名称。尽管你可以为这一参数赋予任何名称,但是强烈推荐你使用 self 这一名称——其它的任何一种名称绝对会引人皱眉。
也就是说,类的成员函数在普通参数之外还必须放一个虚的参数在参数列表最前面,实际调用的时候并不需要提供这个参数

Python 中的 self 相当于 C++ 中的 this 指针以及 Java 与 C# 中的 this 引用。

最简单的类:

1
2
3
4
class Person:
pass # 一个空的代码块
p = Person()
print(p)

通过使用 class 语句与这个类的名称来创建一个新类。在它之后是一个缩进的语句块,代表这个类的主体。

我们已经在前面讨论过类与对象一如函数那般都可以带有方法(Method),唯一的不同在于我们还拥有一个额外的 self 变量(虚的变量)。现在让我们来看看下面的例子:

1
2
3
4
5
6
7
class Person:
def say_hi(self):#注意这个函数并没有正在的参数,只有一个self参数
print('Hello, how are you?')
p = Person()
p.say_hi()
Person().say_hi()
# 前面两行同样可以写作Person().say_hi()

这里我们就能看见 self 是如何行动的了。要注意到 say_hi 这一方法不需要参数,但是依旧在函数定义中拥有 self 变量。

类的初始化函数

类似于CPP的初始化函数:
在 Python 的类中,有不少方法的名称具有着特殊的意义。比如,__init__ 方法会在类的对象被实例化(Instantiated)时立即运行。这一方法可以对任何你想 进行操作的目标对象进行初始化(Initialization)操作。这里要注意在 init 前后加上的双下划线。
例子:

1
2
3
4
5
6
7
8
9
class Person:
def __init__(self, name):
self.name = name
def say_hi(self):
print('Hello, my name is', self.name)
p = Person('Swaroop')
p.say_hi()
# 前面两行同时也能写作
# Person('Swaroop').say_hi()

在本例中,我们定义一个接受 name 参数(当然还有 self 参数)的__init__ 方法。在这里,我们创建了一个字段,同样称为 name 。要注意到尽管它们的名字都是“name”,但这是两个不相同的变量。虽说如此,但这并不会造成任何问题,因为 self.name 中的点号意味着 这个叫作“name”的东西是某个叫作“self”的对象的一部分,而另一个 name 则是一个局部变量。由于我们已经如上这般明确指出了我们所指的是哪一个名字,所以它不会引发混乱。
当我们在 Person 类下创建新的实例 p 时,我们采用的方法是先写下类的名称,后跟括在 括号中的参数,形如: p = Person('Swaroop') 。
我们不会显式地调用 __init__ 方法。 这正是这个方法的特殊之处所在。