面向对象前戏之人狗大战

# 编写代码简单的实现人打狗 狗咬人的小游戏(剧情需要)
"""推导步骤1:代码定义出人和狗"""
person1 = {
'name': 'jason',
'age': 18,
'gender': 'male',
'p_type': '猛男',
'attack_val': 8000,
'life_val': 99999999
}
person2 = {
'name': 'kevin',
'age': 28,
'gender': 'female',
'p_type': '淑女',
'attack_val': 1,
'life_val': 100
}
dog1 = {
'name': '小黑',
'd_type': '泰迪',
'attack_val': 100,
'life_val': 8000
}
dog2 = {
'name': '小白',
'd_type': '恶霸',
'attack_val': 2,
'life_val': 80000
}
"""
如果想要定义多个人狗,需要多次编写上述字典,采用封装成函数的方式既可以提高效率,又方便随时调用
""" # 1.定义出人狗的函数
def create_person(name, age, gender, p_type, attack_val, life_cal):
person_dict = {
'name': name,
'age': age,
'gender': gender,
'p_type': p_type,
'attack_val': attack_val,
'life_val': life_cal
}
return person_dict def create_dog(name, d_type, attack_val, life_val):
dog_dict = {
'name': name,
'd_type': d_type,
'attack_val': attack_val,
'life_val': life_val
}
return dog_dict # 2.调用函数,传参,接受函数体代码的返回值
p1 = create_person('max', 25, 'male', '刺客', 10000, 9999999)
print(p1) # 生成字典然后返回,p1:{'name': 'max', 'age': 25, 'gender': 'male', 'p_type': '刺客', 'attack_val': 10000, 'life_cal': 9999999}
p2 = create_person('kevin', 28, 'female', '淑女', 100, 800)
print(p2) # {'name': 'kevin', 'age': 28, 'gender': 'female', 'p_type': '淑女', 'attack_val': 100, 'life_cal': 800} d1 = create_dog('小黑', '恶霸', 800, 900000) # d1:{'name': '小黑', 'd_type': '恶霸', 'attack_val': 800, 'life_val': 900000}
d2 = create_dog('小白', '泰迪', 100, 800000) # d2:{'name': '小白', 'd_type': '泰迪', 'attack_val': 100, 'life_val': 800000} # 3.定义出人打狗、狗咬人的动作
def person_attack(person_dict, dog_dict):
print(f'人{person_dict.get("name")}准备揍狗{dog_dict.get("name")}')
dog_dict['life_val'] -= person_dict.get('attack_val')
print(f'人揍了狗一拳,狗掉血{person_dict.get("attack_val")},剩余血量{dog_dict.get("life_val")}') def dog_attack(dog_dict, person_dict):
print(f'狗{dog_dict.get("name")}准备咬人{person_dict.get("name")}')
person_dict['life_val'] -= dog_dict.get('attack_val')
print(f'狗咬了人一口,人掉血{dog_dict.get("attack_val")},人剩余血量{person_dict.get("life_val")}') # 4.正确传参:通过刚才d1、d2、p1、p2通过定义字典函数返回的返回值,把相应字典当做参数传入
person_attack(p1, d1) # 人max准备揍狗小黑 人揍了狗一拳,狗掉血10000,剩余血量890000
dog_attack(d2, p2) # 狗小白准备咬人kevin 狗咬了人一口,人掉血100,人剩余血量700 # 5.错误传参:将人的参数传给了狗,狗的参数传给了人。因此得出采用传参的方式极易将犯错误的参数传递给函数
person_attack(d1, p1) # 人小黑准备揍狗max 人揍了狗一拳,狗掉血800,剩余血量9999199
dog_attack(p2, d2) # 狗kevin准备咬人小白 狗咬了人一口,人掉血100,人剩余血量799900

面向对象核心思路

"""
如何实现狗只能调用狗的攻击动作,人只能调用人的攻击动作?
"""
def get_person(name, age, gender, p_type, attack_val, life_val):
def person_attack(person_dict, dog_dict):
print(f'人{person_dict.get("name")}准备揍狗{dog_dict.get("name")}')
dog_dict['life_val'] -= person_dict.get('attack_val')
print(f"人揍了狗一拳 狗掉血:{person_dict.get('attack_val')} 狗剩余血量:{dog_dict.get('life_val')}")
person_dict = {
'name': name,
'age': age,
'gender': gender,
'p_type': p_type,
'attack_val': attack_val,
'life_val': life_val,
'person_attack': person_attack
}
return person_dict def get_dog(name, d_type, attack_val, life_val):
def dog_attack(dog_dict, person_dict):
print(f"狗:{dog_dict.get('name')}准备咬人:{person_dict.get('name')}")
person_dict['life_val'] -= dog_dict.get('attack_val')
print(f"狗咬了人一口 人掉血:{dog_dict.get('attack_val')} 人剩余血量:{person_dict.get('life_val')}")
dog_dict = {
'name': name,
'd_type': d_type,
'attack_val': attack_val,
'life_val': life_val,
'dog_attack': dog_attack
}
return dog_dict person1 = get_person('max', 25, 'male', '猛男', 1000, 80000) # 调用函数get_person并传参,此时person1 = person_dict
dog1 = get_dog('小黑', '恶霸', 800, 900000) # 调用函数get_dog并传参,此时dog1 = dog_dict
person1.get('person_attack')(person1, dog1) # 相当于调用了函数person_attack(person1, dog1),并传入字典person_dict、dog_dict

编程思想

1.面向过程编程:过程即流程,面向过程就是按照固定的流程解决问题,结局是固定的,也就是功能需求
eg:注册功能、登录功能、转账功能(需要留举出每一步的流程,并且随着步骤的深入,问题的解决越来越简单)
结局思路:提出问题,然后指定出解决问题的方案 2.面向对象编程:类似造物主,程序员只需要造出一个个对象,结局有无数个,对象将来会如何发展和程序员没有关系,也无法控制
"""
上述两种编程思想没有优劣之分,需要结合实际需求而定
如果需求是注册、登陆、人脸识别肯定面相好过程更合适
如果需求是游戏人物name面向对象更合适
实际编程两种思想是彼此交融的,只不过占比不同
"""

面向对象之类与对象

对象:数据与功能的结合体,对象才是核心
类:多个对象相同数据和功能的结合体,类主要功能是为了节省代码
"""
一个人:对象
一群人:人类(所有人相同的特征)
"""
现实中一般是先有对象再有类,程序中如果想要产生对象,必须要先定义出类

类与对象的创建

面向对象并不是一门新的技术,但是为了更好地适应功能并且便于区分,针对面向对象设计了新的语法格式,python中一定要有类,才能借助于类产生对象
1.类的语法结构:
class 类名:
'''代码注释'''
对象公共的数据
对象公共的功能
1.1 class是定义类的关键字
1.2类名的命名与变量名几乎一致,类名的首字母推荐用大写
1.3数据:变量名与数据值的绑定;功能或方法就是函数 2.类的定义与调用
# 需求:选课系统
#定义类
class Student:
# 对象公共的数据:
school_name = '清华大学'
# 对象公共的功能
def choice_course(self):
print('学生选课功能') 类在定义阶段就会执行类体代码,但是类的局部名称空间外无法直接调用,只能在类的局部名称空间使用 2.1:查看类的局部名称空间中所特有的名字:类名.dict__
print(Student.__dict__)
2.2:拿到类的局部名称空间中的名字:类名.dict__.get('类中的名字')
'''类中的名字要加引号'''
print(Student.__dict__.get('name'))
2.3上述过程太过繁琐,可以直接用类名点名字的方式拿到类中的名字
print(Student.name) # jason
print(Student.choice_course) # <function Student.choice_course at 0x000001DD04C7E730>
print(Student.choice_course(111)) # 选课系统 None
2.4类名加括号可以产生一个对象,并且每次都会产生全新的对象
obj1 = Student()
obj2 = Student()
obj3 = Student()
print(obj1, obj2, obj3) # <__main__.Student object at 0x000001F81E91B0B8> <__main__.Student object at 0x000001F81E9DC588> <__main__.Student object at 0x000001F81E9DC940>
2.5类名中本身什么都没有,类Student目前产生了三个对象,本身为空,由于它们产生于一个类,它们可以拿到类Student的数据和功能
print(obj1.name) # jason
print(obj2.name) # jason
print(obj3.name) # jason
2.6通过类名点的方式修改类内部的名字,类内部的名字是公共的,当类内部的名字修改后,所有对象拿到的名字都是修改后的名字
Student.name = 'max'
print(obj1.name) # max
print(obj2.name) # max
print(obj3.name) # max
"""
数据和功能也可以称为属性,数据可能会被称为属性名
"""

对象独有的数据

类当中都是对象共有的名字,但是每个对象也可以拥有自己单独的数据。在类中定义功能的时候把函数名替换成__init__,用self点的方式来赋值,底层原理是将传入功能的参数赋值给self点的变量名,self点的变量名其实是字字符串只不过在这里不需要加引号。通过类名括号内传参的方式将参数传递给功能,然后通过类名点的方式就可以拿到对象独有的数据。
class Student:
school_name = '清华大学' def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender stu1 = Student('max', 25, 'male')
print(stu1.name) # max
print(stu1.gender) # male
stu2 = Student('jason', 18, 'male')
print(stu2.__dict__) # {'name': 'jason', 'age': 18, 'gender': 'male'}
print(stu2.name) # jason

对象独有的功能

定义在类中的功能 默认就是绑定给对象使用的 谁来调谁就是主人公。类调用功能需要手动传参,而对象调用不需要传参,因为对象会将自身当做第一个参数传入功能。如果功能需要多个参数的话,对象调用功能需将第一个参数以外的参数手动传入
class Student: def choice_course(self):
print('选课系统') Student.choice_course(111) # 选课系统
stu1 = Student()
stu1.choice_course() # 选课系统 class Student: def choice_course(self, name):
print('选课系统') stu1 = Student()
stu1.choice_course('max') # 选课系统

动静态方法

1.在类中定义的函数(功能有多重属性)
"""
类名加括号会产生一个对象,对象用点函数名的方式不用传参,因为对象对被当做第一个参数自动传入,类名点函数名需要传参
"""
class Group:
s = 'from Group'
def func1(self):
print('from func1') gro = Group()
gro.func1() # from func1
Group.func1(111) # from func1 2.被@classmethond修饰的函数默认绑定给类,类会将自身当做第一个参数传入,所以类调用函数不需要传参。对象调永也不需要传参
class Group:
s = 'from group' @classmethod
def func1(cls):
print('from func1') Group.func1() # from func1
gro = Group()
gro.func1() # from func1 3.被@staticmethod修饰的函数就是一个普普通通的函数,不管是类还是对象,调用内部的函数都需要传参
class Group:
@staticmethod
def func1(name):
print('from func1') Group.func1('max') # from func1
gro = Group
gro.func1('max') # from func1

面向对象之继承的概念

"""
1.面向对象的三大特征:封装、继承、多态
2.三者中继承最为核心
3.封装和多态略为抽象
"""
1.继承的含义:
在现实生活中表示人与人之间资源的从属关系
在编程世界里表示类与类之间资源的从属关系
2.继承的目的:
和现实生活中类似,编程中继承表示不同类之间资源从属关系,比如B类继承A类,那么B类可以共享A类中的数据和功能
3.继承实操:
3.1在定义类的时候类名后面可以加括号填写其他类名,表示继承该类名
class Student:
name = 'max' class Teacher(Student):
pass tea1 = Teacher()
print(tea1.name) # max
3.2在python中支持多继承,括号内填写多个类名,用逗号隔开
class A1:
name = 'max' class A2:
age = 25 class A3:
gender = 'male' class A4(A1, A2, A3):
pass a = A4()
print(a.name, a.age, a.gender) # max 25 male
"""
1.继承其他类的类,我们称之为子类、派生类
2.被继承的类,我们称之为父类
"""

继承的本质

"""
通过对象和类的概念引出继承的本质:
对象:数据与功能的结合体
类:多个对象相同数据和功能的结合体
父类:多个类(子类)相同数据和功能的结合体
类与父类本质都是为了节省代码
"""
继承本质应该分为两部分:
抽象:将多个类相同的东西抽出去形成一个新的类
继承:将多个类继承刚刚抽取出来的新的类

对象名字的查找顺序

1.不继承情况下名字的查找顺序:
1.1:当对象中有名字,首先从对象的名称空间查找
class A1:
name = 'jason' a = A1()
print(a.__dict__) # {}
a.name = 'max'
print(a.name) # max
"""
因为查找的是对象的名字,所以每次查找的名字之前一定要先生成一个对象,并且用对象名点名字
"""
1.2当对象中没有名字时,去类中查找
class Student:
name = 'max' stu1 = Student()
print(stu1.name) # max
1.3如果类中也没有,那么直接报错
class Student:
name = 'max' stu1 = Student()
print(stu1.age) # 报错
"""
对象名称空间>>>:类(没有即报错)
"""
2.单继承情况下名字查找顺序:
2.1:对象名称空间有要找的名字时,直接去对象名称空间找
class A1:
name = 'from A1' class A2(A1):
pass a2 = A2()
a2.name = 'from a2'
print(a2.name) # from a2
2.2当对象名称空间中没有时,去产生对象的类名称空间中查找
class A1:
name = 'from A1' class A2(A1):
name = 'from A2' a2 = A2()
print(a2.name) # from A2
2.3当类名称空间中没有时,去父类名称空间中查找
class A1:
name = 'from A1' class A2(A1):
pass a2 = A2()
print(a2.name) # from A1
"""
对象名称空间>>>产生对象的类名称空间>>>父类(没有即报错)
"""
3.多继承情况下名字查找顺序:
3.1对象名称空间中有时首先找对象名称空间
class A:
name = 'from A' class B:
name = 'from B' class C:
name = 'from C' class S(A, B, C):
name = 'from S' obj = S()
obj.name = 'obj名称空间中的name'
print(obj.name) # obj名称空间中的name
3.2对象名称空间中没有时,从产生它的类名称空间中查找
class A:
name = 'from A' class B:
name = 'from B' class C:
name = 'from C' class S(A, B, C):
name = 'from S' obj = S()
print(obj.name) # from S
3.3类名称空间没有时直接从父类名称空间中查找(从左往右)
class A:
name = 'from A' class B:
name = 'from B' class C:
name = 'from C' class S(A, B, C):
pass obj = S()
print(obj.name) # from A 4.非菱形继承
class G:
name = 'from G' class A:
name = 'from A' class B:
name = 'from B' class C:
name = 'from C' class D(A):
name = 'from D' class E(B):
name = 'from E' class F(C):
name = 'from F' class S1(D, E, F):
pass obj = S1()
print(obj.name)
"""
非菱形继承查找顺序首先查找对象名称空间,在查找产生对象的类名称空间,如果没有继续查找父类名称空间,父类名称空间查找顺序为从左往右,从下往上,也可以用print(s1.mro)方法来查看查找顺序,上述题目在父类D名称空间可以找到name,如果找不到再去其父类A中查找。
"""
5.菱形继承
class G:
name = 'from G'
pass
class A(G):
name = 'from A'
pass
class B(G):
name = 'from B'
pass
class C(G):
name = 'from C'
pass
class D(A):
name = 'from D'
pass
class E(B):
name = 'from E'
pass
class F(C):
name = 'from F'
pass class S1(D,E,F):
pass
obj = S1()
print(obj.name)
"""
菱形查找顺序为先从对象你名称空间中查找,再到类名称空间,再到父类名称空间。父类名称空间查找顺序从左到右,走道菱形交汇点之前停止,直到所有的类都找完,再找交汇点的类。
"""

经典类与新式类

"""
经典类:不继承object或其子类的类
新式类:继承object或其子类的类
在python2中有经典类和新式类
在python3中只有新式类(所有类都默认继承objecr)
"""
class Student(object):pass
为了更好地兼容python2,以后我们在定义类的时候,如果没有其他明确的父类,也可以直接在括号内加上object

派生方法

1.子类基于父类做扩展:Student的父类为Person,说明在类Student中可以用到类Person中的名字,但是类Student还想扩展一个名字level,此时可以用到关键字super().__init__(父类所有的名字),然后再扩展新增自己的名字
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender class Student(Person):
def __init__(self, name, age, gender, level):
super().__init__(name, age, gender)
self.level = level stu1 = Student('max', 25, 'male', 2)
print(stu1.__dict__) # {'name': 'max', 'age': 25, 'gender': 'male', 'level': 2}
print(stu1.name) # max class Teacher(Person):
def __init__(self, name, age, gender, grade):
super().__init__(name, age, gender)
self.grade = grade tea1 = Teacher('jason', 18, 'male', 9)
print(tea1.__dict__) # {'name': 'jason', 'age': 18, 'gender': 'male', 'grade': 9}

python学习第五周总结的更多相关文章

  1. python学习第五次笔记

    python学习第五次笔记 列表的缺点 1.列表可以存储大量的数据类型,但是如果数据量大的话,他的查询速度比较慢. 2.列表只能按照顺序存储,数据与数据之间关联性不强 数据类型划分 数据类型:可变数据 ...

  2. Python学习第五堂课

    Python学习第五堂课推荐电影:华尔街之狼 被拯救的姜哥 阿甘正传 辛德勒的名单 肖申克的救赎 上帝之城 焦土之城 绝美之城 #上节内容: 变量 if else 注释 # ""& ...

  3. 201671010140. 2016-2017-2 《Java程序设计》java学习第五周

    java学习第五周心得体会        本周,是Java学习第五周,随着时间推移,随着课本内容的推进,我们接触到的程序也开始变得越来越复杂,不再是二三章那些用来练手的小程序了,这一点,在我们的例题运 ...

  4. python学习笔记第二周

    目录 一.基础概念 1.模块 1)os模块 2)sys模块 2.pyc文件 3.数据类型 1)数字 2)布尔值 3)字符串 4.数据运算 5.运算符 6.赋值运算 7.逻辑运算 8.成员运算 9.身份 ...

  5. python学习笔记五 模块上(基础篇)

    模块学习 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要 ...

  6. Python学习笔记五

    一. 递归 递归函数: def a (): print ("from b") b() def b(): print("from a ") a() a() 递推和 ...

  7. Python学习笔记五:错误与异常

    一:常见异常与错误 BaseException 所有异常的基类SystemExit 解释器请求退出KeyboardInterrupt 用户中断执行(通常是输入^C)Exception 常规错误的基类S ...

  8. Python 学习 第五篇:语句和语法

    Python程序是语句构成的,语句包含表达式,表达式嵌套在语句中,包含变量和常量,用于处理对象.Python的语法实质上是由表达式.语句和代码块构成的.语句是由表达式构成的,代码块是由多个语句构成的复 ...

  9. Python学习(五)函数 —— 内置函数 lambda filter map reduce

    Python 内置函数 lambda.filter.map.reduce Python 内置了一些比较特殊且实用的函数,使用这些能使你的代码简洁而易读. 下面对 Python 的 lambda.fil ...

  10. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

随机推荐

  1. linux系统启动达梦迁移工具失败解决办法

    在达梦数据库服务端的tool目录下执行./dts来启动迁移工具,迁移工具启动前出现报错,以下提供几种遇到问题的解决办法: 1. 报错1: 执行./dts,报错提示: [yyuser@qy-ggyf-z ...

  2. JavaScript 实现地图搜索功能

    需求:输入框输入地址点击查询,查询结果在地图定位到查询位置,显示查询位置的经纬度 <html xmlns="http://www.w3.org/1999/xhtml"> ...

  3. Spring Cloud Circuit Breaker 使用示例

    Spring Cloud Circuit Breaker 使用示例 作者: Grey 原文地址: 博客园:Spring Cloud Circuit Breaker 使用示例 CSDN:Spring C ...

  4. 【Java并发011】原理层面:CAS操作全解析

    一.前言 volatile关键字是Java51个关键字中用的比较少的一个,它是一个与多线程并发的关键字,但是实际开发中,一般不会用到,使用synchronize+wait()+notify()/not ...

  5. 这么简单,还不会使用java8 stream流的map()方法吗?

    一.前言 在日常的开发工作中经常碰到要处理list中数据的问题,比如从数据库中查出了很多学生,由于一些原因需要在内存中找出这些学生中的所有姓名,或者把名为"王五"的语文成绩暂时修改 ...

  6. 关于Mybatis-Plus中update()、updateById()方法的使用及null值的判断

    使用场景说明: 在 Mybatis-Plus 的使用过程中,经常会遇对数据库更新的情况 更新常用方法:update().updateById() 问题:经常会遇见对 null 值的处理,对传入的实体参 ...

  7. 静态文件配置 django连接MySQL django模型层初识 ORM基本语句

    目录 静态文件配置 1. 问题描述 2. 静态文件 3. 资源访问 form表单属性补充 action method 请求方法 get请求 post请求 views层 request对象 reques ...

  8. 制作 Python Docker 镜像的最佳实践

    概述 ️Reference: 制作容器镜像的最佳实践 这篇文章是关于制作 Python Docker 容器镜像的最佳实践.(2022 年 12 月更新) 最佳实践的目的一方面是为了减小镜像体积,提升 ...

  9. 【机器学习】李宏毅——自注意力机制(Self-attention)

    前面我们所讲的模型,输入都是一个向量,但有没有可能在某些场景中输入是多个向量,即一个向量集合,并且这些向量的数目并不是固定的呢? 这一类的场景包括文字识别.语音识别.图网络等等. 那么先来考虑输出的类 ...

  10. 铁威马NAS添加SSL证书实现HTTPS安全访问

    如何让你的铁威马NAS域名可以支持HTTPS呢?其实想要支持HTTPS,只需要获取第三方签发的证书,信任你的域名就可以啦! 在铁威马TOS 4.2系统中,允许用户导入安全证书,或者自我颁发安全证书,这 ...