Python学习-07-面向对象编程初级

一、摘要

1)     类:

属性:实例变量

         类变量

        私有属性 __var

方法:构造方法:初始化实例

         析构方法:实例销毁的时候自动执行的方法。

         私有方法     

2)     对象:实例化一个类之后得到的对象

3)     封装:把一些功能的实现细节不对外暴露

4)     继承:代码的重用

        多继承:Python3中都是广度优先。

5)     多态:接口重用,一个接口,多种实现

 

二、类和方法(参考http://www.cnblogs.com/alex3714/articles/5188179.html)

2.1引入

你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀,人狗作战,那至少需要2个角色,一个是人, 一个是狗,且人和狗都有不同的技能,比如人拿棍打狗,狗可以咬人,怎么描述这种不同的角色和他们的功能呢?

上面是两个不同的角色,但是同一个种角色,但有些属性是不同的呢?比如,大家都听说过cs吧,cs里有警察和恐怖份子,但因为都是人,所以我们在实现的时候,可以写一个角色叫 person(), 警察和恐怖份子都可以互相射击,但警察不可以杀人质,恐怖分子可以,这怎么实现呢?你想了说想,说,简单,只需要在杀人质的功能里加个判断,如果是警察,就不让杀不就ok了么。没错,这虽然解决了杀人质的问题,但其实你会发现,警察和恐怖分子的区别还有很多,同时又有很多共性,如果在每个区别处都单独做判断,那得累死。

你想了想说,那就直接写2个角色吧,反正这么多区别,但是也不能写两个角色呀,因为他们还有很多共性,写两个不同的角色,就代表相同的功能也要重写了,这要有多少代码重复啊?

然后。。。。。就不知道怎么办了?

我们可以通过这节课来讲的类来解决这一类问题。

2.2面向过程VS面向对象

1)编程范式:

编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式,对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式。两种最重要的编程范式分别是面向过程编程和面向对象编程。

面向过程编程(Procedural Programming):Procedural programming uses a list of instructions to tell the computer what to do step-by-step.

面向过程编程依赖过程,一个过程包含一组要被进行计算的步骤,面向过程又被称为top-down languages,就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。

举个典型的面向过程的例子,数据库备份,分三步,连接数据库,备份数据库,测试备份文件可用性。

def db_conn():

    print("connecting db...") 

def db_backup(dbname):

    print("导出数据库...",dbname)

    print("将备份文件打包,移至相应目录...") 

def db_backup_test():

    print("将备份文件导入测试库,看导入是否成功") 

def main():

    db_conn()

    db_backup('my_db')

db_backup_test()

 

这样做的问题也是显而易见的,就是如果我们要对程序进行修改,对我们修改的那部分有依赖的各个部分我们都也要跟着修改, 举个例子,如果程序开头我们设置了一个变量值 为1 , 但如果其它子过程依赖这个值 为1的变量才能正常运行,那如果我们改了这个变量,那这个子过程我们也要修改,假如又有一个其它子程序依赖这个子过程 , 那就会发生一连串的影响,随着程序越来越大, 这种编程方式的维护难度会越来越高。

所以我们一般认为, 如果我们只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,但如果我们要处理的任务是复杂的,且需要不断迭代和维护 的, 那还是用面向对象最方便了。

面向对象编程(OOP):

OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解我们的代码逻辑,从而使团队开发变得更从容。

面向对象的引入: 

世界万物,皆可分类

世界万物,皆为对象

只要是对象,就肯定属于某种品类

只要是对象,就肯定有属性

 

你是上帝

地球

山川,河流,森林,大海

 

飞禽走兽

臭鱼烂虾

 

飞禽---几百种鸟,

-布谷鸟-飞,吃虫子,下蛋,唱歌。

-乌鸦-飞,吃虫子,下蛋。。

引入模型 先把重复的建出来。

面向对象的几个核心特性如下:

Class 类

一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法。

Object 对象

一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同。

Encapsulation 封装

在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法。(只能访问到类,但是不能访问到类的内部。这就是封装。人,只能看到人,而不能看到器官)

Inheritance 继承

一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承。(上帝没有造具体的人,只造了模型。某某是继承他父亲那里的。)

Polymorphism 多态

多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。(老板说九点工作,而不用跑到具体的某个人面前,让他工作。老板只需要调用工作这个指令,就可以让大家都工作了)

编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来,再通过这个抽象的事物,与不同的具体事物进行对话。

对不同类的对象发出相同的消息将会有不同的行为。比如,我们的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。

多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定。

面向对象编程简介:

测试引入的例子:

 1 #Author:ajun
 2 
 3 class Dog:
 4 
 5     def __init__(self,name):
 6 
 7         self.name = name
 8 
 9  
10 
11     def bulk(self):
12 
13         print("%s: wang wang wang!" % self.name)
14 
15 d1 = Dog("张三")
16 
17 d2 = Dog("李四")
18 
19 d3 = Dog("王五")
20 
21  
22 
23 d1.bulk()
24 
25 d2.bulk()
26 
27 d3.bulk()
View Code

 

OOP不是一个很容易理解的编程方式,大家虽然都按老师讲的都知道OOP的三大特性是继承、封装、多态,并且大家也都知道了如何定义类、方法等面向对象的常用语法,但是一到真正写程序的时候,还是很多人喜欢用函数式编程来写代码,特别是初学者,很容易陷入一个窘境就是“我知道面向对象,我也会写类,但我依然没发现在使用了面向对象后,对我们的程序开发效率或其它方面带来什么好处,因为我使用函数编程就可以减少重复代码并做到程序可扩展了,为啥子还用面向对象?”。对于此,无论用什么形式来编程,我们都要明确记住以下原则:

1)写重复代码是非常不好的低级行为

2)你写的代码需要经常变更

 开发正规的程序跟那种写个运行一次就扔了的小脚本一个很大不同就是,你的代码总是需要不断的更改,不是修改bug就是添加新功能等,所以为了日后方便程序的修改及扩展,你写的代码一定要遵循易读、易改的原则(专业数据叫可读性好、易扩展)。

如果你把一段同样的代码复制、粘贴到了程序的多个地方以实现在程序的各个地方调用这个功能,那日后你再对这个功能进行修改时,就需要把程序里多个地方都改一遍,这种写程序的方式是有问题的,因为如果你不小心漏掉了一个地方没改,那可能会导致整个程序的运行都出问题。因此我们知道在开发中一定要努力避免写重复的代码,否则就相当于给自己再挖坑。

还好,函数的出现就能帮我们轻松的解决重复代码的问题,对于需要重复调用的功能,只需要把它写成一个函数,然后在程序的各个地方直接调用这个函数名就好了,并且当需要修改这个功能时,只需改函数代码,然后整个程序就都更新了。

其实OOP编程的主要作用也是使你的代码修改和扩展变的更容易,那么既然函数都能实现这个需求了,还要OOP干嘛?呵呵,说这话就像,古时候,人们打仗杀人都用刀,后来出来了枪,它的主要功能跟刀一样,也是杀人,然后小白就问,既然刀能杀人了,那还要枪干毛线,哈哈,显而易见,因为枪能更好更快更容易的杀人。函数编程与OOP的主要区别就是OOP可以使程序更加容易扩展和易更改。

函数编程与OOP编程的区别,可以参考,利用CS来介绍的:

http://www.cnblogs.com/alex3714/articles/5188179.html

使用面向对象比函数的优点:

1) 代码量少了

2) 代码逻辑清晰

类的语法

1 class Dog(object):
2 
3     print("hello,I am a dog!") 
4 
5 d = Dog() #实例化这个类,

#此时的d就是类Dog的实例化对象

#实例化,其实就是以Dog类为模版,在内存里开辟一块空间,存上数据,赋值成一个变量名

上面的代码其实有问题,想给狗起名字传不进去。

 1 class Dog(object): #Dog是类名
 2 
 3     n=123#类变量
 4 
 5     def __init__(self,name,dog_type):#__init__构造函数,实例化类时做一些初始化工作
 6 
 7         self.name = name  #实例变量(静态属性),作用域是实例本身
 8 
 9         self.type = dog_type 
10 
11     def sayhi(self): #类的方法(动态属性),就是类的功能。
12 
13         print("hello,I am a dog, my name is ",self.name) 
14 
15 d = Dog('LiChuang',"京巴")#d就是Dog的一个实例
16 
17 d.sayhi()

为什么有__init__? 为什么有self? 这个构造函数,主要实现初始化。

加入把下面两句注释掉:加入print语句

# d = Dog('LiChuang', "京巴")

# d.sayhi()

print(Dog)

没实例直接打印Dog输出如下

<class '__main__.Dog'>

这代表什么?代表 即使不实例化,这个Dog类本身也是已经存在内存里的对不对,是的,那实例化时,会产生什么呢?

 根据上图我们得知,其实self,就是实例本身!你实例化时python会自动把这个实例本身通过self参数传进去。那么为什么,sayhi(self),要写个self呢? 

class Dog(object):

    ...

    def sayhi(self):

 

        print("hello,I am a dog, my name is ",self.name)

self就是为了接收第一个变量值,就是我们传递的实例的名字。

在实例化的时候,函数都是在类中存的,节省空间。

2.3类变量和实例变量

实例的属性存储在实例的dict中。

类属性和方法存储在类的dict中。

查找属性的顺序:特性->实例的dict->类的dict->基类。

类变量:实际类似于类的全局变量

实例变量:实例类的局部变量

如果类变量名和实例变量名相同,先在实例变量中,找到。

类变量的用途:

节省开销(类变量和实例变量的区别)

2.4 构造函数和析构函数

         构造方法(构造函数):初始化实例

         析构方法(析构函数):实例销毁的时候自动执行的方法。在实例释放、销毁的时候自动执行的,通常用于一些收尾工作,如关闭一些数据库连接,打开的临时文件。

ef __del__(self):

print(“%s 彻底死了”)

 

析构函数一般都是在对象彻底销毁或者退出的时候执行的。

通过删除对象,就可以提前执行析构方法。

 2.5私有方法和私有属性

私有方法:__开头的方法,从外面无法访问

私有属性:__开头的变量,就是私有属性。只能在内部访问。外部无法访问。

2.6封装

封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

2.7继承

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”。

被继承的类称为“基类”、“父类”或“超类”。

继承的过程,就是从一般到特殊的过程。

要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

继承概念的实现方式主要有2类:实现继承、接口继承。

Ø         实现继承是指使用基类的属性和方法而无需额外编码的能力;

Ø         接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法);

在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。

抽象类仅定义将由子类创建的一般属性和方法。

OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。 

继承示例

定义一个people的类:

 1 class People(object): #新式类
 2 
 3     def __init__(self,name,age):
 4 
 5         self.name = name
 6 
 7         self.age = age
 8 
 9         self.friends = []
10 
11         print("--doens't run ")
12 
13     def eat(self):
14 
15         print("%s is eating..." % self.name)
16 
17     def talk(self):
18 
19         print("%s is talking..." % self.name)
20 
21     def sleep(self):
22 
23         print("%s is sleeping..." % self.name)
24 
25  
26 
27 #简单定义一个子类:并调用:
28 
29 class Man (People):
30 
31     pass #必须有
32 
33 ml = Man ("ajun",22)
34 
35 ml.eat()
36 
37  
38 
39 #重构:给父类添加新的方法。
40 
41 class Man(People):
42 
43     def piao(self):#没有的方法直接添加
44 
45         print("%s is piaoing ..... 20s....done." % self.name)
46 
47     def sleep(self):#如果父类已经有了的方法,先添加父类的方法,在添加新#方法
48 
49         People.sleep(self)
50 
51         print("man is sleeping ")
52 
53 #创建子类,woman:
54 
55 class Woman(People):
56 
57     def get_birth(self):
58 
59         print("%s is born a baby...." % self.name)
60 
61  
62 
63 w1 = Woman("ChenRonghua",26)
64 
65 w1.get_birth()
66 
67  

 

思考:

1)思考w1是否能够调用Man的piao()方法?为什么?

2)Man()和Woman()两个类是什么关系。他们两个和people()是什么关系?

3) 我想给Man()类添加一个参数,而Woman()类不增加参数,如果做?

 问题3的解决:(普通的继承)

    

 1 class Man(Relation,People):
 2 
 3     def __init__(self,name,age,money):#新添加一个初始化,父类的重构。
 4 
 5         People.__init__(self,name,age)
 6 
 7         super(Man,self).__init__(name,age) #新式类写法
 8 
 9         self.money  = money
10 
11         print("%s 一出生就有%s money" %(self.name,self.money))

  同样实例化的时候,就要多传递一个参数:

   m1 = Man("NiuHanYang",22,50)  

 多继承:一个子类可以继承多个父类。继承了一个类中有的属性和方法,另外一个类中相同的就不需要继承了。

 1 class People(object): #新式类
 2 
 3     def __init__(self,name,age):
 4 
 5         self.name = name
 6 
 7         self.age = age
 8 
 9         self.friends = []
10 
11     def eat(self):
12 
13         print("%s is eating..." % self.name)
14 
15     def talk(self):
16 
17         print("%s is talking..." % self.name)
18 
19     def sleep(self):
20 
21         print("%s is sleeping..." % self.name)
22 
23  
24 
25 class Relation(object):#新增一个Relation()类。
26 
27     def make_friends(self,obj): #w1
28 
29         print("%s is making friends with %s" % (self.name,obj.name))
30 
31 class Man(Relation,People):#Man()这个类新继承了Relation()类,
32 
33 #执行顺序默认从左到右
34 
35     def __init__(self,name,age,money):#在继承两个父类的时候,先执行的是自己#的构造方法
36 
37         People.__init__(self,name,age)
38 
39         super(Man,self).__init__(name,age) #新式类写法
40 
41         self.money  = money
42 
43         print("%s 一出生就有%s money" %(self.name,self.money))
44 
45     def piao(self):
46 
47         print("%s is piaoing ..... 20s....done." % self.name)
48 
49     def sleep(self):
50 
51         People.sleep(self)
52 
53         print("man is sleeping ")
54 
55 class Woman(People,Relation):
56 
57     def get_birth(self):
58 
59         print("%s is born a baby...." % self.name)
60 
61 #测试
62 
63 m1 = Man("NiuHanYang",22,50)
64 
65 w1 = Woman("ChenRonghua",26)
66 
67 w1.make_friends(m1)
68 
69  
多继承举例

2.8多态

多态性:就是一个接口多种实现。

多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。 

多态的作用是!实现接口的重用

封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。 

Pyhon 很多语法都是支持多态的,比如 len(),sorted(), 你给len传字符串就返回字符串的长度,传列表就返回列表长度。

举例:创建一个动物类,通过继承,生成一个狗类,一个猫类。然后让狗叫,让猫叫!

 1 #Author:ajun
 2 
 3 class Animal:
 4 
 5     def __init__(self, name):  # Constructor of the class
 6 
 7         self.name = name
 8 
 9 class Cat(Animal):
10 
11     def talk(self):
12 
13         print('Meow!')
14 
15 class Dog(Animal):
16 
17     def talk(self):
18 
19         print('Woof! Woof!')
20 
21 d = Dog("张三")
22 
23 d.talk()
24 
25 c = Cat("李四")
26 
27 c.talk()
28 
29  

是否可以通过一个接口,让狗和猫都叫!!!比如说animal.talk()

修改最后一部分实例化代码如下:

1 def Animal_talk(obj):
2     obj.talk()
3 d = Dog("张三")
4 c = Cat("李四")
5 
6 Animal_talk(d)
7 Animal_talk(c)

这样就实现了统一的接口,都在调用。但是呢,我们最好把统一接口放在父类里面。

 1 class Animal:
 2 
 3     def __init__(self, name):  # Constructor of the class
 4 
 5         self.name = name
 6 
 7     def Animal_talk(obj):
 8 
 9         obj.talk()
10 
11 class Cat(Animal):
12 
13     def talk(self):
14 
15         print('Meow!')
16 
17 class Dog(Animal):
18 
19     def talk(self):
20 
21         print('Woof! Woof!')
22 
23 d = Dog("张三")
24 
25 c = Cat("李四")
26 
27 Animal.Animal_talk(d)
28 
29 Animal.Animal_talk(c)
30 
31  
最终代码

Python中不像C++那样,通过特定的函数来实现多态,但是我们可以通过上面的方法来实现,类的多态。统一接口,多种实现。主要应用于接口的重用!

三、练习

3.1

 1 class Role:
 2     n = 123 #类变量
 3     n_list = [] #列表的类变量,公用的同一个内存变量
 4     name = "我是类name"
 5     def __init__(self, name, role, weapon, life_value=100, money=15000):
 6         #构造函数
 7         #在实例化时做一些类的初始化的工作
 8         self.name = name #r1.name=name实例变量(静态属性),作用域就是实例本身
 9         self.role = role
10         self.weapon = weapon
11         self.__life_value = life_value
12         self.money = money
13     def __del__(self):
14         pass #print("%s 彻底死了。。。。" %self.name)
15 
16     def show_status(self):
17         print("name:%s weapon:%s life_val:%s" %(self.name,
18      self.weapon, self.__life_value))
19     def __shot(self): # 类的方法,功能 (动态属性)
20         print("shooting...")
21 
22     def got_shot(self):
23         self.__life_value -=50
24         print("%s:ah...,I got shot..."% self.name)
25 
26     def buy_gun(self, gun_name):
27         print("%s just bought %s" % (self.name,gun_name) )
28 
29 r1 = Role('lisi', 'police',  'AK47') # Role(r1,'Alex', 'police',  'AK47')把一个类变成一个具体对象的过程叫 实例化(初始化一个类,造了一个对象)
30 r1.buy_gun("AK47")#Role.buy_gun(r1) 所以类中必须需要一个self方法
31 r1.got_shot()
32 r1.bullet_prove=True#在外面添加防弹衣的属性,完全可以,添加新的属性r1添加了新的属性,r2肯定没有
33 print(r1.bullet_prove)
34 print(r1.show_status())
35 print(r1.n,r1.name)
36 
37 r2 = Role('jack', 'terrorist', 'B22')  #生成一个角色
38 r2.got_shot()
39 print(r2.n,r2.name)
40 print(Role.n)
41 r1.name = "张三"#修改名字
42 r1.n_list.append("from r1")
43 r1.bullet_prove = True#在外面添加防弹衣的属性,完全可以,添加新的属性r1添加了新的属性,r2肯定没有
44 r1.n = "改类变量"  #实例中是否能够改类变量,它只是在r1的类变量中添加了一个新的变量n,这个n与类变量n,不一样。不影响r2中的类变量
45 print("r1:",r1.weapon,r1.n )
46 del r1.weapon #删除属性
47 print(r1.n,r1.name,r1.bullet_prove,r1.weapon)#删除了r1.weapon,不会打印出来,报错
48 r2 = Role('jack', 'terrorist', 'B22')  #生成一个角色
49 r2.name = "王五"
50 r2.n_list.append("from r2")
51 print("r2:",r2.name,r2.n,r2.n_list)
52 r2.got_shot() #Role.got_shot(r2)
53 Role.n = "ABC"
54 print(Role.n_list)
55 print(r1.n ,r2.n )
CS中警察和匪的例子

3.2学校类

模拟学校,老师,学生的关系类。

要求实现:

1)实例化一个学校

2)实例化两个老师

3)实例化两个学生

4)打印老师和学生的个人信息

5)学生注册

6)学校雇佣老师

7)新老师上课

8)所有学生交学费

目的:

1)练习多类继承

2)练习构造类的关系

3)练习类实例化,构造类的方法

4)复习前面所学知识

完成思路:

构造学生类,学校类,老师类,学校成员类。学生类和教师类继承学校成员类(为了以后代码的修改)。

通过题意发现:

学校类:包含学校名字,学校地址,学生,老师。具有雇佣老师,学生注册等方法。

教师类:包含教师姓名,年龄,性别,收入,课程。具有打印个人信息,上课等方法。

学生类:包含学生姓名,年龄,性别,学号,班级。具有交费,打印个人信息等方法。

学校成员类:包含学生和老师的公共属性:年龄,性别,姓名,公共方法:打印个人信息。

 1 #Author: ajun
 2 class School(object):
 3     def __init__(self,school_name,school_addr):
 4         self.school_name=school_name
 5         self.school_addr=school_addr
 6         self.students=[]
 7         self.teachers=[]
 8     def stu_enroll(self,stu_obj):
 9         print("%s在%s注册成功"%(stu_obj.name,self.school_name))
10         self.students.append(stu_obj)
11     def hire_teacher(self,teacher_obj):
12         print("%s录用了%s老师"%(self.school_name,teacher_obj.name))
13         self.teachers.append(teacher_obj)
14 class School_Member(object):
15     def __init__(self,name,age,sex):
16         self.name=name
17         self.age=age
18         self.sex=sex
19     def tell(self):
20         pass
21 class Student(School_Member):
22     def __init__(self,name,age,sex,stu_id,grade):
23         super(Student,self).__init__(name,age,sex) #注意这里的__init__()没有self
24         self.stu_id=stu_id
25         self.grade=grade
26     def tell(self):
27         print('''
28         ---info of student: %s---
29         Name  : %s
30         Age   : %s
31         Sex   : %s
32         Stu_id: %s
33         Grade : %s      
34         ''' %(self.name,self.name,self.age,self.sex,self.stu_id,self.grade))
35     def pay_tuition(self,amount):
36         print("%s成功交了学费%s"%(self.name,amount))
37 class Teacher(School_Member):
38     def __init__(self,name,age,sex,salary,course):
39         super(Teacher,self).__init__(name,age,sex)
40         self.salary=salary
41         self.course=course
42     def tell(self):
43         print('''
44                 ---info of teacher: %s---
45                 Name  : %s
46                 Age   : %s
47                 Sex   : %s
48                 Salary: %s
49                 Course : %s      
50                 ''' % (self.name, self.name, self.age, self.sex, self.salary, self.course))
51 
52     def teach(self):
53         print("%s is teaching course : %s"%(self.name,self.course))
54 school=School("四川信息职业技术学院","广元")
55 teacher_1=Teacher("ajun",27,"M",5000,"Python")
56 teacher_2=Teacher("胖子",29,"MG",8000,"Linux")
57 student_a=Student("张三",19,"G",163001,"16级")
58 student_b=Student("李四",17,"M",163002,"16级")
59 student_a.tell()
60 teacher_1.tell()
61 school.stu_enroll(student_a)
62 school.hire_teacher(teacher_1)
63 school.stu_enroll(student_b)
64 teacher_1.teach()
65 for stu in school.students:
66         stu.pay_tuition(5000)
参考答案

3.3 存放家具:

定义一个房子  定义一个床 定义一个茶几
#然后实现把床 茶几 放在房子里面
# 房子:面积 地址 放的东西
# 存放床
# 存放茶几
 1 class House(object):
 2     def __init__(self,name,area,addr):
 3         self.name=name
 4         self.area=area
 5         self.addr=addr
 6         self.jiaju=[]
 7     def cun_bed(self,bed_temp):
 8         self.area-=bed_temp.area
 9         self.jiaju.append(bed_temp.name)
10     def cun_chaji(self,chaji_temp):
11         self.area-=chaji_temp.area
12         self.jiaju.append(chaji_temp.name)
13     def __str__(self):
14         return "%s当前的面积为:%s,拥有的家居为:%s"%\
15                (self.name,self.area,self.jiaju)
16 class Bed(object):
17     def __init__(self,name,area,price):
18         self.name=name
19         self.area=area
20         self.price=price
21 class Chaji(object):
22     def __init__(self,name,area,price):
23         self.name=name
24         self.area=area
25         self.price=price
26 
27 daxiongjia=House("大熊家",200,"川信四栋4222")
28 daxiongbed=Bed("席梦思",4,500)
29 daxiongchaji=Chaji("全友家私",2,1000)
30 daxiongjia.cun_bed(daxiongbed)
31 daxiongjia.cun_chaji(daxiongchaji)
32 print(daxiongjia)
参考答案

3.4 英雄对战

 1 class Riven(object):
 2     def __init__(self,name,aggress,life,money):
 3         self.name=name
 4         self.aggress=aggress
 5         self.life=life
 6         self.money=money
 7     def attack(self,enemy):
 8         enemy.life=enemy.life-self.aggress
 9 class DeMa(object):
10     def __init__(self,name,aggress,life,money):
11         self.name=name
12         self.aggress=aggress
13         self.life=life
14         self.money=money
15     def attack(self,enemy):
16         enemy.life=enemy.life-self.aggress
17 class Dao(object):
18     def __init__(self,price,life,aggress):
19         self.price=price
20         self.life=life
21         self.aggress=aggress
22     def update(self,hero):
23         hero.money=hero.money-self.price
24         hero.aggress=hero.aggress+self.aggress
25         hero.life=hero.life+self.life
26     def fire(self,hero):
27         hero.life=hero.life-1000
28 R1=Riven("R1",54,414,6300)#实例化River
29 D1=DeMa("D1",56,455,3150)#实例化德玛西亚
30 duoduo=Dao(473,100,9)#实例化多兰之刃
31 R1.duoduo=duoduo#重新定义一个变量R1.duoduo 指向duoduo
32 duoduo.update(R1)#River装备多兰之刃
33 R1.attack(D1)#River装备后砍德玛西亚
34 print(D1.life)
35 R1.duoduo.fire(D1)#River用多兰之刃的技能砍德玛西亚
36 print(D1.life)
View Code

3.5老王开枪

  1 class Person(object):
  2     """描述人的类"""
  3     def __init__(self,name):
  4         super(Person, self).__init__()
  5         self.name=name
  6         self.gun=None#用来表示枪的引用
  7         self.hp=100
  8     def anzhuang_zidan(self,zi_dan_temp,dan_jia_temp):
  9         """把子弹 按照到弹夹中"""
 10         #弹夹保存子弹
 11         dan_jia_temp.baocun_zidan(zi_dan_temp)
 12     def anzhuang_danjia(self,gun_temp,dan_jia_temp):
 13         """把弹夹按照到枪中"""
 14         #枪.保存.弹夹
 15         gun_temp.baocun_danjia(dan_jia_temp)
 16     def naqiang(self,gun_temp):
 17         """老王拿起一把枪"""
 18         self.gun=gun_temp
 19     def __str__(self):
 20         if self.gun:
 21             return "%s的血量为%d,他有枪。%s"%(self.name,self.hp,self.gun)
 22         else:
 23             if self.hp>0:
 24                 return "%s的血量为%d,他没有枪" % (self.name, self.hp)
 25             else:
 26                 return "%s 已经挂了。。。"%self.name
 27     def kou_ban_ji(self,diren):
 28         """让枪发射子弹,去打敌人"""
 29         #枪.开火(敌人)
 30         self.gun.fire(diren)
 31     def diaoxue(self,sha_shang_li):
 32         """掉血"""
 33         self.hp-=sha_shang_li
 34 
 35 class Gun(object):
 36     """描述枪的类"""
 37     def __init__(self,name):
 38         super(Gun, self).__init__()
 39         self.name=name#存放枪的名字
 40         self.dan_jia=None#记录弹夹的引用
 41     def baocun_danjia(self,dan_jia_temp):
 42         self.dan_jia=dan_jia_temp
 43     def __str__(self):
 44         if self.dan_jia:
 45             return "枪的信息:%s,%s"%(self.name,self.dan_jia)
 46         else:
 47             return "枪的信息:%s,这个枪没有子弹"%self.name
 48     def fire(self,diren):
 49         """枪从弹夹中获取一个子弹,然后让子弹去射敌人"""
 50         #先从弹夹中取子弹
 51         zidan_temp=self.dan_jia.tanchu_zidan()
 52         #让这个子弹去伤害敌人
 53         if zidan_temp:
 54             zidan_temp.dazhong(diren)
 55         else:
 56             return "没有子弹了"
 57 class Danjia(object):
 58     """描述弹夹的类"""
 59     def __init__(self,max_num):
 60         super(Danjia, self).__init__()
 61         self.max_num=max_num#弹夹的存放子弹数
 62         self.zi_dan_list=[]#用来保存子弹的列表
 63     def baocun_zidan(self,zi_dan_temp):
 64         self.zi_dan_list.append(zi_dan_temp)
 65     def __str__(self):
 66         return "弹夹的信息%d/%d"%(len(self.zi_dan_list),self.max_num)
 67     def tanchu_zidan(self):
 68         """弹出最上面那颗子弹"""
 69         if self.zi_dan_list:
 70             return self.zi_dan_list.pop()
 71         else:
 72             return None
 73 class Zidan(object):
 74     """描述子弹的类"""
 75     def __init__(self,sha_shang_li):
 76         super(Zidan, self).__init__()
 77         self.sha_shang_li=sha_shang_li#子弹的杀伤力
 78     def dazhong(self,diren):
 79         """让敌人掉血"""
 80         diren.diaoxue(self.sha_shang_li)
 81 
 82 #1.创建一个老王对象
 83 laowang=Person("老王")
 84 #2.创建一个抢对象
 85 ak47=Gun("ak47")
 86 #3.创建一个弹夹对象
 87 dan_jia=Danjia(30)
 88 #4.创建一个子弹对象
 89 for i in range(20):#安装20发子弹
 90     zi_dan=Zidan(10)
 91 #6.老王把子弹装弹夹
 92 #老王安装子弹到弹夹(子弹,弹夹)
 93     laowang.anzhuang_zidan(zi_dan,dan_jia)
 94 #7.老王把弹夹装枪里
 95 #老王.按照弹夹到抢中(枪,弹夹)
 96 laowang.anzhuang_danjia(ak47,dan_jia)
 97 #测试弹夹的信息
 98 print(dan_jia)
 99 #测试枪的信息
100 print(ak47)
101 #7.老王拿枪
102 #老王.拿枪(枪)
103 laowang.naqiang(ak47)
104 #测试老王
105 print(laowang)
106 # 5.创建敌人
107 gebi_laosong=Person("隔壁老宋")
108 print(gebi_laosong)
109 #8.老王开枪
110 #老王.扣扳机(隔壁老宋)
111 for i in range(10):
112     laowang.kou_ban_ji(gebi_laosong)
113     print(gebi_laosong)
114     print(laowang)
View Code

3.6烤地瓜

 1 #Author:ajun
 2 class DiGua(object):
 3     """定义了一个地瓜类"""
 4     def __init__(self):#构造函数
 5         self.cookedString="生的"#烤的状态
 6         self.cookedLevel=0#烤的时间
 7         self.condiments=[]#烤的酌料
 8     def __str__(self): #析构函数
 9         return "地瓜 状态:%s(%d),添加的作料有:\
10         %s"%(self.cookedString, self.cookedLevel,\
11              str(self.condiments))
12     def cook(self,cooked_time):
13          #因为这个方法被调用了多次,为了能够在一次调用这个方法的时候 能够 获取到上一次调用这个方法时的cooked_time
14         #所以 需要在此,把cooked_time保存到这个对象的属性中,因为属性不会随着方法的调用而结束(一个方法被调用的时候
15         #是可以用局部变量来保存数据的,但是当这个方法定义结束之后这个方法中的所有数据就没有了)
16         self.cookedLevel += cooked_time
17         if self.cookedLevel >=0 and self.cookedLevel<3:
18             self.cookedString = "生的"
19         elif self.cookedLevel >=3 and self.cookedLevel<5:
20             self.cookedString = "半生不熟"
21         elif self.cookedLevel >=5 and self.cookedLevel<8:
22             self.cookedString = "熟了"
23         elif self.cookedLevel>8:
24             self.cookedString = "烤糊了"
25     def addCondiments(self, item):
26         #因为item这个变量指向了一个 作料,所以 接下来需要将item放到append里面
27         self.condiments.append(item)
28 #创建一个地瓜对象
29 di_gua=DiGua()#类的实例化
30 print(di_gua)
31 #开始烤地瓜
32 di_gua.cook(2)
33 di_gua.addCondiments("盐巴")
34 print(di_gua)
35 di_gua.cook(2)
36 di_gua.addCondiments("")
37 print(di_gua)
38 di_gua.cook(2)
39 di_gua.addCondiments("")
40 print(di_gua)
41 di_gua.cook(5)
42 di_gua.addCondiments("小米椒")
43 print(di_gua)
View Code

 

 1 class Hero(object):
 2     def __init__(self,name,aggress,hp,money):
 3         self.name=name
 4         self.aggress=aggress
 5         self.hp=hp
 6         self.money=money
 7     def attarck(self,enemy):
 8         enemy.hp=enemy.hp-self.aggress
 9 class Zhuangbei():
10     def __init__(self,name,aggress,hp,price):
11         self.name=name
12         self.aggress=aggress
13         self.hp=hp
14         self.price=price
15     def update(self,hero):
16         hero.hp += self.hp #更新英雄的血
17         hero.aggress +=self.aggress #更新英雄的攻击力
18         hero.money -= self.price
19     def fire(self,enemy):
20         enemy.hp -= 100
21 ruiwen=Hero("瑞文",54,414,6300)
22 dema=Hero("德玛西亚",56,455,3150)
23 duo=Zhuangbei("多兰之刃",9,100,475)
24 duo.update(ruiwen)#把装备 装备给瑞文
25 print(ruiwen.hp,ruiwen.aggress,ruiwen.money)
26 ruiwen.attarck(dema)
27 print(dema.hp)
28 #给ruiwen实例,增加一个变量duo,变量内容为实例duo的内存地址
29 ruiwen.duo=duo
30 ruiwen.duo.fire(dema)
31 print(dema.hp)
参考代码

 

四、作业

选课系统:

角色:学校、学员、课程、讲师

要求:

1. 创建北京、上海 2 所学校

2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开

3. 课程包含,周期,价格,通过学校创建课程

4. 通过学校创建班级, 班级关联课程、讲师

5. 创建学员时,选择学校,关联班级

5. 创建讲师角色时要关联学校,

6. 提供两个角色接口

      6.1 学员视图, 可以注册, 交学费, 选择班级,

      6.2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩

      6.3 管理视图,创建讲师, 创建班级,创建课程

7. 上面的操作产生的数据都通过pickle序列化保存到文件里

转载于:https://www.cnblogs.com/cx-ajun/p/7156946.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值