学习python第十六天, 一周总结
这一周主要学习内容如下
- 函数
- 函数的调用
- 函数的参数问题
- 使用模块
- 递归函数
- 面对对象编程
- 继承问题,父类、子类
- 关联问题,普通关联、强关联
- 依赖关系
- 多态
复习的目的只是整合一周学习的只是具体还是要参照每一天所写的笔记和代码
函数
简单来说函数就是将各种作用的代码打包起来,然后形成函数,之后在需要使用时就可以直接调过来使用,就不需要重新再写一遍直接用即可
函数都意义大概就是避免代码的冗杂,减少代码的重复性,还有就是如果需要对代码进行更改时就要一个一个更改,而有了函数直接更改函数即可
格式为:
def 函数名(参数):
return 返回值
这里的参数可以理解为数学里函数的自变量,也可以没有参数,而返回值可以理解为数学函数里的因变量
,返回值的种类很多,字符串,数字,布尔值,等等等等,
函数是一个很重要,很常用的知识点,以后也会经常使用到,所以多多的练习必不可少
参数
对于不同的函数我们需要导入不同的参数,参数各种各样,还有一些参数不确定参数的个数,最简单的例子就是求不确定个数的数字和,或乘积,还有不同参数的类型
于是就有了以下方法
# 当不确定参数个数时
def __init__(self, *args):
# 当参数为字典且不确定字典个数时
def __init__(self, **kwargs):
# 当需要确定参数类型时,在参数后面加上冒号加上参数类型
def __init__(self, name: str, age: int, score: dict, parent: list):
模块的使用
模块的使用 其实与使用python的第三方库差不多,都是先导入再使用,不同的地方就是现在我们只学到了在同一个环境下的模块使用,
递归函数
递归函数其实就是在一个函数中自己调用自己,有点类似于while循环,需要找到一个停止调用的钥匙
def fac(num):
if num == 0:
return 1
return num * fac(num - 1)
在返回值那里继续调用自己,造成一个循环,在循环的过程中参数变小
当参数变为1时我们就停止递归if num == 0:
return 1
面对对象
面向对象编程
指令式编程---->面向过程(函数)编程----->程序比较简单的时候没有任何毛病
编程范式(程序设计的方法论):面向对象编程/函数式编程
对象: 对象是可以接收消息的实体,面向对象编程就是通过给对象发消息达到解决问题的目标
对象 = 数据 + 函数(方法)----->对象将数据和操作数据的函数从逻辑上变成一个整体。
类(类型): 将一大类对象共同的特正抽取出来之后得到的一个抽象概念
简单地说,类是对象的蓝图(模板),有了类才能创建出这种类的对象
面向对象编程:
- 定义类---->使用驼峰命名法,每个单词首字母大写
~数据抽象: 找到对象相关的静态特征(属性)---->找名词
~行为抽象: 找到和对象相关的动态特征(方法)----->找动词 - 造对象
- 发消息
- 口诀
一切皆为对象
对象都有属性和行为
每个对象都是独一无二的
对象一定属于某个类
简化面对对象编程的基本步骤如下:
- 定义类(数据抽象,行为抽象)
- 创建对象(创建对象----->构造器语法----->类名)
- 给对象发消息(调用对象的方法)
我自己总结下来就是,找到一种种类,从这种类里边抽象出一个对象,当然也可以先抽象出一个对象再将其归到一个类里,
抽象出这个类的属性,有什么特殊的地方,比如什么颜色,头上有犄角还是身后有尾巴,或者是其他的特点,这些是属性
抽象出这个类的行为,这个种类的物种能够做什么事情,有什么用,就是它的行为,
将这个类抽象出来之后,创建一个这个种类里面的一个个体,比如学生类,创建出小明这个学生,牛类,你家门口的那头奶牛大花,对象需要是一个具体的东西,可以不存在,但是要具体,让人一下子就能想象出它的样子,创建出对象,根据类的要求传入参数,也就是属性,属于这个类且这个对象也有的属性
最后给对象发消息,让它执行它的行为
这就是一个面对对象编程的过程,值得注意的是这里的对象可不是你的男朋友或者女朋友,如果单身狗就当我没说
静态方法,动态方法
我们在类里面写的函数,通常称之为方法,它们基本上都是发给对象的消息。
但是有的时候,我们的消息并不想发给对象,而是希望发给这个类(类本身也是一个对象),
这个时候,我们可以使用静态方法或类方法,将我们要发的消息传给类
继承
对已有的类进行扩展开展创建出新的类,这个过程叫做继承
提供继承学习的类叫做父类,得到继承信息的类叫做子类
子类直接从父类继承公共的属性和行为,再添加自己特有的属性和行为
子类一般强于父类,父类有的子类可直接拿来用,而父类却不能使用子类的行为
- 两个类之间有哪些可能的关系???
~ is-a关系:继承 —> 从一个类派生出另一个类
a student is a person.
a teacher is a person.
~ has-a关系:关联 —> 把一个类的对象作为另外一个类的对象的属性
a person has an identity card.
a car has an engine.
- (普通)关联
- 强关联:整体和部分的关联,聚合和合成
~ use-a关系:依赖 —> 一个类的对象作为另外一个类的方法的参数或返回值
a person use a vehicle.
简单的关系如下:
class Vehicle:
"""交通工具"""
pass
class Horse(Vehicle):
"""马"""
pass
class Motobike(Vehicle):
"""摩托车"""
def __init__(self):
self.engine = Engine()
class Engine:
"""引擎"""
pass
class Follower:
"""徒弟"""
def __init__(self, name):
self.name = name
def do_work(self):
pass
class MrTang:
"""唐僧"""
def __init__(self):
self.followers = [Follower('孙悟空'), Follower('猪悟能'), Follower('沙悟净')]
def drive(self, vehicle):
"""驾驶"""
pass
马和摩托车都是交通工具,所以他们可以使用交通工具的属性
引擎是摩托车的一部分所以他们属于关联关系
唐僧可以骑马,使用与被使用关系属于依赖
面向对象编程的四大支柱:
-
~ 抽象(abstraction):提取共性(定义类就是一个抽象过程,需要做数据抽象和行为抽象)。
-
封装(encapsulation):把数据和操作数据的函数从逻辑上组装成一个整体(对象)。
—> 隐藏实现细节,暴露简单的调用接口。 - 继承(inheritance):扩展已有的类创建新类,实现对已有类的代码复用。
-
多态(polymorphism):给不同的对象发出同样的消息,不同的对象执行了不同的行为。
—> 方法重写:子类对父类已有的方法,重新给出自己的实现版本
重写
子类对父类已有的方法,重新给出自己的实现版本,这个过程叫做方法重写(override)。
在重写方法的过程中,不同的子类可以对父类的同一个方法给出不同的实现版本,那么该方法在运行时就会表现出多态行为。
面对对象编程练习
-
写一个扑克游戏,洗牌,把牌发到四个玩家手上
-
-
牌
- 属性: 花色、点数
- 行为: 显示
-
-
扑克
- 属性: 保存牌的列表
- 行为: 发牌、 洗牌
-
-
玩家
- 属性: 名字,保存玩家手牌的列表
- 行为: 摸牌、整理、出牌
整理需要用到一种特殊的方法------魔术方法
魔术方法
魔术(魔法)方法 —> 以双下划线开头和结尾的方法 —> 有特殊用途和意义的方法
- init —> 初始化方法,在调用构造器语法创建对象的时候会被自动调用
~ (initialize -> 初始化)
- str —> 获得对象的字符串表示,在调用 print函数直接输出对象时会被自动调用
- repr —> 获得对象的字符串表示,把对象放到容器中,用 print直接输出容器时会自动调用
~ (representation -> 表述)
- lt —> 对应小于号运算符,自动比大小
~ (less than -> '<'运算符)
class Card:
def __init__(self, suite, face):
"""
牌的属性,花色和点数
"""
self.suite = suite
self.face = face
def __str__(self):
"""展示字符"""
return self.show()
def __repr__(self):
"""展示字符"""
return self.show()
def __lt__(self, other):
"""自动比较大小的方法"""
face1, face2 = self.face, other.face
return face1 < face2
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 main():
"""程序入口"""
card1 = Card('H', 1)
card2 = Card('S', 13)
card3 = Card('D', 12)
card4 = Card('C', 9)
print(card1, card2, card3, card4)
cardA = [card1, card2, card3, card4]
print(cardA)
if __name__ == '__main__':
main()
class Poker:
"""
扑克
"""
def __init__(self):
self.cards = [Card(suite, face)
for suite in 'SHCD'
for face in range(1, 14)]
# 生成式语法生成一副扑克
# for suite in 'SHCD':
# for face in range(1, 14):
# card = Card(suite, face)
# self.cards.append(card)
self.counter = 0
def shuffle(self):
# 将扑克顺序打乱
self.counter = 0
random.shuffle(self.cards)
def deal(self) -> Card:
"""发牌, 将扑克牌一张一张发"""
card = self.cards[self.counter]
self.counter += 1
return card
def has_more(self) -> bool:
# 牌发完了
return self.counter < len(self.cards)
def main():
poker = Poker()
poker.shuffle()
while poker.has_more():
# 使用循环发牌,当牌发完了,has_more(self) -> bool就会返回False,终止循环
print(poker.deal(), end='')
if __name__ == '__main__':
main()
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):
"""显示玩家手上的牌"""
print(self.nickname, end=':')
# 输出玩家昵称,再将玩家手上的牌一张张输出
for card in self.cards:
print(card, end='')
print()
def main():
nicknames = ['吕布', '猴子', '铠', '程咬金']
players = [Player(nickname) for nickname in nicknames]
poker = Poker()
poker.shuffle()
for _ in range(13):
for player in players:
card = poker.deal()
player.get_one_card(card)
for player in players:
player.show()
if __name__ == '__main__':
main()
练习,使用继承
给我的感觉使用继承就好比使用函数一样
就是为了减少代码的重复
将多个子类所拥有的属性写在父类里(当然前提是父类也同时有这属性才行)
然后直接从父类里面拿来用就行了
就好比,学生、老师都属于人这个类,那么学生类和老师类就是人类的子类,他们共有的属性就写在父类里,比如吃、玩
class Person:
def __init__(self, name, gander):
self.name = name
self.gander = gander
pass
def eat(self):
"""
吃饭
:return:
"""
print(f'{self.name}正在吃饭')
pass
def play(self, game_name):
"""
玩耍
:param game_name:
:return:
"""
print(f'{self.name}正在玩{game_name}')
pass
class Student(Person):
def __init__(self, name, gender, grade):
self.name = name
self.gender = gender
self.grade = grade
def study(self, course_name):
"""
学习
:param course_name:
:return:
"""
print(f'{self.name}正在学习{course_name}')
class Teacher(Person):
def __init__(self, name, gender, title):
super().__init__(name, gender)
self.title = title
def teach(self, object_name):
return f'{self.name}教的是{object_name}'
if __name__ == '__main__':
stu = Student('王大锤', '男', '五年级')
stu.study('语文')
stu.eat()
stu.play('王者荣耀')
多态
多态也属于面对对象编程的范畴,当父类所拥有的行为,子类也拥有但是由于子类的不同所执行的方法也不同,再继承调用这种方法的过程就叫做多态,而这种方法我们在父类里抽象的时候不能将特点具体执行写出来,只能在子类调用时才能具体体现,
示例代码如下:
我们现在要写一个发工资的情形,不同的职位,职员发不同的工资
薪资(月薪)结算系统
-
三类员工:
- 部门经理:固定月薪,15000元
- 程序员:计时结算月薪,每小时200元
- 销售员:底薪+提成,底薪1800元,销售额5%提成
from abc import abstractmethod
# 导入这个模块,使用这个模块里的方法标记多态类型
class Employee:
def __init__(self, name, post):
self.name = name
self.post = post
@abstractmethod
# 标记多态
def get_salary(self):
pass
class Manager(Employee):
def get_salary(self):
""" 经理的工资发放标准"""
return 15000
class Programmer(Employee):
def __init__(self, name, post):
super().__init__(name, post)
self.work_time = 0
pass
def get_salary(self):
"""程序员的工资发放标准"""
return self.work_time * 200
class Salesman(Employee):
def __init__(self, name, post):
super().__init__(name, post)
self.sale = 0
def get_salary(self):
""" 销售员的工资发放标准"""
return 1800 + self.sale * 0.05
def main():
temps = [Manager('王大锤', '经理'), Programmer('马克', '程序员'),
Programmer('乔布斯', '程序员'), Salesman('龚凡', '销售员'),
Salesman('科科特', '销售员'), Salesman('巴菲特', '销售员')]
for temp in temps:
# 遍历每一个员工
if type(temp) == Programmer:
working_time = float(input(f'请输入{temp.name}的工作时间'))
temp.work_time = working_time
elif type(temp) == Salesman:
post_money = float(input(f'请输入{temp.name}的销售额'))
temp.sale = post_money
print(f'{temp.name}的工资是{temp.get_salary()}')
if __name__ == '__main__':
main()
在使用多态的时候要注意,子类的方法名要和父类的一样才能使用
无论是函数还是面对对象编程都是比较重要的知识点,需要多多学、看、写代码
简易版 21点游戏
class Card:
def __init__(self, suite, face):
self.suite = suite
self.face = face
def __str__(self):
return self.show()
def __repr__(self):
return self.show()
def __lt__(self, other):
face1, face2 = self.face, other.face
return face1 < face2
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]}'
import random
class Poker:
"""
扑克
"""
def __init__(self):
self.cards = [Card(suite, face)
for suite in 'SHCD'
for face in range(1, 14)]
# for suite in 'SHCD':
# for face in range(1, 14):
# card = Card(suite, face)
# self.cards.append(card)
self.counter = 0
def shuffle(self):
self.counter = 0
random.shuffle(self.cards)
def deal(self) -> Card:
"""发牌"""
card = self.cards[self.counter]
self.counter += 1
return card
def has_more(self) -> bool:
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):
"""显示玩家手上的牌"""
print(self.nickname, end=':')
for card in self.cards:
print(card, end='')
print()
def compare(self):
"""
转换非数字牌的点数
:return: 点数
"""
X = []
for get_number in self.cards:
m = str(get_number)
x = m[1:]
if x == 'J' or x == 'K' or x == 'Q':
x = 10
elif x == 'A' and sum(X) + 11 <= 21:
x = 11
elif x == 'A' and sum(X) + 11 > 21:
x = 1
else:
x = int(x)
X.append(x)
return X
def BlackJack(self):
"""
形成Black Jack的特殊情况
:return:
"""
if sum(self.compare()) == 21 and len(self.cards) == 2:
print('Black Jack')
def main():
total_money = 1000
while total_money > 0:
bet_money = int(input('清下注:'))
if bet_money > total_money:
print('钱不够')
continue
player1 = Player('闲家')
player2 = Player('庄家')
poker = Poker()
poker.shuffle()
for _ in range(2):
card1 = poker.deal()
player1.get_one_card(card1)
card2 = poker.deal()
player2.get_one_card(card2)
player1.show()
player2.show()
while True:
h1 = 1
while True:
if sum(player1.compare()) > 21:
h1 = 0
break
h1 = int(input('闲家是否继续要牌如果要请输入1,否则输入0:'))
if h1 == 1:
card = poker.deal()
player1.get_one_card(card)
player1.show()
elif h1 == 0:
break
h2 = 1
while True:
if sum(player2.compare()) > 21:
h2 = 0
break
h2 = int(input('庄家是否继续要牌如果要请输入1,否则输入0:'))
if h2 == 1:
card = poker.deal()
player2.get_one_card(card)
player2.show()
elif h2 == 0:
break
if h1 == 0 and h2 == 0:
break
print(f'闲家{sum(player1.compare())}点, 庄家{sum(player2.compare())}点')
if player1.BlackJack() and player2.BlackJack():
print('平局')
elif player1.BlackJack():
print('Black Jack,闲家胜')
total_money += bet_money * 2
if player2.BlackJack():
print('庄家胜')
total_money -= bet_money
elif sum(player1.compare()) > 21:
print('庄家胜')
total_money -= bet_money
elif sum(player2.compare()) > 21:
print('闲家胜')
total_money += bet_money * 2
elif sum(player2.compare()) > 21:
print('闲家胜')
total_money += bet_money * 2
elif sum(player1.compare()) > sum(player2.compare()):
print('闲家胜')
total_money += bet_money * 2
elif sum(player1.compare()) == sum(player2.compare()):
print('平局')
else:
print('庄家胜')
total_money -= bet_money
print(f'您还有{total_money}元')
if __name__ == '__main__':
main()