标签:ble require span 怎么办 执行 quit init 引用 面向对象
第一次参加工作,进入了一家游戏公司,公司需要开发一款游戏《人狗大战》
一款游戏,首先得把角色和属性定下来。
角色有2个,分别是人和狗
属性如下:
人 :昵称、性别、血、攻击力
狗 :名字、品种、血、攻击力
1 #人 2 person = {‘name‘: ‘xiao_Ming‘, ‘sex‘:‘M‘, ‘hp‘: 1, ‘ad‘: 5} 3 #狗 4 dog = {‘name‘: ‘旺财‘, ‘sex‘:‘M‘, ‘hp‘: 100, ‘ad‘: 100} 5 6 def attack(person,dog): 7 #人攻击狗 8 print(‘{}攻击{}‘.format(person[‘name‘], dog[‘name‘])) 9 #狗掉血,狗的血量-人的攻击力 10 dog[‘hp‘] -= person[‘ad‘] 11 12 attack(person,dog) 13 #查看狗的血量 14 print(dog[‘hp‘])
执行输出:
xiao_Ming攻击旺财
95
人攻击了狗,狗要反击了!,再定义一个函数
1 def bite(dog,person): #狗咬人 2 print(‘{}咬了{}‘.format(dog[‘name‘], person[‘name‘])) 3 # 人掉血,人的血量-狗的攻击力 4 person[‘hp‘] -= dog[‘ad‘] 5 #判断人的血量是否小于等于0 6 if person[‘hp‘] <= 0: 7 print(‘game over,{} win‘.format(dog[‘name‘])) 8 9 bite(dog,person) 10 #查看人的血量 11 print(person[‘hp‘])
执行输出:
旺财咬了xiao_Ming
game over,旺财 win
-99
现在还只有一个玩家,有多个玩家怎么办,再加一个?
每添加一个人,就得创建一个字典
但是创造一个人物角色,没有血条,游戏就会有bug
所以,为了解决这个问题,需要定义一个模板,那么人的属性就固定下来了
定义2个函数,人和狗的模板 注意: self它不是关键字,只是一个变量而已。varieties表示品种
1 def Person(name, sex, hp, ad): 2 # 人模子 3 self = {‘name‘: name, ‘sex‘: sex, ‘hp‘: hp, ‘ad‘: ad} 4 return self 5 6 7 def Dog(name, varieties, hp, ad): 8 # 狗模子 9 self = {‘name‘: name, ‘varieties‘: varieties, ‘hp‘: hp, ‘ad‘: ad} 10 return self 11 12 def bite(dog,person): #狗咬人 13 print(‘{}咬了{}‘.format(dog[‘name‘], person[‘name‘])) 14 # 人掉血,人的血量-狗的攻击力 15 person[‘hp‘] -= dog[‘ad‘] 16 #判断人的血量是否小于等于0 17 if person[‘hp‘] <= 0: 18 print(‘game over,{} win‘.format(dog[‘name‘])) 19 20 person1 = Person(‘xiao_Ming‘,‘M‘,1,5) 21 dog1 = Dog(‘旺财‘,‘teddy‘,100,100) 22 23 bite(dog1,person1) 24 print(person1[‘hp‘])
可以发现,这里就规范了角色的属性个数,简化了创建角色的代码
执行输出:
旺财咬了xiao_Ming
game over,旺财 win
-99
如果参数传的顺序乱了,游戏就会有bug
为了解决这个问题,需要把攻击函数放在人模子里面,咬人放在狗模板里面。
外部无法直接调用。
1 def Person(name,sex,hp,ad): 2 # 人模子 3 self = {‘name‘:name, ‘sex‘:sex, ‘hp‘:hp, ‘ad‘: ad} 4 5 def attack(dog): # 人攻击狗 6 #参数已经被self接收了,所以attack函数不需要接收2个参数,1个参数就够了 7 print(‘{}攻击{}‘.format(self[‘name‘], dog[‘name‘])) 8 # 狗掉血,狗的血量-人的攻击力 9 dog[‘hp‘] -= self[‘ad‘] 10 11 self[‘attack‘] = attack #增加一个字典key 12 print(self) #查看字典的值 13 return self 14 15 def Dog(name,varieties,hp,ad): 16 # 狗模子 17 self = {‘name‘: name, ‘varieties‘: varieties, ‘hp‘: hp, ‘ad‘: ad} 18 19 def bite(person): # 狗咬人 20 # 参数已经被self接收了,所以bite函数不需要接收2个参数,1个参数就够了 21 print(‘{}咬了{}‘.format(self[‘name‘], person[‘name‘])) 22 # 人掉血,人的血量-狗的攻击力 23 person[‘hp‘] -= self[‘ad‘] 24 # 判断人的血量是否小于等于0 25 if person[‘hp‘] <= 0: 26 print(‘game over,{} win‘.format(self[‘name‘])) 27 28 self[‘bite‘] = bite 29 return self 30 31 #创建2个角色 32 person1 = Person(‘xiao_Ming‘,‘M‘,1,5) 33 dog1 = Dog(‘旺财‘,‘teddy‘,100,100) 34 #执行人攻击狗函数,它是通过字典取值调用的。 35 person1[‘attack‘](dog1) 36 print(dog1[‘hp‘])
执行输出:
{‘name‘: ‘xiao_Ming‘, ‘sex‘: ‘M‘, ‘hp‘: 1, ‘attack‘: <function Person.<locals>.attack at 0x000001F56180AAE8>, ‘ad‘: 5}
xiao_Ming攻击旺财
95
类的概念 : 具有相同属性和技能的一类事物
人类就是抽象一个概念
对象 : 就是对一个类的具体的描述
具体的人 ,她有什么特征呢?比如,眉毛弯弯的,眼睛大大的,穿着一件粉色的裙子...
比如说桌子,猫,这些是类的概念,为什么呢?因为它是抽象的。
再比如购物
商品 的大概属性: 名字,类别,价格,产地,保质期,编号...
比如 苹果 生鲜类 5块钱 --- 它是一个对象,因为对它做了具体描述
使用面向对象的好处:
1.使得代码之间的角色关系更加明确
2.增强了代码的可扩展性
3.规范了对象的属性和技能
面向对象的特点:结局的不确定性
新建一个类,类名的首字母最好是大写的,规范一点,否则Pycharm有波浪号
1 class Person: 2 静态变量 = 123 3 4 print(Person.__dict__) #内置的双下划线方法
执行输出:
{‘__doc__‘: None, ‘静态变量‘: 123, ‘__module__‘: ‘__main__‘, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Person‘ objects>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Person‘ objects>}
从结果中,可以找到 ‘静态变量‘: 123
访问静态变量,第一种方式
1 print(Person.__dict__[‘静态变量‘])
访问静态变量,第二种方式
1 print(Person.静态变量)
执行输出:123
测试外部是否可以修改静态变量
1 Person.静态变量 = 456 2 print(Person.静态变量)
执行输出:456
删除静态变量
1 del Person.静态变量 2 print(Person.__dict__)
执行输出:456
{‘__module__‘: ‘__main__‘, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Person‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Person‘ objects>, ‘__doc__‘: None}
发现找不到 ‘静态变量‘: 123 了
总结:
引用静态变量
1.类名.__dict__[‘静态变量名‘] 可以查看,但是不能删改
2.类名.静态变量名 直接就可以访问,可以删改
删除一个静态变量 del 类名.静态变量名
动态变量,指的是函数。为什么呢?因为函数内部要执行一段代码,参数不同,结果是不确定的。
1 class Person: 2 静态变量 = 123 #静态属性,静态变量 3 role = ‘person‘ 4 def f1(self): #默认带一个参数self,方法,动态属性 5 print(1234567) 6 <br>#引用动态变量 7 Person.f1()
执行报错:
TypeError: f1() missing 1 required positional argument: ‘self‘
提示缺少一个参数self
随便传一个参数,再次执行
1 Person.f1(1)
执行输出:
1234567
因为self变量必须要传,可不可以不传呢?
可以把self删掉,但是不符合规范
只要是类的方法,必须要传self
self的名字,是约定俗成
总结:
引用动态变量
1.类名.方法名 查看这个方法的内存地址
2.类名.方法名(实参) 调用了这个方法,必须传一个实参,这个实参传给了self
类和对象,是相对的概念
类是已经创造的模子
对象是用模子填充
调用类名加括号,创造一个对象
创造一个命名空间,唯一属于对象
1 alex = Person() # 创造一个对象 2 alex 是对象、实例 3 Person是类 4 对象 = 类名()
类变成对象的过程,是实例化的 过程
实例化,是产生实例的过程
总结:
创造一个对象 - 实例化
产生一个实例(对象)的过程
对象 = 类名()
计算机只认识二进制
写的代码,是自己能看懂的。但是执行的过程中,并不是这样种的。
实例化的过程:
1.创造一个实例,将会作为一个实际参数 # python
2.自动触发一个__init__的方法,并且把实例以参数的形式传递给__init__方法中的self形参
3.执行完__init__方法之后,会将self自动返回给alex
__init__方法 :初始化方法,给一个对象添加一些基础属性的方法,一般情况下是针对self的赋值
1 class Person: 2 role = ‘person‘ #静态属性 3 def __init__(self): 4 print(self) #查看变量 5 6 alex = Person() 7 print(alex) #查看变量
执行输出:
<__main__.Person object at 0x0000025F23D8BC18>
<__main__.Person object at 0x0000025F23D8BC18>
可以看到2次查看变量的内存地址是一样的。
也就是说self表示实例本身。
如果实例化时,传一个参数
1 alex = Person(‘sb‘)
执行报错:
TypeError: __init__() takes 1 positional argument but 2 were given
因为传的参数是多余的,为什么呢?在没传参之前,执行正常,传参之后,就报错了。
因为实例化时,它把实例本身传给类,self接收了参数,也就是实例本身。再多传一个参数,就报错了。
类里面再多写一个参数,实例化时,传一个参数
1 class Person: 2 role = ‘person‘ #静态属性 3 def __init__(self,name): 4 print(self,name) #查看变量 5 6 alex = Person(‘sb‘) 7 print(alex) #查看变量
执行输出:
<__main__.Person object at 0x00000243EC48B908> sb
<__main__.Person object at 0x00000243EC48B908>
类和外部唯一的联系,就是self
执行输出:
{‘name‘: ‘sb‘}
让alex拥有自己的字典
1 class Person: 2 role = ‘person‘ #静态属性 3 def __init__(self,name,sex,hp,ad): 4 self.__dict__[‘name‘] = name 5 self.__dict__[‘sex‘] = sex 6 self.__dict__[‘hp‘] = hp 7 self.__dict__[‘ad‘] = ad 8 9 alex = Person(‘sb‘,‘M‘,1,5) 10 print(alex.__dict__)
执行输出:
{‘name‘: ‘sb‘, ‘ad‘: 5, ‘sex‘: ‘M‘, ‘hp‘: 1}
每次调用Person()都会产生一个新的内存空间,它会返回给调用者
但是上面的写法,不规范
第二种写法
1 class Person: 2 role = ‘person‘ #静态属性 3 def __init__(self,name,sex,hp,ad): 4 self.name = name 5 self.sex = sex 6 self.hp = hp 7 self.ad = ad 8 9 alex = Person(‘sb‘,‘M‘,1,5) 10 print(alex.__dict__)
执行输出,效果同上。
推荐使用第二种方法,从此以后,就不要使用__dict__的方法修改属性
直接使用对象名.属性名 修改
1 class Person: 2 role = ‘person‘ #静态属性 3 def __init__(self,name,sex,hp,ad): 4 self.name = name 5 self.sex = sex 6 self.hp = hp 7 self.ad = ad 8 9 alex = Person(‘sb‘,‘M‘,1,5) 10 alex.name = ‘a_sb‘ 11 print(alex.name)
执行输出:
a_sb
增加一个类方法
1 class Person: 2 role = ‘person‘ #静态属性 3 def __init__(self,name,sex,hp,ad): 4 self.name = name 5 self.sex = sex 6 self.hp = hp 7 self.ad = ad 8 def attack(self): 9 print(‘{}发起了一次攻击‘.format(self.name))
执行类方法
1 alex = Person(‘sb‘,‘M‘,1,5) 2 Person.attack(alex)
执行输出:
sb发起了一次攻击
执行类方法可以简写
1 alex = Person(‘sb‘,‘M‘,1,5) 2 alex.attack()
方法的调用 :
1.类名.方法名(对象名) # 那么方法中的self参数就指向这个对象
2.对象名.方法名() # 这样写 相当于 方法中的self参数直接指向这个对象,推荐使用
attack是和Person关联起来的
所以外部可以直接调用attack方法
小明,10岁,男,上山去砍柴
小明,10岁,男,开车去东北
小明,10岁,男,最爱大保健
老李,90岁,男,上山去砍柴
老李,90岁,男,开车去东北
老李,90岁,男,最爱大保健
老张…
1 class Person(object): 2 def __init__(self, name, age, sex=‘男‘, hobby=(‘上山去砍柴‘, ‘开车去东北‘, ‘最爱大保健‘)): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 self.hobby = hobby 7 8 def info(self): 9 for i in self.hobby: 10 print(‘{},{}岁,{},{}‘.format(self.name, self.age, self.sex, i)) 11 12 13 ming = Person(‘小明‘, 10) 14 li = Person(‘老李‘, 90) 15 ming.info() 16 li.info()
使用面向对象的方式编码三级菜单
将之前的代码复制粘贴过来,切割成面向对象方式
1 # -*- coding: utf-8 -*- 2 class AreaMenu(object): 3 def __init__(self): 4 self.zone = { 5 ‘山东‘: { 6 ‘青岛‘: [‘四方‘, ‘黄岛‘, ‘崂山‘, ‘李沧‘, ‘城阳‘], 7 ‘济南‘: [‘历城‘, ‘槐荫‘, ‘高新‘, ‘长青‘, ‘章丘‘], 8 ‘烟台‘: [‘龙口‘, ‘莱山‘, ‘牟平‘, ‘蓬莱‘, ‘招远‘] 9 }, 10 ‘江苏‘: { 11 ‘苏州‘: [‘沧浪‘, ‘相城‘, ‘平江‘, ‘吴中‘, ‘昆山‘], 12 ‘南京‘: [‘白下‘, ‘秦淮‘, ‘浦口‘, ‘栖霞‘, ‘江宁‘], 13 ‘无锡‘: [‘崇安‘, ‘南长‘, ‘北塘‘, ‘锡山‘, ‘江阴‘] 14 }, 15 ‘浙江‘: { 16 ‘杭州‘: [‘西湖‘, ‘江干‘, ‘下城‘, ‘上城‘, ‘滨江‘], 17 ‘宁波‘: [‘海曙‘, ‘江东‘, ‘江北‘, ‘镇海‘, ‘余姚‘], 18 ‘温州‘: [‘鹿城‘, ‘龙湾‘, ‘乐清‘, ‘瑞安‘, ‘永嘉‘] 19 } 20 } 21 self.province = list(self.zone.keys()) 22 self.run() 23 24 def run(self): # 省列表 25 while True: 26 print(‘省‘.center(20, ‘*‘)) 27 # 打印省列表 28 for i in self.province: 29 print(‘{}\t{}‘.format(self.province.index(i) + 1, i)) 30 province_input = input(‘请输入省编号,或输入q/Q退出:‘).strip() 31 if province_input.isdigit(): 32 province_input = int(province_input) 33 if 0 < province_input <= len(self.province): 34 # 省编号,由于显示加1,获取的时候,需要减1 35 province_id = province_input - 1 36 # 城市列表 37 city = list(self.zone[self.province[province_id]].keys()) 38 # 进入市区列表 39 self.city(province_id, city) 40 else: 41 print("\033[41;1m省编号 {} 不存在!\033[0m".format(province_input)) 42 elif province_input.upper() == ‘Q‘: 43 break 44 else: 45 print("\033[41;1m输入省编号非法!\033[0m") 46 47 def city(self, province_id, city): # 市区列表 48 if province_id == ‘‘ or city == ‘‘: 49 return ‘province_id 和 city 参数不能为空‘ 50 while True: 51 print(‘市‘.center(20, ‘*‘)) 52 for j in city: 53 print(‘{}\t{}‘.format(city.index(j) + 1, j)) 54 city_input = input("请输入市编号,或输入b(back)返回上级菜单,或输入q(quit)退出:").strip() 55 if city_input.isdigit(): 56 city_input = int(city_input) 57 if 0 < city_input <= len(city): 58 # 市编号,由于显示加1,获取的时候,需要减1 59 city_id = city_input - 1 60 # 县列表 61 county = self.zone[self.province[province_id]][city[city_id]] 62 # 进入县列表 63 self.county(county) 64 else: 65 print("\033[41;1m市编号 {} 不存在!\033[0m".format(city_input)) 66 elif city_input.upper() == ‘B‘: 67 break 68 elif city_input.upper() == ‘Q‘: 69 # 由于在多层while循环里面,直接exit退出即可 70 exit() 71 else: 72 print("\033[41;1m输入市编号非法!\033[0m") 73 74 def county(self, county): # 县列表 75 if county == ‘‘: 76 return ‘county 参数不能为空‘ 77 while True: 78 print(‘县‘.center(20, ‘*‘)) 79 for k in county: 80 print(‘{}\t{}‘.format(county.index(k) + 1, k)) 81 # 到县这一级,不能输入编号了,直接提示返回菜单或者退出 82 county_input = input("输入b(back)返回上级菜单,或输入q(quit)退出:").strip() 83 if county_input == ‘b‘: 84 # 终止此层while循环,跳转到上一层While 85 break 86 elif county_input == ‘q‘: 87 # 结束程序 88 exit() 89 else: 90 print("\033[41;1m已经到底线了,请返回或者退出!\033[0m") 91 92 93 if __name__ == ‘__main__‘: 94 AreaMenu()
# -*- coding: utf-8 -*-
class
AreaMenu(
object
):
def
__init__(
self
):
self
.zone
=
{
‘山东‘
: {
‘青岛‘
: [
‘四方‘
,
‘黄岛‘
,
‘崂山‘
,
‘李沧‘
,
‘城阳‘
],
‘济南‘
: [
‘历城‘
,
‘槐荫‘
,
‘高新‘
,
‘长青‘
,
‘章丘‘
],
‘烟台‘
: [
‘龙口‘
,
‘莱山‘
,
‘牟平‘
,
‘蓬莱‘
,
‘招远‘
]
},
‘江苏‘
: {
‘苏州‘
: [
‘沧浪‘
,
‘相城‘
,
‘平江‘
,
‘吴中‘
,
‘昆山‘
],
‘南京‘
: [
‘白下‘
,
‘秦淮‘
,
‘浦口‘
,
‘栖霞‘
,
‘江宁‘
],
‘无锡‘
: [
‘崇安‘
,
‘南长‘
,
‘北塘‘
,
‘锡山‘
,
‘江阴‘
]
},
‘浙江‘
: {
‘杭州‘
: [
‘西湖‘
,
‘江干‘
,
‘下城‘
,
‘上城‘
,
‘滨江‘
],
‘宁波‘
: [
‘海曙‘
,
‘江东‘
,
‘江北‘
,
‘镇海‘
,
‘余姚‘
],
‘温州‘
: [
‘鹿城‘
,
‘龙湾‘
,
‘乐清‘
,
‘瑞安‘
,
‘永嘉‘
]
}
}
self
.province
=
list
(
self
.zone.keys())
self
.run()
def
run(
self
):
# 省列表
while
True
:
print
(
‘省‘
.center(
20
,
‘*‘
))
# 打印省列表
for
i
in
self
.province:
print
(
‘{}\t{}‘
.
format
(
self
.province.index(i)
+
1
, i))
province_input
=
input
(
‘请输入省编号,或输入q/Q退出:‘
).strip()
if
province_input.isdigit():
province_input
=
int
(province_input)
if
0
< province_input <
=
len
(
self
.province):
# 省编号,由于显示加1,获取的时候,需要减1
province_id
=
province_input
-
1
# 城市列表
city
=
list
(
self
.zone[
self
.province[province_id]].keys())
# 进入市区列表
self
.city(province_id, city)
else
:
print
(
"\033[41;1m省编号 {} 不存在!\033[0m"
.
format
(province_input))
elif
province_input.upper()
=
=
‘Q‘
:
break
else
:
print
(
"\033[41;1m输入省编号非法!\033[0m"
)
def
city(
self
, province_id, city):
# 市区列表
if
province_id
=
=
‘
‘ or city == ‘
‘:
return
‘province_id 和 city 参数不能为空‘
while
True
:
print
(
‘市‘
.center(
20
,
‘*‘
))
for
j
in
city:
print
(
‘{}\t{}‘
.
format
(city.index(j)
+
1
, j))
city_input
=
input
(
"请输入市编号,或输入b(back)返回上级菜单,或输入q(quit)退出:"
).strip()
if
city_input.isdigit():
city_input
=
int
(city_input)
if
0
< city_input <
=
len
(city):
# 市编号,由于显示加1,获取的时候,需要减1
city_id
=
city_input
-
1
# 县列表
county
=
self
.zone[
self
.province[province_id]][city[city_id]]
# 进入县列表
self
.county(county)
else
:
print
(
"\033[41;1m市编号 {} 不存在!\033[0m"
.
format
(city_input))
elif
city_input.upper()
=
=
‘B‘
:
break
elif
city_input.upper()
=
=
‘Q‘
:
# 由于在多层while循环里面,直接exit退出即可
exit()
else
:
print
(
"\033[41;1m输入市编号非法!\033[0m"
)
def
county(
self
, county):
# 县列表
if
county
=
=
‘‘:
return
‘county 参数不能为空‘
while
True
:
print
(
‘县‘
.center(
20
,
‘*‘
))
for
k
in
county:
print
(
‘{}\t{}‘
.
format
(county.index(k)
+
1
, k))
# 到县这一级,不能输入编号了,直接提示返回菜单或者退出
county_input
=
input
(
"输入b(back)返回上级菜单,或输入q(quit)退出:"
).strip()
if
county_input
=
=
‘b‘
:
# 终止此层while循环,跳转到上一层While
break
elif
county_input
=
=
‘q‘
:
# 结束程序
exit()
else
:
print
(
"\033[41;1m已经到底线了,请返回或者退出!\033[0m"
)
if
__name__
=
=
‘__main__‘
:
AreaMenu()
标签:ble require span 怎么办 执行 quit init 引用 面向对象
原文地址:https://www.cnblogs.com/sky77/p/9680866.html