Python Tutorial for Beginners
为什么学Python
简单方便代码少. 不用太关注类型, 声明等琐事. 使用灵活, 第三方支持包也多.
在深度学习中,经常会看到很多demo是用Python来写的,深度学习框架一般都有一个Python版的接口,目前主流的深度学习框架都支持Python.记录一下Python基础语法好好练丹!!!
为什么使用IPython/Jupyter
IPython Notebook号称 “编码器的实验室笔记本” - 允许用户在单个基于浏览器的页面中交叉显示/执行数据,代码和说明文本,而不是在单独的文件中
Python基础关键字和语法
为什么学Python
简单方便代码少. 不用太关注类型, 声明等琐事. 使用灵活, 第三方支持包也多.
在深度学习中,经常会看到很多demo是用Python来写的,深度学习框架一般都有一个Python版的接口,目前主流的深度学习框架都支持Python.记录一下Python基础语法好好练丹!!!
为什么使用IPython/Jupyter
IPython Notebook号称 “编码器的实验室笔记本” - 允许用户在单个基于浏览器的页面中交叉显示/执行数据,代码和说明文本,而不是在单独的文件中
基础类型
python中的主要基本数据类型是数字(整数和浮点数),布尔值和字符串
Hello World!
1 |
|
Hello World!
1 |
|
Hello World!
1 |
|
1 |
|
The
makes a new line
1 |
|
The is a tab
1 |
|
I'm going to the movies
1 |
|
This is a string enclosed by "" not ''
1 |
|
Hello World
字符串操作
字符串是python的特殊类型。作为对象,在类中,您可以使用.methodName()表示法调用字符串对象上的方法。字符串类在python中默认可用,因此您不需要import语句即可将对象接口用于字符串。
1 |
|
hello world
HELLO WORLD
Hello World
1 |
|
1 |
|
Help on built-in function lower:
lower() method of builtins.str instance
Return a copy of the string converted to lowercase.
1 |
|
Type help() for interactive help, or help(object) for help about object.
1 |
|
['Hello', 'World']
1 |
|
['Hello', 'World']
1 |
|
'Hello World'
1 |
|
01
1 |
|
'000'
1 |
|
'FizzBuzz'
基础数学
有四种不同的数字类型:普通整数,长整数,浮点数和复数。另外,布尔值是普通整数的子类型。
1 |
|
2
1 |
|
128.0
1 |
|
128
1 |
|
65.0
1 |
|
65.0
1 |
|
6
1 |
|
8
1 |
|
0
if 语句
比较操作符 | 功能 |
---|---|
< | 小于 |
<= | 小于或等于 |
| 大于
= | 大于或等于
== | 等于
!= | 不等于
检查某些东西是否为True,如果是,则执行此操作。如果它不是True(False),则不执行
1 |
|
3
1 |
|
1 |
|
Fizz
1 |
|
Buzz
1 |
|
This was True
1 |
|
逻辑操作符 | 描述 |
---|---|
and | 如果两个操作数均为True,则condition变为True. |
or | 如果两个操作数中的任何一个为True,则condition变为True. |
not | 用于反转逻辑(不是False变为True,而不是True变为False |
1 |
|
True
1 |
|
4
1 |
|
True
1 |
|
4
1 |
|
1 |
|
False
else 语句
必须在if或elif语句之后。最多可以有一个其他声明。仅当上面的所有“if”和“elif”语句都为False时才会执行
1 |
|
1 |
|
number is not greater than 3
1 |
|
Hi
Task
- 将num分配给整数值。
- 如果整数是偶数,写一个if else组合将打印“你的整数是偶数”。否则,打印“你的整数是奇数”。
提示:任何可以精确地除以2的整数都是偶数(例如:2,4,6)。任何不能精确地除以2的整数都是奇数(例如:1,3,5)。使用模运算符(%),它将数字左边的余数除以右边的数字。
1 |
|
Your integer is odd
elif 语句
必须在if语句之后。 elif语句语句允许您检查True的多个表达式,并在其中一个条件求值为True时立即执行代码块。
与else类似,elif语句是可选的。但是,与其他情况不同,最多只能有一个语句,if后面可以有任意数量的elif语句。
1 |
|
num = 21
1 |
|
Your number is odd
1 |
|
You rolled a 1. Great job!
Task
- 将num分配给整数值。
- 编写一系列if,elif,else语句,打印您指定的num。但是对三的倍数要打印“Fizz”而不是数字, 五的倍数要打印“Buzz”。对于三和五共同的倍数则打印“FizzBuzz”
1 |
|
1 |
|
Buzz
1 |
|
1 |
|
FizzBuzz
列表
列表后面要加上方括号 [ ]
| | | |
— | — | — | — | —
z =| [3, | 7, | 4, | 2]
index | 0 | 1 | 2 | 3
1 |
|
访问列表里面的值
1 |
|
3
1 |
|
4
1 |
|
4
切分列表
1 |
|
[3, 7]
1 |
|
[3, 7, 4]
1 |
|
[7, 4, 2]
取列表的最大值, 最小值, 长度, 以及总和
1 |
|
2 7 4 16
对列表中对象出现次数进行统计
1 |
|
3
返回列表第一个指针
| | | | | |
— | — | — | — | — | — | —
random_list =| [4, | 1, | 5, | 4, | 10, | 4]
index=| 0 | 1 | 2 | 3 | 4 | 5
1 |
|
0
1 |
|
3
1 |
|
5
对列表进行排序
1 |
|
1 |
|
[2, 3, 4, 7, 8, 10, 11]
1 |
|
[11, 10, 8, 7, 4, 3, 2]
1 |
|
['Adam', 'Jessica', 'Lester', 'Michael', 'Monica', 'Rachel', 'Steve']
1 |
|
['Steve', 'Rachel', 'Monica', 'Michael', 'Lester', 'Jessica', 'Adam']
1 |
|
['Adam', 'Jessica', 'Lester', 'Michael', 'Monica', 'Rachel', 'Steve']
1 |
|
['Steve', 'Rachel', 'Monica', 'Michael', 'Lester', 'Jessica', 'Adam']
在列表结尾添加一个对象
1 |
|
[11, 10, 8, 7, 4, 3, 2]
1 |
|
[11, 10, 8, 7, 4, 3, 2, 3]
删除列表中一个对象
1 |
|
[11, 8, 7, 4, 3, 2, 3]
删除列表中指定位置的对象
1 |
|
[11, 8, 7, 4, 3, 2, 3]
1 |
|
4
1 |
|
[11, 8, 7, 3, 2, 3]
合并列表
通过在末尾续加的方式来延长列表
1 |
|
1 |
|
[11, 8, 7, 3, 2, 3, 4, 5]
1 |
|
x+y= [11, 8, 7, 3, 2, 3, 4, 5, 'Steve', 'Rachel', 'Monica', 'Michael', 'Lester', 'Jessica', 'Adam']
在列表指定位置前插入对象
1 |
|
[11, 8, 7, 3, 2, 3, 4, 5]
1 |
|
1 |
|
[11, 8, 7, 3, [4, 5], 2, 3, 4, 5]
字典
字典是将键(key)映射到值(value)的无序数据结构。值可以是任何值(列表,函数,字符串,任何东西)。键(key)必须是不可变的,例如,数字,字符串或元组。
示例
字典:我们查找的单词是key,查找的定义是值
1 |
|
1 |
|
{'person': 'a human being, whether an adult or child',
'marathon': 'a running race that is about 26 miles',
'resist': ' to remain strong against the force or effect of (something)',
'run': 'to move with haste; act quickly'}
访问字典中的值
1 |
|
'a running race that is about 26 miles'
更新字典
1 |
|
'an external covering for the human foot'
1 |
|
{'person': 'a human being, whether an adult or child',
'marathon': 'a running race that is about 26 miles',
'resist': ' to remain strong against the force or effect of (something)',
'run': 'to move with haste; act quickly',
'shoe': 'an external covering for the human foot, usually of leather and consisting of a more or less stiff or heavy sole and a lighter upper part ending a short distance above, at, or below the ankle.',
'shirt': 'a long- or short-sleeved garment for the upper part of the body'}
1 |
|
{'person': 'a human being, whether an adult or child',
'marathon': 'a running race that is about 26 miles',
'run': 'to move with haste; act quickly',
'shoe': 'an external covering for the human foot, usually of leather and consisting of a more or less stiff or heavy sole and a lighter upper part ending a short distance above, at, or below the ankle.',
'shirt': 'a long- or short-sleeved garment for the upper part of the body'}
不是所有东西都可以当作Key
下方是错误用法示例
1 |
|
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-7f0c73a86aa1> in <module>
----> 1 webstersDict[['sock']] = 'a short stocking usually reaching to the calf or just above the ankle.'
TypeError: unhashable type: 'list'
使用get()方法返回给定键的值
你会明白为什么这在字数统计任务中如此有价值
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
删除键,但同时可以返回值
1 |
|
遍历字典
1 |
|
1 |
|
1 |
|
person a human being, whether an adult or child
marathon a running race that is about 26 miles
run to move with haste; act quickly
shoe an external covering for the human foot, usually of leather and consisting of a more or less stiff or heavy sole and a lighter upper part ending a short distance above, at, or below the ankle.
shirt a long- or short-sleeved garment for the upper part of the body
元组
元组是一种序列,就像列表一样。元组和列表之间的区别在于,与列表(可变)不同,元组不能更改(不可变)。
元组使用括号,而列表使用方括号。
初始化一个元组
有两种方法可以初始化空元组。您可以通过让()没有值来初始化空元组
1 |
|
您还可以使用元组函数初始化空元组。
1 |
|
可以通过用逗号分隔值的序列来初始化具有值的元组。
1 |
|
重要的是要记住,如果要创建仅包含一个值的元组,则需要在项目后面添加一个逗号。
1 |
|
访问元组内的值
元组中的每个值都有一个指定的索引值。值得注意的是,python是一种基于零索引的语言。所有这些意味着元组中的第一个值是索引0。
1 |
|
3
Python还支持负索引。负索引从元组结束开始。使用负索引来获取元组中的最后一项有时会更方便,因为您不必知道元组的长度来访问最后一项。
1 |
|
2
提醒一下,您也可以使用正索引访问相同的项目(如下所示)。
1 |
|
2
切分元组
切分操作返回包含所请求项的新元组。切分很适合在元组中获取值的子集。对于下面的示例代码,它将返回一个元组,其中包含索引0的对象,而不包括索引2的对象。
1 |
|
(3, 7)
1 |
|
(3, 7, 4)
负索引也OK
1 |
|
(3, 7, 4)
元组是不可改变的
元组是不可变的,这意味着在初始化元组之后,不可能更新元组中的单个项。正如您在下面的代码中所看到的,您无法更新或更改元组项的值(这与可变的Python列表不同)。
下方有错误示例
1 |
|
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-19-79aed936fbd0> in <module>
1 z = (3, 7, 4, 2)
2
----> 3 z[1] = "fish"
TypeError: 'tuple' object does not support item assignment
即使元组是不可变的,也可以采用现有元组的一部分来创建新的元组,如下例所示。
1 |
|
Tuple方法
在开始本节之前,让我们首先初始化一个元组
1 |
|
index 方法(索引)
index方法返回对应值的第一个索引
1 |
|
count 方法(计数)
count方法返回值在元组中出现的次数。
1 |
|
遍历元组
您可以使用for循环遍历元组的项目
1 |
|
元组拆包
元组对序列解包非常有用
1 |
|
枚举
枚举函数返回一个元组,其中包含每次迭代的计数(从默认为0的开始)和迭代序列获得的值
1 |
|
元组相对列表的优势
列表和元组是标准Python数据类型,用于在序列中存储值。元组是不可变的,而列表是可变的。以下是元组列表的一些其他优点
组比列表更快。如果你要定义一组常量值,那么你将要做的就是迭代它,使用元组而不是列表。可以使用timeit库部分测量性能差异,该库允许您为Python代码计时。下面的代码为每个方法运行代码100万次,并输出所花费的总时间(以秒为单位)。
1 |
|
元组可以用作字典键
一些元组可以用作字典键(特别是包含不可变值的元组,如字符串,数字和其他元组)。列表永远不能用作字典键,因为列表不是不可变的
1 |
|
{('this', 'is'): 23, ('is', 'a'): 12, ('a', 'sentence'): 2}
列表不可以用作字典键
1 |
|
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-21-79ec3fbad604> in <module>
1 bigramsListDict = {['this', 'is']: 23,
2 ['is', 'a']: 12,
----> 3 ['a', 'sentence']: 2}
4
5 print(bigramsListDict)
TypeError: unhashable type: 'list'
元组可以是集合中的值
1 |
|
列表不可以是集合中的值
1 |
|
Task: 用Python生成斐波那契序列
Fibonacci序列是一个整数序列,其特征在于前两个之后的每个数字是前两个数字的总和。根据定义,Fibonacci序列中的前两个数字是1和1,或0和1,具体取决于所选择的序列起点,以及每个后续数字是前两个数字的总和。
1 |
|
1.使用循环,编写一个Python程序,打印出前10个Fibonacci数
1 |
|
For 循环
For循环是迭代对象元素的常用方法(在第一个示例中,列表)
具有可迭代方法的任何对象都可以在for循环中使用。
python的一个独特功能是代码块不被{} 或begin,end包围。相反,python使用缩进,块内的行必须通过制表符缩进,或相对于周围的命令缩进4个空格。
虽然这一开始可能看起来不直观,但它鼓励编写更易读的代码,随着时间的推移,你会学会喜欢它
1 |
|
23
41
12
16
7
Hi
枚举
返回一个元组,其中包含每次迭代的计数(从默认为0开始)和迭代序列获得的值:
1 |
|
0 steve
1 rachel
2 michael
3 adam
4 monica
Task
从文本中删除标点符号并将最终产品转换为列表:
On a dark desert highway, cool wind in my hair Warm smell of colitas, rising up through the air Up ahead in the distance, I saw a shimmering light My head grew heavy and my sight grew dim I had to stop for the night There she stood in the doorway; I heard the mission bell And I was thinking to myself, “This could be Heaven or this could be Hell” Then she lit up a candle and she showed me the way
(加州旅馆)
1 |
|
1 |
|
On a dark desert highway, cool wind in my hair Warm smell of colitas, rising up through the air Up ahead in the distance, I saw a shimmering light My head grew heavy and my sight grew dim I had to stop for the night There she stood in the doorway; I heard the mission bell And I was thinking to myself, "This could be Heaven or this could be Hell" Then she lit up a candle and she showed me the way
基本上,任何具有可迭代方法的对象都可以在for循环中使用。即使是字符串,尽管没有可迭代的方法 - 但我们不会在这里继续。具有可迭代方法基本上意味着数据可以以列表形式呈现,其中有序地存在多个值。
1 |
|
On a dark desert highway cool wind in my hair Warm smell of colitas rising up through the air Up ahead in the distance I saw a shimmering light My head grew heavy and my sight grew dim I had to stop for the night There she stood in the doorway I heard the mission bell And I was thinking to myself This could be Heaven or this could be Hell Then she lit up a candle and she showed me the way
1 |
|
['On',
'a',
'dark',
'desert',
'highway',
'',
'cool',
'wind',
'in',
'my',
'hair',
'Warm',
'smell',
'of',
'colitas',
'',
'rising',
'up',
'through',
'the']
1 |
|
0
1 |
|
1 |
|
1 |
|
['On',
'a',
'dark',
'desert',
'highway',
'cool',
'wind',
'in',
'my',
'hair',
'Warm',
'smell',
'of',
'colitas',
'rising',
'up',
'through',
'the',
'air',
'Up']
Continue
continue语句将转到循环的下一次迭代
continue语句用于忽略某些值,但不会中断循环
1 |
|
['a',
'dark',
'desert',
'highway',
'cool',
'wind',
'in',
'my',
'hair',
'Warm',
'smell',
'of',
'colitas',
'rising',
'up',
'through',
'the',
'air',
'Up']
Break
break语句将完全打断循环
1 |
|
1 |
|
I found the word I was looking for
['On', 'a', 'dark']
Task (顺道介绍一下Range函数)
- 编写一个Python程序,它迭代整数从1到50(使用for循环)。对于偶数的整数,将其附加到列表even_numbers。对于奇数的整数,将其附加到奇数奇数列表中
1 |
|
1 |
|
Even Numbers: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50]
1 |
|
Odd Numbers: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]
While 循环
For 循环 | While 循环 |
---|---|
遍历一组对象 | 条件为false时自动终止 |
没有break也可以结束 | 使用break语句才能退出循环 |
如果我们希望循环在某个时刻结束,我们最终必须使条件为False
1 |
|
0
1
2
3
4
5
break语句
使用break可以完全退出循环
1 |
|
1
2
while True条件使得除非遇到break语句,否则不可能退出循环
如果您陷入无限循环,请使用计算机上的ctrl + c来强制终止
1 |
|
1
2
Found 2
提醒:使用模运算符(%),它将数字左边的余数除以右边的数字
1 |
|
1
1 |
|
0
比较操作符 | 功能 |
---|---|
< | 小于 |
<= | 小于或等于 |
| 大于
= | 大于或等于
== | 等于
!= | 不等于
1 |
|
2
3
4
5
当我们知道要循环多少次时,Range很有用
下面例子是: 从0开始,但不包括5
1 |
|
[0, 1, 2, 3, 4]
1 |
|
[1, 2, 3, 4]
[2, 3, 4]
[3, 4]
[4]
[]
函数
Python中的函数是什么?
在Python中,function是一组执行特定任务的相关语句。
函数有助于将我们的程序分解为更小的模块化块。随着我们的计划越来越大,功能使其更加有条理和易于管理。
此外,它避免重复并使代码可重用
创建函数的语法
1 |
|
上面显示的是一个函数定义,它由以下组件组成。
- 关键字def标记函数头的开始。
- 用于唯一标识它的函数名称。函数命名遵循在Python中编写标识符的相同规则。
- 参数(参数),我们通过它将值传递给函数。它们是可选的。
- 冒号(:)标记函数头的结尾。
- 用于描述函数功能的可选文档字符串(docstring)。
- 构成函数体的一个或多个有效的python语句。语句必须具有相同的缩进级别(通常为4个空格)。
- 用于从函数返回值的可选return语句。
如何在python中调用函数?
一旦我们定义了一个函数,我们就可以从另一个函数,程序甚至Python提示符中调用它。要调用函数,我们只需使用适当的参数键入函数名称
1 |
|
Hello, Emma. Good morning!
文档字符串
函数头之后的第一个字符串称为docstring,是文档字符串的缩写。它用于简要解释函数的作用。
虽然可选,但文档是一种很好的编程习惯。除非你能记住你上周吃的晚餐,否则请记录你的代码。
在上面的示例中,我们在函数头的正下方有一个docstring。我们通常使用三引号,以便docstring可以扩展到多行。我们可以将此字符串作为函数的__doc__属性使用。
例如:
1 |
|
This function greets to
the person passed in as
parameter
返回语句
return语句用于退出函数并返回到调用函数的位置。如下:
1 |
|
此语句可以包含要求求值的表达式,并返回值。如果语句中没有表达式,或者函数内部不存在return语句本身,则该函数将返回None对象。
例如:
1 |
|
Hello, May. Good morning!
None
这里,None是返回值
再举个例子
1 |
|
2
4
变量的范围和寿命
变量的范围是程序中识别变量的部分。函数内定义的参数和变量在外部不可见。因此,它们具有局部范围。
变量的生命周期是变量在存储器中退出的时间段。函数内部变量的生命周期与函数执行的时间一样长。
一旦我们从函数返回它们就会被销毁。因此,函数不记得先前调用的变量值。
下面是一个示例,用于说明函数内部变量的范围。
1 |
|
('Value inside function:', 10)
('Value outside function:', 20)
在这里,我们可以看到x的值最初为20。即使函数my_func()将x的值更改为10,它也不会影响函数外部的值。
这是因为函数内部的变量x与外部的变量x不同(函数的本地)。尽管它们具有相同的名称,但它们是两个具有不同范围的不同变量。
另一方面,函数外部的变量从内部可见。它们具有全局范围。
我们可以从函数内部读取这些值,但不能更改(写入)它们。为了修改函数外部变量的值,必须使用关键字global将它们声明为全局变量。
参数
在上面的案例中,我们学习了定义函数并调用它。否则,函数调用将导致错误。这是一个例子。
1 |
|
('Hello', 'Monica, Good morning!')
这里,函数greet()有两个参数。
因为,我们用两个参数调用了这个函数,它运行顺畅,我们不会收到任何错误。
如果我们用不同数量的参数调用它,解释器会报错。下面是对此函数的调用,其中包含一个参数,没有参数及其各自的错误消息。
1 |
|
TypeErrorTraceback (most recent call last)
<ipython-input-9-7765bb020128> in <module>()
----> 1 greet("Monica")
2
3 greet()
TypeError: greet() takes exactly 2 arguments (1 given)
变量函数参数
到目前为止,函数具有固定数量的参数。在Python中,还有其他方法可以定义一个可以接受可变数量参数的函数。
下面描述这种类型的三种不同形式。
Python默认参数
函数参数可以在Python中具有默认值。
我们可以使用赋值运算符(=)为参数提供默认值。这是一个例子。
1 |
|
('Hello', 'Kate, Good morning!')
('Hello', 'Bruce, How do you do?')
在此函数中,参数名称没有默认值,在调用期间是必需的(必需)。
另一方面,参数msg的默认值为“早上好!”。因此,在通话期间它是可选的。如果提供了值,它将覆盖默认值。
函数中的任意数量的参数都可以具有默认值。但是一旦我们有一个默认参数,它右边的所有参数也必须有默认值。
这意味着,非默认参数不能遵循默认参数。例如,如果我们将上面的函数头定义为:
1 |
|
我们会收到一个错误:
1 |
|
Python关键字参数
当我们调用具有某些值的函数时,这些值将根据其位置分配给参数。
例如,在上面的函数greet()中,当我们将其称为greet(“Bruce”,“how do you do?”)时,值“Bruce”被赋值给参数名称,类似地how do you do消息
Python允许使用关键字参数调用函数。当我们以这种方式调用函数时,可以更改参数的顺序(位置)。以下对上述函数的调用都是有效的,并产生相同的结果。
1 |
|
我们可以看到,我们可以在函数调用期间将位置参数与关键字参数混合使用。但我们必须记住,关键字参数必须遵循位置参数。
在关键字参数之后使用位置参数将导致错误。
Python任意参数
有时,我们事先并不知道将传递给函数的参数数量.Python允许我们通过具有任意数量参数的函数调用来处理这种情况。
在函数定义中,我们在参数名称前使用星号(*)来表示这种参数。这是一个例子。
1 |
|
('Hello', 'Monica')
('Hello', 'Luke')
('Hello', 'Steve')
('Hello', 'John')
在这里,我们使用多个参数调用该函数。这些参数在传递给函数之前被包装到元组中。在函数内部,我们使用for循环来检索所有参数。
Python函数: 在列表中移除重复对象
1 |
|
[2, 4, 10, 20, 5]
当你使用return语句时,另一件值得一提的事是你可以用它来返回多个值。因此,您可以使用元组。
Python面向对象编程
在本文中,您将学习Python中的OOP的以下基本概念:
- Python类
- 对象实例
- 定义和使用方法
- OOP继承
什么是面向对象编程(OOP)?
面向对象编程(Object-oriented Programming,简称OOP)是一种编程范例,它提供了一种结构化程序的方法,以便将属性和行为捆绑到单个对象中。
例如,对象可以表示具有姓名属性,年龄,地址等的人,具有行走,说话,呼吸和跑步等行为。或者包含收件人列表,主题,正文等属性的电子邮件,以及添加附件和发送等行为。
换句话说,面向对象编程是一种, 可以为具体现实世界的事物建模的方法,如汽车以及公司和员工,学生和教师等事物之间的关系. OOP将现实世界的实体建模为软件对象,以及与之相关的数据,并可以执行某些功能。
另一种常见的编程范例是函数式编程,其构造类似于顺序执行的程序,因为它以函数和代码块的形式提供一组执行步骤,这些步骤一步步执行以完成任务。
关键的一点是,对象是面向对象编程范例的核心,不仅在函数编程中表示数据,而且在程序的整体结构中也是如此。
注意:由于Python是一种多范式编程语言(也就是说面向对象或者函数式编程都是可以的),您可以选择最适合手头问题的范例,在一个程序中混合使用不同的范例,和/或随着程序的发展从一种范例切换到另一种范例。
Python中的类
首先关注数据,每个事物或对象都是某个类的实例。
Python中可用的原始数据结构(如数字,字符串和列表)旨在分别表示简单的事物,例如某事物的成本,诗歌的名称和您喜欢的颜色。
如果你想代表更复杂的东西怎么办?
例如,假设您想跟踪许多不同的动物。如果您使用了列表,则第一个元素可以是动物的名称,而第二个元素可以表示其年龄。
你怎么知道哪个元素应该是哪个?如果你有100种不同的动物怎么办?你确定每只动物都有名字和年龄,等等吗?如果你想为这些动物添加其他属性怎么办?这就是为什么我们需要一个”类”(Class)。
类可以用来创建新的用户定义的数据结构,其中包含有关内容的任意信息。对于动物,我们可以创建一个Animal( )类来跟踪关于Animal的属性,如名称和年龄。
注意, 一个类只提供结构 - 它是应该如何定义某个东西的蓝图,但它实际上并不提供任何真实的内容. Animal( )类可以指定名称和年龄, 是定义动物所必需的,但它实际上不会包含特定动物的名字或年龄。
可以将”类”视为”某事物的定义”.
Python对象(实例)
虽然类是蓝图,但实例是具有实际值的类的副本,字面上是属于特定类的对象。这不再是一个想法;它是一只真正的动物,就像一只名叫罗杰的狗,已经八岁了。
换句话说,类就像一个表格或问卷。它定义了所需的信息。填写表格后,您的特定副本就是该类的一个实例;它包含与您相关的实际信息。
您可以填写多个副本以创建许多不同的实例,但如果没有表单作为指导,您将会彻底迷失,不知道需要哪些信息。因此,在创建对象的单个实例之前,我们必须首先通过定义类来指定所需的内容。
如何在Python中定义类
在Python中定义类很简单:
1 |
|
首先使用class关键字指示您正在创建一个类,然后添加该类的名称(使用骆驼命名法,以大写字母开头。)
另外,我们在这里使用了Python关键字pass。这经常被用作代码最终会占用的占位符。它允许我们运行此代码, 而不会抛出错误。
注意:上面的代码在Python 3上是正确的。在Python 2.x(“遗留Python”)上,您将使用稍微不同的类定义:
1
2
3
>#Python 2.x类定义:
>class Dog(object):
Pass括号中的(对象)部分指定了您继承的父类(更多内容见下文。)在Python 3中,这不再是必需的,因为它采用隐式默认值。
实例属性
所有类都需要创建对象,所有对象都包含称为属性的特征(在开头段落中称为属性)。使用__init __()方法通过为对象的初始属性提供其默认值(或状态)来初始化(例如,指定)对象的初始属性。此方法必须至少有一个参数以及自变量,它引用对象本身(例如,Dog)。
1 |
|
在我们的Dog()类中,每只狗都有一个特定的名字和年龄,这对于你何时开始真正创造不同的狗来说显然很重要。请记住:该类仅用于定义狗,而不是实际创建具有特定名称和年龄的个体狗的实例;我们很快就会谈到这一点。
类似地,自变量也是类的实例。由于类的实例具有不同的值,我们可以声明Dog.name = name而不是self.name = name。但由于并非所有狗都拥有相同的名称,我们需要能够为不同的实例分配不同的值。因此需要特殊的自变量,这将有助于跟踪每个类的各个实例。
注意:您永远无需主动调用__init __()方法;当你创建一个新的’Dog’实例时会自动调用它。
类属性
虽然实例属性特定于每个对象,但类属性对于所有实例都是相同的 - 在这种情况下,属性都来自狗。
1 |
|
因此,虽然每只狗都有一个独特的名字和年龄,但每只狗都是哺乳动物。
让我们创造一些狗……
实例化对象
实例化是创建一个新的,唯一的类实例的意思。
1 |
|
我们首先定义一个新的Dog()类,然后创建两个新的狗,每个狗分配给不同的对象。因此,要创建类的实例,请使用类名,后跟括号。然后为了证明每个实例实际上是不同的,我们实例化了两个狗,将每个狗分配给一个变量,然后测试这些变量是否相等。
您认为类实例的类型是什么?
1 |
|
让我们看一个稍微复杂的例子…..
1 |
|
Philo is 5 and Mikey is 6.
Philo is a mammal!
注意:请注意我们如何使用点表示法来访问每个对象的属性。
这是怎么回事?
我们创建了Dog()类的新实例,并将其分配给变量philo。然后我们通过了两个论点,“Philo”和5,分别代表狗的名字和年龄。
这些属性将传递给__init__方法,该方法在您创建新实例时将其调用,并将名称和年龄附加到对象。您可能想知道为什么我们不必传递自我论证。
这是Python魔法: 当你创建一个新的类实例时,Python会自动确定self是什么(在本例中是一个Dog)并将其传递给__init__方法。
练习
用相同的Dog类,实例化三只新狗,每只狗的年龄不同。然后编写一个名为get_biggest_number()的函数,它接受任意数量的年龄并返回最旧的函数。然后输出最老的狗的年龄.
实例方法
实例方法在类中定义,用于获取实例的内容。
它们还可用于使用对象的属性执行操作。与__init__方法一样,第一个参数始终是self:
1 |
|
Mikey is 6 years old
Mikey says Gruff Gruff
在后一种方法中,我们定义了行为speak()。您可以为狗分配哪些其他行为?回顾一下开头的段落,看看其他对象的一些示例行为。
修改属性
您可以根据某些行为更改属性的值:
1 |
|
False
True
在这里,我们添加了一种发送电子邮件的方法,该方法将is_sent变量更新为True。
Python对象继承
继承是一个类采用另一个类的属性和方法的过程。新形成的类称为子类,子类派生的类称为父类。
重要的是要注意子类覆盖或扩展父类的功能(例如,属性和行为)。换句话说,子类继承了父项的所有属性和行为,但也可以添加不同行为。最基本的类是一个对象,通常所有其他类都继承为它们的父对象。
定义新类时,Python 3隐式使用object作为父类。所以以下两个定义是等价的:
1 |
|
注意:在Python 2.x中,新风格类和旧风格类之间存在区别。不在这里详细介绍,但是通常希望您将对象指定为父类,以确保在编写Python 2 OOP代码时定义新样式类。
狗公园示例
让我们假装我们在一个狗公园。有多个Dog对象, 发起不同的Dog行为,每个对象都有不同的属性。一般来说,这意味着有些狗正在跑步,而有些正在伸展,有些正在盯着其他狗。此外,每只狗都由它的主人命名,并且由于每只狗都是活生生的, 各个年龄段的都有。
将一只狗与另一只狗区分开来的另一种方法是什么?狗的品种怎么样:
1 |
|
German Shepard
Boston Terrier
每种犬的行为略有不同。考虑到这些因素,让我们为每个品种创建单独的类。这些是父类Dog的子类。
扩展父类的功能
运行下方代码:
1 |
|
Jim is 12 years old
Jim runs slowly
您完成此程序时,请仔细阅读代码, 以搞清其中的原理,然后在运行程序之前,先在大脑中预测一下输出结果, 然后和真正的输出结果比对一下, 看看是否一致.
我们没有添加任何特殊属性或方法来区分RussellTerrier和Bulldog,但由于它们现在是两个不同的类,我们可以为它们添加一个速度的类属性。
父类与子类
isinstance()函数用于确定实例是否也是某个父类的实例。
1 |
|
Jim is 12 years old
Jim runs slowly
True
True
False
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-c976ae4d1a2c> in <module>
52
53 # Is julie and instance of jim?
---> 54 print(isinstance(julie, jim))
TypeError: isinstance() arg 2 must be a type or tuple of types
看得懂吗? jim和julie都是Dog()类的实例,而johnnywalker不是Bulldog()类的实例。然后作为一个完整性检查,我们测试了julie是否是jim的实例,这是不可能的,因为jim是类的实例而不是类本身 - 因此是TypeError的原因。
覆盖父类的功能
请记住,子类也可以覆盖父类的属性和行为。举些例子:
1 |
|
SomeBreed()类从父类继承物种,而SomeOtherBreed()类覆盖物种,将其设置为爬行动物~~~~~~~~
练习: 狗狗继承
创建一个容纳狗的实例的Pets类;这个类与Dog类完全分开。换句话说,Dog类不会继承Pets类。然后将三个dog实例分配给Pets类的实例。从下面的代码开始。将文件另存为pets_class.py。您的输出应如下所示:
I have 3 dogs.
Tom is 6.
Fletcher is 7.
Larry is 9.
And they’re all mammals, of course.
练习: 狗狗饿不饿
使用相同的文件,将一个实例属性is_hungry = True添加到Dog类。然后添加一个名为eat()的方法,在调用时将is_hungry的值更改为False。找出喂养每只狗的最佳方式,然后输出“我的狗饿了。”如果所有人都饿了或“我的狗不饿”。如果所有人都不饿。最终输出应如下所示:
I have 3 dogs.
Tom is 6.
Fletcher is 7.
Larry is 9.
And they’re all mammals, of course.
My dogs are not hungry.