深度学习(1) Python基础

关于Python

变量类型与输出语句

编程基础

⚫ 敲代码时切换到英文输入法,所有符号均为英文状态
⚫ Python 的注释以 # 开头为标志,注释单独成行,或放在某语句右侧
⚫ Python 是动态输入类型的语言,像 Matlab 一样,变量类型是动态推断的
⚫静态类型的 C 语言须声明变量类型,如 int a = 1,而 Python 只需要 a =1
⚫ 编程语言中的 a = 1 的含义是——将数值 1 赋给变量 a
⚫ Python 里换行符(回车)可以替代分号(;),所以一般不出现分号
⚫ Python 里四个空格是一个缩进,不要随意在某行代码的开头输入空格

变量类型

⚫ 像 C 语言和 Matlab 一样,变量名由字母、数字、下划线组成(但不能以数字开头),字母区分大小写,变量名不能与内置的函数同名
⚫ 根据变量是否可以充当容器,将变量类型分为基本类型和高级类型
基本变量类型:字符串、数字、布尔型
高级变量类型:集合、元组、列表、字典
七种变量类型,示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 字符串(str)
str_v = "a real man"

# 数字(int 或 float)
num_v = 415411

# 布尔型(bool)
bool_v = True

# 集合(set)
set_v = {1, 2, 3, 1}

# 元组(tuple)
tuple_v = (1, 2, 3)

# 列表(list)
list_v = [1, 2, 3]

# 字典(dict)
dict_v = {'a':1, 'b':2 , 'c':3 }

输出语句

Python 语言的标准输出方法是:print(变量名)。Jupyter 中增加一种独特的输出方法,即在一个代码块内的最后一行写上变量名,即可输出该变量的数值。以上两种输出方法完全等效
print 函数的原理是输出仅一个单独的变量,它只有这一种用法,其它的各种用法要么是输出了f字符串,要么是输出了元组

基本变量类型

字符串

字符串的结构

字符串用引号括起来,双引号和单引号都可以

1
2
str1 = 'A real man, he knows what he needs to do.'
str2 = "A real man, he knows what he needs to do."

当字符串变量内含有单引号,就用双引号来表示该字符串
当字符串变量内含有双引号,就用单引号来表示该字符串

1
2
str1 = "Jack's book is in his home."
str2 = 'He said "Rose".'

输出语句的经典用法

想在字符串中插入其它变量,可使用“f字符串”的方法,代码示例如下

1
2
3
4
str1 = "money path"
str2 = "doctor"
str3 = f"You ruined his {str1}. You ruined his {str2}."
str3

正是有了 f 字符串,才能实现如下输出,这也是 print 最常见的使用场景

1
2
answer = 0.98 # 经过一系列运算,测试集给出准确率为 98%
print(f"测试集的准确率为: {answer}")

注意,这里的 print 依然只输出了一个单独的变量,即一个单独的 f 字符串

输出语句的转义字符

在字符串中添加转义字符,如换行符\n 与制表符\t,可增加 print 的可读性。同时,转义字符只有在 print 里才能生效,单独对字符串使用无效

1
2
3
4
5
6
# 构建字符串
message = "Shop sells:\n\tlitchi, \n\tfritters, \n\tfried fish."
# 单独输出字符串
message
# 转义字符在 print 里生效
print(message)

数字

整数型数字和浮点型数字

数字有两种数据类型,分别是整数(int)和浮点数(float)。这里暂时不用太过区分二者,进入下一节《NumPy 数组库》时才要注意区分

常用运算符

布尔型

布尔型只有两个值(True 和 False),通常是基于其它变量类型来进行生成

基于基本变量类型生成

⚫ 对字符串作比较,使用等于号==与不等号!= ⚫ 对数字作比较,使用大于>、大于等于>=、等于==、小于<、小于等于<=

1
2
3
4
5
6
7
8
9
# 字符串——检查某字符串的值
str_v = 'cxk'
print(str_v == 'chicken')
print(str_v != 'chicken')
# 数字——检查某数字是否在某范围
num_v = 3
print(num_v > 5)
print(num_v == 5)
print(num_v < 5)

基于高级变量类型生成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 集合——检查某变量是否在该集合中
set_v = {1, 2, 3}
print(2 in set_v)
print(2 not in set_v)
# 元组——检查某变量是否在该元组中
tuple_v = (1, 2, 3)
print(2 in tuple_v)
print(2 not in tuple_v)
# 列表——检查某变量是否在该列表中
list_v = [1, 2, 3]
print(2 in list_v)
print(2 not in list_v)
# 字典——检查某变量是否在该字典中
dict _v = {'a':1, 'b':2, 'c':3}
print( 2 in dict _v.values() )
print( 2 not in dict _v.values() )

同时检查多个条件

and 的规则是,两边全为 True 则为 True,其它情况均为 False or 的规则是,两边有一个是 True 则为 True,其他情况为 False

1
2
3
4
5
6
7
# 先产生两个布尔值
T = True
F = False
# and 示例
T and F
# or 示例
T or F

除了 and 和 or,还在一个布尔值前面加上 not,如 not True 就是 False

判断语句

bool 值通常作为 if 判断的条件,if 判断的语法规则为

if 布尔值:
情况一
elif 布尔值:
情况二
else:
其它情况

注意事项:
⚫ Python 的循环、判断、函数和类中均不使用 end 来表示代码块的结束
Python 常常利用缩进(即四个空格)来表示代码块的范围
每一个判断条件的最后有一个冒号,不要遗漏
⚫ if 语句中,if:只出现 1 次,elif:可出现 0 至∞次,else:可出现 0 或 1 次
示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
bool1 = False
bool2 = False
bool3 = False
if bool1:
 print('当 bool1 为 True,此行将被执行')
elif bool2:
 print('否则的话,当 bool2 为 True,此行将被执行')
elif bool3:
 print('否则的话,当 bool3 为 True,此行将被执行')
else:
 print('否则的话,此行将被执行')

基本变量间的转换

字符串、整数、浮点数、布尔型四者之间可以无缝切换
⚫ 转换为字符串使用 str 函数
⚫ 转换为整数型数字使用 int 函数
⚫ 转换为浮点型数字使用 float 函数
⚫ 转换为布尔型使用 bool 函数
示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 定义变量
str_v = '123'
int_v = 123
float_v = 123.0
bool_v = True
# 转化为字符串
print( str( int_v ) )
print( str( float_v ) )
print( str( bool_v ) )
# 转化为整数型变量
print( int( str_v ) )
print( int( float_v ) )
print( int( bool_v ) )
# 转化为浮点型变量
print( float( str_v ) )
print( float( float_v ) )
print( float( bool_v ) )
# 转化为布尔型变量
print( bool( str_v ) )
print( bool( int_v ) )
print( bool( float_v ) )

注:其它变量转为布尔型变量时,只有当字符串为空、数字为 0、集合为空、元组为空、列表为空、字典为空时,结果才为 False

高级变量类型

高级变量类型,即集合、元组、列表、字典,它们有一个共同的特点:作为容器,它们可以随意容纳任意变量(甚至在同一个容器内包含 7 种变量类型)

集合

集合是无序的、不可重复的元素的组合
可以用两种方式创建集合:通过 set 函数或使用大括号,示例如下:

1
2
3
4
# 使用 set()函数将列表转化为集合
set( [3,2,9,1,8,1,5,0,3,5] )
# 使用大括号创建
{'3','2','9','1','8','1','5','0','3','5'}

注意:请勿用大括号创建空集合,否则会被误认为是字典
集合出现次数稀少,它更多的是被看作是字典的索引(即数据的标签)。后面会学习 Pandas 库,可替代集合

元组

与列表不同!!!

创建元组

有两种方式可以创建元组,一种是规范括号法,一种是省略括号法

1
2
3
4
# 规范的括号法
(1, 2, 3)
# 省略括号法(核心)
1, 2, 3

输出语句中的元组法

高级变量类型都可以容纳所有的变量类型,如示例所示:

1
2
# 一个释放自我的元组
'a', 1, True, {1,2,3},(1,2,3),[1,2,3],{'a':1, 'b':2, 'c':3}

如果你在 print 里忽然见到逗号,不必大惊小怪,示例如下:

1
2
3
4
# 元组法替代 f 字符串
answer = 98
print(f'最终答案为: {answer}') # f 字符串法
print('最终答案为: ', answer) # 元组法

缺点:输出的元素之间含有一个空格

元组拆分法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 元组拆分法——极速创建新变量
a,b,c = 1,2,3
print(c,b,a)
# 元组拆分法——极速交换变量值
a,b = 1,2
b,a = a,b
print(a,b)
# 元组拆分法——只要前两个答案
values = 98, 99, 94, 94, 90, 92
a, b, *rest = values
a, b, rest

列表

创建列表

列表由若干个有序的变量组成,其中的元素之间可以无任何关系。列表出现的标志是中括号,列表里的变量使用逗号分隔,示例如下:

1
2
3
4
5
6
7
8
9
# 一个全是字符串的列表
list1 = ['Bro.chicken', '30 months', 'Marry Pd']
list1
# 一个全是数字的列表
list2 = [11, 45, 14]
list2
# 一个释放自我的列表
list3= ['cxk', 666, True, set([1,2,3]), (1,2,3), [1,2,3], {'a':1, 'b':2, 'c':3}]
list3

列表可以容纳各种变量类型,其代价是——列表要单独存储 每一个元素的变量类型,列表越大越占空间。

访问与修改某个元素

访问列表元素时使用中括号,索引由 0 开始,示例如下:

1
2
3
list3 = ['cxk', 666, True, set([1,2,3]), (1,2,3), [1,2,3], {'a':1}]
print(list3[0])
print(list3[5])

当想访问列表倒数第一个元素时,可使用 a[-1];当想访问倒数第二个元素,可使用 a[-2];以此类推。代码示例如下:

1
2
list4 = ['a', 'b', 'c']
print( ( list4[-3] , list4[-2] , list4[-1] ) )

可以通过访问某列表元素的方式对其数值进行修改。

1
2
3
list4 = ['a', 'b', 'c']
list4[-1] = 5
list4

切片——访问部分元素

切片,就是列表的一部分。如图所示
索引负责其指向区域的右侧一个单元格
当明确知道从第 x 个元素切到第 y 个元素,示例为

1
2
3
4
5
list_v = ['a', 'b', 'c', 'd', 'e']
print( list_v )
print( list_v[ 1 : 4 ] ) # 从索引[1]开始,切到索引[4]之前
print( list_v[ 1 : ] ) # 从索引[1]开始,切到结尾
print( list_v[ : 4 ] ) # 从列表开头开始,切到索引[4]之前

当明确切除列表的开头与结尾,如示例所示

1
2
3
4
5
list_v = ['a', 'b', 'c', 'd', 'e']
print( list_v )
print( list_v[ 2 : -2 ] ) # 切除开头 2 个和结尾 2 个
print( list_v[ : -2 ] ) # 切除结尾两个
print( list_v[ 2 : ] ) # 切除开头两个

当明确隔几个元素采样一次时,示例如下

1
2
3
4
list_v = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
print( list_v[ : : 2 ] ) # 每 2 个元素采样一次
print( list_v[ : : 3 ] ) # 每 3 个元素采样一次
print( list_v[ 1 : -1 : 2 ] ) # 切除一头一尾后,每 2 个元素采样一次

值得注意的是,对列表进行切片后得到一个新的对象,与原列表变量相互独立,如示例所示。但是若存储几百万条数据,这无疑对电脑是一种全新的考验

1
2
3
4
5
6
7
8
9
# 创建 list_v 的切片 cut_v
list_v = [1, 2, 3]
cut_v = list_v[ 1 : ]
cut_v
# 修改 cut_v 的元素
cut_v[1] = 'a'
cut_v
# 输出 list_v,其不受切片影响
list_v

列表元素的添加

列表可以使用 + 和 * 来添加原列表,示例如下

1
2
3
4
5
list1 = [1,2,3]
print( list1 + [4] ) # 列表尾部添加一个元素
print( list1 + [10,11,12] ) # 与另一个列表连接
print( list1 * 2 ) # 复制两倍的自己
print( list1 * 4 ) # 复制四倍的自己

字典

创建字典

字典可以理解为升级版的列表,每个元素的索引都可以自己定,示例如下:

1
2
3
4
list_v = [ 90, 95, 100 ]
dict_v = { 'a':90, 'b':95, 'c':100 }
print( list_v[1] )
print( dict_v['b'] )

接下来创建一个与列表完全等效的特殊字典,如示例所示:

1
2
3
4
list_v = [ 90, 95, 100 ]
dict_v = { 0: 90, 1: 95, 2: 100 }
print( list_v[1] )
print( dict_v[1] )

字典中的元素值可以是任何变量,如示例所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
dict_v = {
 0: 'Chicken',
 1: 123, 
 2: True, 
 3: set([1,2,3]), 
 4: (1,2,3), 
 5: [1,2,3], 
 6: {'a':1}
}
print ( dict_v[0], dict_v[1], dict_v[2], dict_v[3],
dict_v[4], dict_v[5], dict_v[6])

字典中的索引只能是数字或者字符串,且一般都是字符串
注意:dict 作为 Python 的关键字和内置函数,变量名不建议命名为 dict,键一般是唯一的,如果重复最后的一个键值对会替换前面的,值不需要唯一。
字典的每个键值 key:value 对用冒号 : 分割,每个键值对之间用逗号 , 分割,整个字典包括在花括号 {} 中,如示例所示:

1
2
3
4
5
dict_v = {
 'zero' : 123, 
 1: True,
}
print( dict_v['zero'], dict_v[1])

字典的索引叫做“键”,字典的索引值叫“值”

访问字典里的值

把相应的键放入熟悉的方括弧,如下实例:

1
2
3
4
5
6
#!/usr/bin/python
 
tinydict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
 
print "tinydict['Name']: ", tinydict['Name']
print "tinydict['Age']: ", tinydict['Age']

字典元素的修改、添加与删除

向字典添加新内容的方法是增加新的键/值对如下实例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
tinydict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
 
tinydict['Age'] = 8 # 更新
tinydict['School'] = "RUNOOB" # 添加
 
 
print "tinydict['Age']: ", tinydict['Age']
print "tinydict['School']: ", tinydict['School']

能删单一的元素也能清空字典,清空只需一项操作。
显示删除一个字典用del命令,如下实例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
tinydict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
 
del tinydict['Name']  # 删除键是'Name'的条目
tinydict.clear()      # 清空字典所有条目
del tinydict          # 删除字典
 
print "tinydict['Age']: ", tinydict['Age'] 
print "tinydict['School']: ", tinydict['School']

循环语句

for 循环遍历列表

for 循环可以让循环变量依次取遍列表中的每个元素,其语法规则为

for 循环变量 in 列表:
循环体

for 循环语句依托列表来进行循环,循环变量依次取遍列表中的元素,示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
for num in range(10,20):  # 迭代 10 到 20 (不包含) 之间的数字
   for i in range(2,num): # 根据因子迭代
      if num%i == 0:      # 确定第一个因子
         j=num/i          # 计算第二个因子
         print ('%d 等于 %d * %d' % (num,i,j))
         break            # 跳出当前循环
   else:                  # 循环的 else 部分
      print ('%d 是一个质数' % num)

for 循环遍历字典

for 循环遍历字典时,既可以遍历索引,也可以遍历值,更可以都遍历,示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 两电一邮的 A+学科
schools ={'成电': '电科、信通', '西电': '电科', '北邮': '信通'}
# 循环键
for k in schools.keys():
    print( '两电一邮包括' , k )
# 循环值
for v in schools.values():
    print( 'A+学科是' , v )
# 循环键值对
for k, v in schools.items():
    print( k, '的 A+学科是', v )

以上 print 输出的都是一个元组变量,用于替代 f 字符串

while 循环

for 循环用于遍历高级变量类型中的元素,而 while 循环用于不断运行,直到布尔条件从 True 转为 False。其语法规则为

while bool:
循环体

示例如下:

1
2
3
4
a = 1
while a <= 5:
    print(a)
    a += 1

continue 与 break

continue 用于中断本轮循环并进入下一轮循环,在 for 和 while 中均有效。
break 用于停止循环,跳出循环后运行后续代码,在 for 和 while 中均有效。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# break 的演示
a = 1
while True:
    if a > 5:
        break
    print(a)
    a += 1
# continue 的演示
a = 0
while a < 5:
    a += 1
    if a == 3:
        continue
    print(a)

列表推导式

基础用法如示例所示,这两种写法可以表达同一个意思:

1
2
3
4
5
6
7
8
# 求平方——循环
value = [ ]
for i in [1,2,3,4,5]:
 value = value + [i**2]
print(value)
# 求平方——列表推导式
value = [ i**2 for i in [1,2,3,4,5] ]
print(value)

加一个 if 语句,如示例所示:

1
2
3
4
5
6
7
8
9
# 求平方——循环
value = [ ]
for i in [1,2,3,4,5]:
    if i < 4:
        value = value + [i**2]
print(value)
# 求平方——列表推导式
value = [ i**2 for i in [1,2,3,4,5] if i < 4 ]
print(value)

高级变量间的转换

集合、元组、列表、字典四者之间可以无缝切换,需要用到四个函数
⚫ 转换为集合使用 set 函数
⚫ 转换为元组使用 tuple 函数
⚫ 转换为列表使用 list 函数
⚫ 转换为字典使用 dict 函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 定义变量
set_v = {1,2,3}
tuple_v = (1,2,3)
list_v = [1,2,3]
dict_v = { 'a':1 , 'b':2 , 'c':3 }
# 转化为集合
print( set( tuple_v ) )
print( set( list_v ) )
print( set( dict_v.keys() ) )
print( set( dict_v.values() ) )
print( set( dict_v.items() ) )
# 转化为元组
print( tuple( set_v ) )
print( tuple( list_v ) )
print( tuple( dict_v.keys() ) )
print( tuple( dict_v.values() ) )
print( tuple( dict_v.items() ) )
# 转化为列表
print( list( set_v ) )
print( list( tuple_v ) )
print( list( dict_v.keys() ) )
print( list( dict_v.values() ) )
print( list( dict_v.items() ) )
# 转化为字典
print( dict( zip( {'a','b','c'} , set_v ) ) )
print( dict( zip( ('a','b','c') , tuple_v ) ) )
print( dict( zip( ['a','b','c'] , list_v ) ) )

注:在使用 dict 函数时,需搭配 zip 函数,zip 可将两个容器内的元素配对

函数

函数可以避免大段的重复代码,其格式为

def 函数名(输入参数): ’’’ 文档字符串 ’’' 函数体 return 输出参数

文档字符串用于解释函数的作用,查看某函数文档字符串的方法是.doc。 第四行的 return 可省略(一般的函数不会省略),若省略,则返回 None

吞吐各个类型的变量

函数的输入参数与输出参数均可以为任意的变量类型,示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 函数的输入与输出
def my_func(v):
    ''' 我的函数 '''
    return v
str_v = my_func( "cxk" ) # 字符串
str_v
num_v = my_func( 123 ) # 数字
num_v
bool_v = my_func( True ) # 布尔型
bool_v
set_v = my_func( {1,2,3} ) # 集合
set_v
tuple_v = my_func( (1,2,3) ) # 元组
tuple_v
list_v = my_func( [1,2,3] ) # 列表
list_v
dict_v = my_func( {'a':1, 'b':2 , 'c':3 } ) # 字典
dict_v

函数内部的空间是独立的,函数内部的变量叫做形式参数,不影响外界的实际参数。在刚刚的例子中,In [1]函数体内的 v 就是形式参数,它在外界的实际空间中是不存在的,只在调用函数的过程中会在函数空间内临时存在

吞吐多个变量

吞吐多个普通参数

输入多个值本质是输入了一个元组,输出多个值本质是输出了一个元组

1
2
3
4
5
6
# 吞吐多个值(借助元组)
def my_counter(a,b):
    '''加法器和乘法器'''
    return a+b, a*b
x,y = my_counter(5,6)
x,y
吞吐一个任意数量的参数
1
2
3
4
5
6
# 传入任意数量的参数(利用元组拆分法)
def menu(*args):
    '''菜单'''
    return args
    info = menu('荔枝', '油饼', '香精煎鱼', '香翅捞饭')
info
吞吐多个普通参数,并附带一个任意数量的参数

普通参数与任意数量参数可以同时出现,但请把后者放在最右侧

1
2
3
4
5
# 同时传入普通参数和任意数量的参数(后者只能出现一个)
def her_hobbies(name, *hobbies): 
    return name, hobbies
n,h = her_hobbies('cxk', 'singing', 'dancing', 'rap', 'basketball')
print( f"{n} likes {h}." )

(4)吞吐多个普通参数,并附带一个任意数量的键值对参数 除了上述示例,甚至可以输入多个键值对,如下示例所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 对各专业评价
def evaluate(in1, in2, **kwargs): 
    ''' 先对计算机类评价,再对通信类评价,也可自行补充 '''
    kwargs ['计算机类'] = in1
    kwargs ['通信工程'] = in2
    return kwargs
    # 规矩评价法
eva1 = evaluate( '打代码的', '拉网线的' )
eva1
# 额外补充法
eva2 = evaluate( 
    '打代码的' ,
    '拉网线的' ,
    电子工程 = '焊电路的' ,
    能源动力 = '烧锅炉的'
)
eva2

在上述示例中,函数的输入形参 kwargs 的两个**会让 Python 创建一个名为kwargs 的空字典,并将键值对放入其中

4.3 函数的关键字调用

函数可以顺序调用,也可以关键字调用,关键字方式更广泛,如示例所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def my_evaluate1(college, major, evaluate):
    '''对某大学某专业的评价'''
    message = f"{college}{major}{evaluate}。"
    return message
    # 顺序调用
info = my_evaluate1('电子科技大学', '自动化', '挺厉害')
info
# 关键字调用
info = my_evaluate1('电子科技大学', evaluate='也还行', major='测控')
info

输入参数的默认值

如果有些参数绝大部分情况是不变的,那么可以给其设置一个默认值

1
2
3
4
5
6
7
8
# 函数的默认值
def my_evaluate2(college, level='带专'): 
    message = f"{college}, 你是一所不错的{level}!"
    return message
info = my_evaluate2('电子科技大学') # 遵循默认值
info
info = my_evaluate2('华中科技大学' , level='985') # 打破默认值
info

创建和使用类

⚫ 类的本质:在一堆函数之间传递参数
⚫ 根据约定,类的名称需要首字母大写
⚫ 类中的函数叫方法,一个类包含一个__init__方法 + 很多自定义方法,__init__特殊方法前后均有两个下划线,每一个类中都必须包含此方法。示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 类的示范
class Counter:
    '''一台可以加减的计算器'''
 
    def __init__(self,a,b): # 特殊方法
        ''' a 和 b 公共变量,也是 self 的属性'''
        self.a = a # 公共变量 a 是 self 的属性
        self.b = b # 公共变量 b 是 self 的属性
 
    def add(self): # 自定义的加法方法
        '''加法'''
        return self.a + self.b
 
    def sub(self): # 自定义的乘法方法
        '''减法'''
        return self.a - self.b

⚫ 函数内部的变量与外部是在两个空间,为了使自定义方法能在类里互通,需要一个 self 作为舰船,将需要互通的变量作为 self 的属性进行传递;因此,特殊方法__init__旨在使用舰船 self 来承载公共变量 a 和 b
⚫ __init__特殊方法后的括号里要写上舰船 self 以及公共变量 a 和 b,而自定义方法后的括号就只需要写舰船 self 即可

1
2
3
4
# 创建类的实例
cnt = Counter(5,6) # 创建类的一个实例 cnt
print( cnt.a, cnt.b ) # 访问属性
print( cnt.add() ) # 调用方法

属性的默认值

属性即公共变量,上一个实例里的属性即 a 和 b。可以给self 的属性一个默认值,此时默认值不用写进__init__后面的括号里

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 带有默认值的参数
class Man:
    '''一个真正的 man'''
 
    def __init__(self,name,age):
        '''公共变量'''
        self.name = name
        self.age = age
        self.gender = 'man' # 一个带有默认值的属性
 
    def zwjs(self):
        '''自我介绍'''
        print(f"大家好!我是{self.name},今年{self.age}岁了!")
# 创建与使用类
cxk = Man('鸡哥',24)
cxk.name, cxk.age # 访问属性
cxk.zwjs() # 调用方法
cxk.gender # 访问默认值
# 修改默认值的数值
cxk.gender = 'Neither man nor woman'
cxk.gender

继承

继承:在某个类(父类)的基础上添加几个方法,形成另一个类(子类)
⚫ 父类从无到有去写属性和方法,第一行是 class 类名
⚫ 子类可继承父类的属性和方法,第一行是 class 类名(父类名) :子类在特殊方法里使用super()函数,就可以继承到父类的全部属性与方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 父类(也就是前面的加减计算器)
class Counter:
    '''一台可以加减的计算器'''
 
    def __init__(self,a,b):
        '''公共变量'''
        self.a = a
        self.b = b
 
    def add(self):
        '''加法'''
        return self.a + self.b
 
    def sub(self):
        '''减法'''
        return self.a - self.b
# 子类(在加减的基础上,添加乘除功能)
class Counter2(Counter):
    '''一台可以加减乘除的高级计算器'''
 
    def __init__(self,a,b):
        '''引用父类的属性'''
        super().__init__(a,b) # 继承父类(superclass)
 
    def mul(self):
        '''乘法'''
        return self.a * self.b
 
    def div(self):
        '''除法'''
        return self.a / self.b
        test = Counter2(3,4)
print( test.sub() ) # 调用父类的方法
print( test.mul() ) # 调用自己的方法

如果想要在子类中修改父类中的某个方法,可以直接在子类里写一个同名方法,即可实现覆写,也可以把覆写说成“变异”

掠夺

继承只能继承一个类的方法,但如果想要得到很多其它类的方法,则需要掠夺功能。有了掠夺功能,一个类可以掠夺很多其它的类,示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 一个无辜的类
class Counter:
    '''一台可以加减的计算器'''
 
    def __init__(self,a,b):
        '''公共变量'''
        self.a = a
        self.b = b
 
    def add(self):
        '''加法'''
        return self.a + self.b
 
    def sub(self):
        '''减法'''
        return self.a - self.b
# 掠夺者
class Amrc:
    '''一台本身只能乘除的计算器,现欲掠夺加减功能'''
 
    def __init__(self,c,d):
        '''公共变量'''
        self.c = c
        self.d = d
        self.cnt = Counter(c,d) # 掠夺 Counter 类的方法
 
    def mul(self):
        '''乘法'''
        return self.c * self.d
 
    def div(self):
        '''除法'''
        return self.c / self.d

掠夺的本质是,将另一类的实例当作 self 的属性用,这样一来,被掠夺的类的数量就不设上限。此外,假如掠夺者和被掠夺者里都有 add 函数,掠夺者里的方法用 test.add(),被掠夺者里的方法用 test.cnt.add(),于是就不必覆写

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy