python自动化_day6_面向对象_组合,继承,多态

复习:http://www.cnblogs.com/Eva-J/articles/7228075.html

模块

 1 import collections,os,sys,re,random,time
 2 collections.defaultdict()  #默认字典   默认字典的优势就是该字典中如果没有元素就直接添加
 3 collections.OrderedDict()  #有序字典   字典是有序的可以直接用索引调用
 4 collections.namedtuple()   #可命名元祖 可以把两个元组重命名之后简单调用
 5 time.time()  #时间戳时间
 6 time.strftime()#字符串时间
 7 time.localtime()#结构化时间
 8 random.choice([1,‘23‘,[4,5]])  # #1或者23或者[4,5] #随机选择一个返回
 9 random.randint(1,5)# 大于等于1且小于等于5之间的整数
10 random.randrange(1,10,2) # 大于等于1且小于10之间的奇数
11 random.sample([1,‘23‘,[4,5]],2) # #列表元素任意2个组合
12 #os模块中很多跟操作系统相关的东西
13     #文件相关
14     #文件夹相关的
15     #和执行系统命令相关
16     #和路径相关的
17 sys.argv()           #命令行参数List,第一个元素是程序本身路径
18 sys.exit()        #退出程序,正常退出时exit(0),错误退出sys.exit(1)
19 sys.version       #获取Python解释程序的版本信息
20 sys.path           #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
21 sys.platform       #返回操作系统平台名称
22 #re模块中的正则表达式使用很重要

初识面向对象

模拟一个人狗大战的游戏:使用函数,来写人狗大战

 1 #首先进一个游戏公司
 2 #写人狗大战的游戏
 3 #想一下 需要有一个人 一个狗  需要互相攻击(动作)会影响游戏人物或者狗的值的变化
 4 #人  需要有基础属性(生命值,武力值,名字,性别,背包)
 5 def Person(name,sex,hp,dps):  #人模子 创建出来的所有人都有相同的属性值
 6     dic = {‘name‘:name,‘sex‘:sex,‘hp‘:hp,‘dps‘:dps,‘bag‘:[]}
 7     return dic
 8 alex = Person(‘alex‘,‘N‘,250,5)
 9 #狗  需要有基础属性(生命值,武力值,名字,品种)
10 def Dog(name,kind,hp,dps):
11     dic = {‘name‘: name, ‘kind‘: kind, ‘hp‘: hp, ‘dps‘: dps}
12     return dic
13 ha2 = Dog(‘哈士奇‘,‘藏獒‘,15000,200)
14 #需要给人和狗安排技能 人可以打狗,狗可以咬人
15 print(alex)
16 print(ha2)
17 #人打狗
18 def attack(person_name,dog_name,person_dps,dog_hp):
19     print(‘%s打了%s,%s掉了%s点血,还剩%s血‘ %(person_name,dog_name,dog_name,person_dps,dog_hp-person_dps))
20 attack(alex[‘name‘],ha2[‘name‘],alex[‘dps‘],ha2[‘hp‘])
21 print(ha2)
22 #目前问题 人大狗只是显示了一个数值没有改变原狗的属性,并且传参还特别麻烦所以需要想办法
23 def attack(person,dog):
24     dog[‘hp‘] -= person[‘dps‘]
25     print(‘%s打了%s,%s掉了%s点血,还剩%s血‘ %(person[‘name‘],dog[‘name‘],dog[‘name‘],person[‘dps‘],dog[‘hp‘]))
26 attack(alex,ha2)
27 #狗咬人
28 def bite(dog,person):
29     person[‘hp‘]-= dog[‘dps‘]
30     print(‘%s咬%s,%s掉了%s点血,还剩%s血‘ % (dog[‘name‘], person[‘name‘], person[‘name‘], dog[‘dps‘], person[‘hp‘]))
31 bite(ha2,alex)
32 print(ha2,alex)
33 #从这里基本实现了人打狗,狗咬人的互动  但是有一个问题,思考如果人咬狗或者狗打人会怎么办,这是一个问题所以我们需要进行动作限制

下面思考需要对动作做限制可以如下:

 1 def Person(name,sex,hp,dps):
 2     dic = {‘name‘:name,‘sex‘:sex,‘hp‘:hp,‘dps‘:dps,‘bag‘:[]}
 3     def attack(dog):
 4         dog[‘hp‘] -= dic[‘dps‘]
 5         print(‘%s打了%s,%s掉了%s点血,还剩%s血‘ % (dic[‘name‘], dog[‘name‘], dog[‘name‘], dic[‘dps‘], dog[‘hp‘]))
 6     dic[‘attack‘] = attack
 7     return dic
 8 def Dog(name,kind,hp,dps):
 9     dic = {‘name‘: name, ‘kind‘: kind, ‘hp‘: hp, ‘dps‘: dps}
10     def bite(person):
11         person[‘hp‘] -= dic[‘dps‘]
12         print(‘%s咬%s,%s掉了%s点血,还剩%s血‘ % (dic[‘name‘], person[‘name‘], person[‘name‘], dic[‘dps‘], person[‘hp‘]))
13     dic[‘bite‘] = bite
14     return dic
15 alex = Person(‘alex‘,‘N‘,250,5)
16 ha2 = Dog(‘哈士奇‘,‘藏獒‘,15000,200)
17
18 print(alex)
19 print(ha2)
20 print(alex[‘attack‘])
21 alex[‘attack‘](ha2)

以上就是使用了基本的面向对象的思想。

面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。

优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。

缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。

应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。

面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。面向对象的程序设计好比如来设计西游记,如来要解决的问题是把经书传给东土大唐,如来想了想解决这个问题需要四个人:唐僧,沙和尚,猪八戒,孙悟空,每个人都有各自的特征和技能(这就是对象的概念,特征和技能分别对应对象的属性和方法),然而这并不好玩,于是如来又安排了一群妖魔鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象。然后取经开始,师徒四人与妖魔鬼怪神仙互相缠斗着直到最后取得真经。如来根本不会管师徒四人按照什么流程去取。

面向对象的程序设计的

优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。

应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。

在python 中面向对象的程序设计并不是全部。

面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

了解一些名词:类、对象、实例、实例化

类:具有相同特征的一类事物(人、狗、老虎)

对象/实例:具体的某一个事物(隔壁阿花、楼下旺财)

实例化:类——>对象的过程(这在生活中表现的不明显,我们在后面再慢慢解释)

按照以前的逻辑,人狗大战创建一个人,创建一只狗,人打狗,狗咬人,两个函数做一些动作,可以理解为面向过程编程

造模子 -------->>>面向对象

好处:规范了一些角色的属性项目,属性的名字,技能,技能的名字

权限:有一些函数只能是这个角色才可以调用

面向对象的规则:类被创造出来  就是一个模子,谁为了描述对象的

  类:具有相同属性和相同动作的一类事物组成一个类 类是抽象的

  对象:具体的某一个具有实际属性和具体动作的一个实体,对象是具体的

只要是写在类名字中的名字,不管是变量还是函数名,都不能在类的外边直接使用
类的功能:查看属性、实例化----创建对象

 1 class 类名:
 2     静态属性 = 123
 3     def 动态属性(self):  #self  在类中的方法一个默认的参数
 4         print(self)
 5 print(类名.静态属性)
 6 类名.静态属性 = 456
 7 print(类名.静态属性)
 8 类名.静态属性2 = ‘abc‘
 9 print(类名.静态属性2)
10 del 类名.静态属性2
11 print(类名.静态属性2)
12 print(类名.__dict__)  #类中必要的默认值之外,还记录了程序员在类中定义的所有名字

类名可以查看某个方法,但是一般情况下,我们不直接使用类名调用方法,类的函数名第一个字母一定是大写的,函数的第一个字母一定是小写的。

创建一个类:

 1 class Person:pass
 2 alex = Person()
 3 print(alex)  #object  对象  alex是Person类的一个对象
 4 对象  = 类名()
 5 print(Person)
 6 print(alex.__dict__)
 7 # alex name hp  dps bag sex
 8 alex.__dict__[‘name‘] = ‘alex‘
 9 alex.__dict__[‘sex‘] = ‘N‘
10 alex.__dict__[‘hp‘] = 250
11 alex.__dict__[‘dps‘] = 5
12 alex.__dict__[‘bag‘] = []
13 print(alex.__dict__)
14 alex.name = ‘alex‘
15 alex.hp = 250
16 alex.dps = 5
17 alex.bag = []
18 alex.sex = ‘N‘
19 print(alex.__dict__)

分析:为什么会执行init中的内容 self到底是什么

实例化的过程:

  1、类名()就是实例化

  2、在实例化的过程中发生了很多事情外部是看不到的

  3、创造一个对象,自动调用__init__方法

  4、这个被创造的对象会被当做实际参数传到__init__方法中,并且传给第一个self参数

  5、执行__init__方法中的内容

  6、自动把self方法作为返回值,返回给实例化的地方

 1 #人狗大战 使用面向对象
 2 class Person:
 3     def __init__(self,name,hp,sex,dps):
 4         self.name = name
 5         self.hp = hp
 6         self.sex = sex
 7         self.dps = dps
 8         self.bag = []
 9     def attack(self,dog):
10         dog.hp -= self.dps
11         print(‘%s打了%s,%s掉了%s点血,还剩%s血‘ % (self.name, dog.name, dog.name, self.dps, dog.hp))
12 class Dog:
13     def __init__(self,name,hp,kind,dps):
14         self.name = name
15         self.hp = hp
16         self.kind = kind
17         self.dps = dps
18     def bite(self,person):
19         person.hp -= self.dps
20         print(‘%s咬%s,%s掉了%s点血,还剩%s血‘ % (self.name, person.name, person.name, self.dps, person.hp))
21 alex = Person(‘aelx‘,250,‘N‘,5)
22 ha2 = Dog(‘哈士奇‘,15000,‘藏獒‘,200)
23 print(alex.__dict__)  #init的储存的内容查看使用__dict__
24 Person.attack(alex)  #类中的函数调用
25 alex.attack(ha2)
26 ha2.bite(alex)
27 print(alex.__dict__)
28 print(ha2.__dict__)

对象名 方法名 相当于调用一个函数,这个函数默认把对象名作为第一个参数传入函数中

剩余的其他参数根据我们的需求可以随意传

 1 #小练习 计算圆形的面积和周长 已知半径
 2 from math import pi
 3 class Circle:
 4     def __init__(self,r):
 5         self.r = r
 6     def perimeter(self):
 7         print(2*pi*self.r)
 8     def area(self):
 9         print(pi*self.r*self.r)
10 circle = Circle(5)
11 circle.perimeter()
12 circle.area()
13
14 #每一个角色都有属于自己的属性和方法
15 #高可扩展性  可读性 规范性
16 #结局不可控

#############命名空间####################

类有自己的命名空间,对象也有自己的命名空间,分析对象是否可以访问类的命名空间,类是否可以访问对象的命名空间

1 class Person:
2     COUNTRY = ‘中国人‘  #静态属性
3     def __init__(self,name):
4         self.name = name
5     def eat(self):
6         print(‘%s在吃泔水‘ %self.name)
7 alex = Person(‘alex‘)
8 egon = Person(‘egon‘)
#当一个类在创建一个实例的时候,就产生了一个这个实例和类之间的联系#可以通过实例 对象 找到实例化它的类#类不能找到他的实例化#在访问变量的时候,都先使用自己命名空间中的,如果自己的空间没有,再到类的空间中去找#在使用对象修改静态变量的过程中,相当于在自己的空间中创建了一个新的变量#在类的静态变量的操作中,应该使用类名来直接进行操作,就不会出现乌龙操作

1 #创建一个类,计算这个类创建了多少个实例
2 class Foo:
3     count = 0
4     def __init__(self):
5         Foo.count += 1
6 f1 = Foo()
7 print(Foo.count)

###########################组合#########################

 1 组合: 一个类的对象作为另外一个类对象的的属性
 2 class Person:
 3     def __init__(self,name,hp,sex,dps):
 4         self.name = name
 5         self.hp = hp
 6         self.sex = sex
 7         self.dps = dps
 8         self.bag = []
 9     def attack(self,dog):
10         dog.hp -= self.dps
11         print(‘%s打了%s,%s掉了%s点血,还剩%s血‘ % (self.name, dog.name, dog.name, self.dps, dog.hp))
12 class Dog:
13     def __init__(self,name,hp,kind,dps):
14         self.name = name
15         self.hp = hp
16         self.kind = kind
17         self.dps = dps
18     def bite(self,person):
19         person.hp -= self.dps
20         print(‘%s咬%s,%s掉了%s点血,还剩%s血‘ % (self.name, person.name, person.name, self.dps, person.hp))
21 alex = Person(‘aelx‘,250,‘N‘,5)
22 ha2 = Dog(‘哈士奇‘,15000,‘藏獒‘,200)
23 print(alex.name)
 1 #基础数据类型 都是类
 2 #‘alex‘ : str 的对象
 3 # alex.name = ‘alex‘
 4 #给alex装备一个武器  alex打不过狗花钱装备一个武器
 5 class  Weapon:
 6     def __init__(self,name,price,dps):
 7         self.name = name
 8         self.price = price
 9         self.dps = dps
10     def kill(self,dog):
11         dog.hp -= self.dps
12 dagoubang = Weapon(‘dagougun‘,600000,10000)
13 alex.money = 1000000
14 if alex.money >= dagoubang.price:
15     alex.weapon = dagoubang
16     alex.weapon.kill(ha2)
17     print(ha2.hp)

计算圆环的面积和周长,已知外圆

 1 from math import pi
 2 class Circle:
 3     def __init__(self,r):
 4         self.r = r
 5     def perimeter(self):
 6         return 2*pi*self.r
 7     def area(self):
 8         return pi*self.r*self.r
 9 # circle = Circle(5)
10 class Cirque:
11     def __init__(self,outside_r,inside_r):  #已知外圆内园的半径调用外圆的方法就是直接调用外圆类的函数
12         self.out_circle = Circle(outside_r)
13         self.in_circle = Circle(inside_r)
14     def perimeter(self):
15         return self.out_circle.perimeter() + self.in_circle.perimeter()
16     def area(self):
17         #返回大圆面积 - 小圆面积
18         return  self.out_circle.area() - self.in_circle.area()
19 ring = Cirque(10,5)
20 print(ring.area())
21 print(ring.perimeter())
#组合是描述了一种什么有什么的关系  圆环有圆   人有武器
#面向对象初识
# 如何创建一个类
# 类的实例化 # 实例和对象是一回事
# 对象调用方法
# 类调用静态属性
# __init__
#命名空间
#类的组合用法  人有武器 圆环有圆  两个类之间有关系 调用类的方法或者函数

#####################继承###########################

#为什么会有继承  为了解决代码的冗余问题
class Person:
    def __init__(self,name,hp,sex,dps):
        self.name = name
        self.hp = hp
        self.sex = sex
        self.dps = dps
        self.bag = []
    def attack(self,dog):
        dog.hp -= self.dps
        print(‘%s打了%s,%s掉了%s点血,还剩%s血‘ % (self.name, dog.name, dog.name, self.dps, dog.hp))
class Dog:
    def __init__(self,name,hp,kind,dps):
        self.name = name
        self.hp = hp
        self.kind = kind
        self.dps = dps
    def bite(self,person):
        person.hp -= self.dps
        print(‘%s咬%s,%s掉了%s点血,还剩%s血‘ % (self.name, person.name, person.name, self.dps, person.hp))
alex = Person(‘aelx‘,250,‘N‘,5)
ha2 = Dog(‘哈士奇‘,15000,‘藏獒‘,200)
print(alex.name)
#分析以上代码人和狗都有相同的属性,如果单独写,会显得很啰嗦,为了解决这个办法可以使用面向对象的继承

继承分为:单继承和多继承

 1 #单继承
 2 class Parent:pass
 3 class Son(Parent):pass
 4 #Son 类继承Parent类
 5 #父类  基类 超类 ------Parent类
 6 #子类 派生类 -------Son类
 7
 8 #多继承
 9 class Parent1:pass
10 class Parent2:pass
11 class Son(Parent1,Parent2):pass

解决上面人狗大战中代码冗余问题:直接使用继承,创建一个动物类,包含人和狗一些必要的属性。

 1 class Animal:
 2     def __init__(self,name,hp,dps):
 3         print(‘---------->‘)
 4         self.name = name
 5         self.hp = hp
 6         self.dps = dps
 7     def eat(self):   #父类的eat方法子类可以调用
 8         print(‘%s吃药回血了‘ %self.name)
 9 class Person(Animal):
10     def __init__(self,name,hp,dps,sex):
11         super().__init__(name,hp,dps)# Animal.__init__(self,name,hp,dps)
12         self.sex = sex
13     def attack(self, dog):
14         dog.hp -= self.dps
15         print(‘%s打了%s,%s掉了%s点血,还剩%s血‘ % (self.name, dog.name, dog.name, self.dps, dog.hp))
16
17 class Dog(Animal):
18     def __init__(self,name, hp, dps,kind):
19         super().__init__(name, hp, dps)# Animal.__init__(self, name, hp, dps)
20         self.kind = kind
21     def bite(self, person):
22         person.hp -= self.dps
23         print(‘%s咬%s,%s掉了%s点血,还剩%s血‘ % (self.name, person.name, person.name, self.dps, person.hp))
24 alex = Person(‘alex‘,250,5,‘N‘)
25 ha2 = Dog(‘哈士奇‘,15000,200,‘藏獒‘)
26 print(alex.__dict__)
27 print(ha2.__dict__)
28 ha2.eat()
29 alex.eat()
30 ha2.bite(alex)
31 alex.attack(ha2)
 1 #面试题
 2 class Foo:
 3     def __init__(self):
 4         self.func()
 5     def func(self):
 6         print(‘in foo‘)
 7 class Son(Foo):
 8     def func(self):
 9         print(‘in son‘)
10 Son()
11
12 #python两种类
13     #python3已经灭绝了 经典类
14         #经典类都遵循深度优先算法
15     #新式类 python3所有的类都是新式类      class A(object): 所有的新式类都继承object
16         #新式类在多继承中都遵循广度优先算法
17 #super和找父类这件事是两回事
18 #在单继承中super就是找父类
19 #在多级继承中 super的轨迹 是根据整个模型的起始点展开一个广度优先算法 遵循mro规则来的

原文地址:https://www.cnblogs.com/tewu/p/9046351.html

时间: 2024-10-12 02:37:49

python自动化_day6_面向对象_组合,继承,多态的相关文章

Python之面向对象的组合、多态、菱形问题、子类中重用父类的两种方式

一.组合 ''' 1.什么是组合 组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象 2.为何用组合 组合也是用来解决类与类直接代码冗余问题的 3.如何用组合 ''' # 继承减少代码冗余,但是将类与类进行了强耦合,python不崇尚,所以能不用继承就尽量不用继承 class OldboyPeople: school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age se

python 全栈 python基础 (十六)面向对象编程的 继承 多态与多态性 封装

一.继承顺序: 多继承情况下,有两种方式:深度优先和广度优先 1.py3/py2 新式类的继承:在查找属性时遵循:广度优先 继承顺序是多条分支,按照从左往右的顺序,进行一步一步查找,一个分支走完会走另一个分支(若多条分支汇总一个头,除最后一条分支能走到头,其他的都走到次之位置停止,进行下一条分支的查找),直到查找到头为止. 可以利用 类名.__mro__ 的方法查看类之间的继承关系(经典类没有这种方法) 1 class B(object): 2 def func(self): 3 print('

Python 基础之面向对象类的继承与多态

一:继承 定义:一个类除了拥有自身的属性方法之外,还拥有另外一个类的属性和方法继承: 1.单继承 2.多继承子类: 一个类继承了另外一个类,那么这个类是子类(衍生类)父类:一个类继承了另外一个类,被继承的那个类是父类(超类,基类)object 是所有的类的父类1.单继承 #例:class Human():    def eat(self):        print("远古人类打猎,吃猎物") def sleep(self): print("远古人类吃饱了就睡觉")

面向对象之 封装 继承 多态

#!/usr/bin/env python # _*_ coding:utf-8 _*_ class Role(object): #继承object类 ac = None #脚本一执行跟着类一起存到了内存 类变量 #类变量和实例变量的区别: #类变量脚本执行跟着类一起存到了内存,不管是否调用都存在,实例变量是存在实例内的, def __init__(self,name,role,weapon): #初始化方法 实例化后自动执行 #self 代表实例本身.谁调用就是谁. name role,wea

python(类的封装调用/继承/多态)

一.类的定义 类:用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例 对象:类实例化出来的叫做对象 对象和类的关系:类和对象的关系就像模具和铸件的关系,类的实例化的结果就是对象,而对对象的抽象就是类. 类和实例 面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如 Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同. 仍以 Student 类为

C#面向对象编程 封装 继承 多态

  C#面向对象编程 什么是面向对象? 面向对象编程是上个实际六十年代继面向结构编程之后提出的一个新的编程思想 封装,继承,多态 封装,继承,多态是面向对象编程的核心: 封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类).被封装的对象通常被称为抽象数据类型 意义是:保护数据不被破坏(例如一台电视机我们能使用它但是不能随意改变内部的电路) 关键字:private,public,protected,internal Public string name;

面向对象之封装,继承,多态的理解

封装 1.什么是封装 封装(encapsulation)又叫隐藏实现(Hiding the implementation).就是只公开代码单元的对外接口,而隐藏其具体实现. 其实生活中处处都是封装,手机,电脑,电视这些都是封装.你只需要知道如何去操作他们,并不需要知道他们里面是怎么构造的,怎么实现这个功能的. 2.如何实现封装 在程序设计里,封装往往是通过访问控制实现的.C++,Java,AS3中都有 Public, Protected, Private 等访问控制符.通过用Public将信息暴

Python自动化开发 - 面向对象(二)

本节内容 1.isinstance(obj,cls)和issubclass(sub,super) 2.反射 3.__setattr__,__delattr__,__getattr__ 一. isinstance(obj,cls)和issubclass(sub,super) 1.isinstance(obj,cls) 检查obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstance(obj, Foo)) # True 2.

(一)Python入门-6面向对象编程:09多态

多态: 多态(polymorphism)是指同一个方法调用由于对象不同可能会产生不同的行为.在现实 生活中,我们有很多例子.比如:同样是调用人的休息方法,张三的休息是睡觉,李四的休 息是玩游戏,程序员是敲代码.同样是吃饭的方法,中国人用筷子吃饭,英国人用刀叉吃 饭,印度人用手吃饭. 关于多态要注意以下2点: 1. 多态是方法的多态,属性没有多态. 2. 多态的存在有两个必要条件:继承.方法重写. [操作] #多态 class Animal: def shout(self): print('动物叫