Python第三周学习总结
难点和重点
重点:函数、 高阶函数的使用、解耦 、 面向对象编程的理解(对象、对象的属性和方法)
难点: 构建函数逻辑抽象、面向对象的编程中对类的抽象以及对应的属性和方法 、对象于属性、方法之间的逻辑关系、属性与方法之间的逻辑关系 、方法于方法之间的调用关系
文章目录
1. 函数
1.1 函数定义及结构
- 定义函数时,用def关键字来定义一个函数。
- 一个完整的函数包括这几个部分:函数名(命名规则和变量遵循变量的命名规则)、参数(提供数据接口)函数体(函数中最重要的部分)、返回值(用关键字 return ,如果没有定义返回值,则默认返回None)
def add(a, b, c):
"""对三个数求和
:param a: 数值型
:param b:
:param c:
:return: 返回 三个数的和
"""
return a + b + c
-
在定义函数时尽量避免有打印和输入执行语句,避免与控制台发生高耦合
在定义函数时要多写注释让调用者知道该函数所要表达的功能,对每一个传入的参数和返回值进行一个简单的说明和它们的数据类型
1.2 参数
- 参数是用来实现数据共享的一个方式,我们把定义函数时放在圆括号的是变量叫做参数。
参数的类型:
1. 位置参数,通常我们定义的参数都是位置参数,每个参数在函数列表中都有具体的位置。
def fun(a,b):
return a+b
2. 命名关键字参数,希望调用参数时必须指定参数名=参数值的形式,这时后再定义函数时可以把参数设置为命名关键字参数。
# 放在 * 号前面的叫位置参数,*号后面的叫命名关键字参数
def(c,d,*,a=1,b=2)
return
3. 可变参数,在定义函数时不知道要传入位置参数的个数,可以使用位置参数来代替传入一个或多个位置参数。最后可变参数会将传入的位置参数封装成元组。
def fun(*args):
return
- 关键字参数,当不知道要传入带参数名的参数个数时,可以使用可变参数来实现。可变参数把传入的带参数名的参数进行封装成字典。
def fun(**kwargs):
return
定义函数时参数列表的顺序:
位置参数一定是放在关键字参数的前面,命名关键字参数放在它们两个之间
2. 函数的应用
2.1 解决函数命名冲突
- 对于函数的命名也是编程一大头疼的问题,有时候不知道怎样给函数一个好的符合才能更好给做到见名知意。
- 函数命名还有一大问题,就是忘记了在该模块该函数以及存在了又重新写了一个与之前完全一样函数名的函数,只是实现功能不一样。
def foo():
print('hello,world')
def foo():
print('this is my pen')
- 上述代码执行时会打印出 “this is my pen”,而不会执行打印“hello,world”.说明第二个同名函数以尽将第一个覆盖。
当我们在电脑同一个文件夹同发同一个文件是,会提示要么把原来的覆盖要么建立副本(也就是重新命名),但我们在不同的文件夹中放入同一个文件是可取的。然而我们的函数类似于上述问题,所以可以根据这一原理,将其放入到不同的模块(python文件)中,这样根据模块的不同对函数的进行区分。
函数的应用案例:
- 求和
def add(*args):
total = sum([arg for arg in args if type(arg) in (int, float)]) # 对于传入的每一个参数进行类型判断
return total
def main():
print(add(1, 2, 3, 'a', 'c'))
if __name__ == '__main__':
main()
# 输出 6
- 上述的
__name__
是一个隐藏变量,只有在本模块执行时它对于的值才为“__mian__
” ,在其它文件中执行它的值是文件名不带扩展名。这样的好处就是当你相对该模块进行一个简单的测试,而又不希望在其它模块被调用者也执行测试语句,这样就有效的隐藏了起来。
3. 高阶函数及应用
3.1 何为高阶函数
- 函数本身可以作为其它函数的参数
- 函数可以赋给变量
- 函数可以作为函数的返回值
将满足上述条件的三个函数称为高阶函数,高阶函数的使用可以降低原函数的耦合程度,提高模块之间的独立性。在函数设计原则要遵循高内聚低耦合,做到每一个函数只实现一样功能即可。提高模块的独立性来提高系统的独立性,以便于后期的维护和需求给更改。
无副作用,所谓副作用就是对全局变量进行修改,产生出了计算结果之外的行为。所以在调用函数和函数的最初设计要尽量做到无副作用效果。
3.2 Python中常用的内置函数
- 以上就是python内置的函数无需导入直接就可以用。
- python除了内置函数还有官方库提高的模块无需安装,使用时只需要进行导入即可。python还有三方库,需要下载和导入。
3.3 模块之间的相互执行
3.3-1 基于Pycharm包的创建和导入
- 创建包(文件夹)
- 模块与包
函数 | 说明 |
---|---|
import 模块名 | 导入模块 |
from 模块名导入 功能 | 导入模块特定的功能 |
import 模块名 as 别名 | 导入模块作为别名 |
3.4 Lambda函数
- 当需要定义一句话就能写完的函数来实现对应的功能,这是可以定义一个匿名函数。
lambda x , y : x+y
def add(x,y):
return x+y
- 其中 x,y 表示参数,x+y为返回的表达式。匿名函数的功能等价于调用add函数实现的功能
3.5 递归函数
- 把函数作为自己的参数的调用过程称为递归调用。
递归函数的结构:
1. 递归公式
2.限制条件(终止递归调用)
- 调用原理
递归函数两个重要的步骤: 递归和回溯
4. 面向对象编程
- 当下主流的编程范式主要有函数式编程和面向对象编程。
4.1 函数式编程
- 函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。
4.2 面向对象编程
- 类:将有共同特征的对象进行抽象的一个概念
- 对象:对象是接受消息的实体,面向对象编程就是通过给对象发消息达到解决问题的目标。
- 属性 :对象的静态特征
- 方法 :对象的动态特征
# 定义类的关键字 class ,类名采用驼峰命名法--->每个单子的首字母大写
class Person:
"""定义一个人类"""
__slots__ = ('name', 'sex') # 限制类的属性
def __init__(self, name, sex):
""" 对属性进行初始化"""
self.name = name
self.sex = sex
def eat(self):
"""定义一个方法"""
print(f'{self.name}在吃饭')
def __str__(self):
"""解决直接打印对象时返回值"""
return f'{self.name}'
def __repr__(self):
"""解决创建多个对手放在可迭代对象里直接打印"""
return f'{self.name}'
def main():
person = Person('01', 23)
p = [Person('02', 3), Person('03', 4)]
print(person)
print(p)
if __name__ == '__main__':
main()
4.3 面向对象编程的四大支柱
- 抽象(abstraction):提取共性(定义类就是一个抽象过程,需要做数据抽象和行为抽象)。
- 封装(encapsulation):把数据和操作数据的函数从逻辑上组装成一个整体(对象)。
—> 隐藏实现细节,暴露简单的调用接口。 - 继承(inheritance):扩展已有的类创建新类,实现对已有类的代码复用。
- 多态(polymorphism):给不同的对象发出同样的消息,不同的对象执行了不同的行为。
4.4 面向对象编程中两个类之间的关系
- 继承关系:从一类中派生出一个新的类
- 关联关系:把一个类作为另一个类的属性,类本身也是一种对象。
- 依赖关系 :一个类的对象最为另一个类的对象的返回值会参数
5. 面向对象编程的应用
- 扑克游戏,四个玩家参与,先洗牌,再把牌发到四个玩家的手上
创建牌类
class Card:
def __init__(self, face, suite):
self.face = face
self.suite = suite
def show(self):
suites = {'S': '♠', 'H': '♥', 'C': '♣', 'D': '♦'}
faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
return f'{suites[self.suite]}{faces[self.face]}'
def __str__(self):
return self.show()
def __repr__(self):
return self.show()
def __lt__(self, other): # less than
# return self.face < other.face
if self.suite == other.suite:
return self.face < other.face
return ord(self.suite) < ord(self.suite)
创建扑克类
import random
from example07 import Card
class Poker:
def __init__(self):
self.cards = [Card(face, suite) for face in range(1, 14) for suite in 'SHCD']
self.counter = 0
def shuffle(self):
"""洗牌"""
self.counter = 0
random.shuffle(self.cards)
def deal(self):
"""发牌"""
card = self.cards[self.counter]
self.counter += 1
return card
def has_more(self):
"""判断是否还有牌"""
return self.counter < len(self.cards)
创建玩家类
class Player:
def __init__(self, nickname):
self.nickname = nickname
self.cards = [] # 保存玩家手中的牌
def get_one_card(self, card):
"""摸牌"""
self.cards.append(card)
def arrange(self):
"""整理牌"""
self.cards.sort()
def show(self):
"""显示玩家手上的牌"""
return f'{self.nickname}:\n{self.cards}'
- 上述为一个完整的面向对象编程步骤,反映了类与类之间的关系,对象与对象之间的联系。
简单总结
从函数到面向对象编程,基本python入门知识已经学了一大半。python作为一门动态编程语言,体现了它的灵活性特征,完全掌握难度很大。自古以来不积硅步,无以至千里,不积小流,无以成江海。编程水平非一日之功,不可太过于急躁,需多加练习和看高质量的代码来提高。