面向对象初识一
初识面向对象
1、面向对象和面向过程
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
面向过程特点:
优点:把复杂的问题流程化,简单化,比较容易想,可扩展性弱,处理单一关系代码量小
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象特点:
优点:可扩展性强(可增加新的方法)
缺点:可控性差(无法预测结果)
处理复杂的关系,代码多,面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
初识类和对象:
类:具有相同特征的一类事物(人、狗、老虎)
对象/实例:具体的某一个事物(隔壁阿花、楼下旺财)
实例化:类——>对象的过程
在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象是则是这一类事物中具体的一个。
类:
def functionName(args): '函数文档字符串' 函数体
''' class 类名: '类的文档字符串' 类体 ''' #我们创建一个类 class Data: pass
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def walk(self): #人都可以走路,也就是有一个走路方法,也叫动态属性 print("person is walking...")
类有两种作用:属性引用和实例化
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def walk(self): #人都可以走路,也就是有一个走路方法 print("person is walking...") print(Person.role) #查看人的role属性 print(Person.walk) #引用人的走路方法,注意,这里不是在调用
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def __init__(self,name): self.name = name # 每一个角色都有自己的昵称; def walk(self): #人都可以走路,也就是有一个走路方法 print("person is walking...") print(Person.role) #查看人的role属性 print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
实例化的过程就是类——>对象的过程
语法:对象名 = 类名(参数)
查看属性&调用方法
print(alex.name) #查看属性直接 对象名.属性名 print(Alex.attack()) #调用方法,对象名.方法名()
注 :self:在实例化时自动将对象/实例本身传给__init__的第一个参数
对象:
class Person: # 类名 Person role = '人' # 类的静态变量 是所有的对象共享的一个属性 def __init__(self,name,sex,aggr,hp): #方法 动态属性 内置的双下方法 self.name = name # 对象属性 实例属性 self.sex = sex self.aggr = aggr self.hp = hp def attack(self,dog): # 自定义方法 dog.hp -= self.aggr print('%s打了%s'%(self.name,dog.name)) # dog.hp -= self.aggr class Dog: def __init__(self,name,kind,aggr,hp): self.name = name # 对象属性 self.kind = kind self.aggr = aggr self.hp = hp def bite(self,person): person.hp -= self.aggr print('%s咬了%s'%(self.name,person.name)) # person.hp -= self.aggr hei = Dog('小黑','teddy',260,10000) # 实例化: 先创造对象 再初始化 alex = Person('alex','female',1,250) # 实例化 egon = Person('egon','male',2,500) # 实例化 alex.attack(hei) # Person.attack(alex,hei) egon.attack(hei) # Person.attack(alex,hei) print(hei.hp) hei.bite(alex) print(alex.hp)
对象是关于类而实际存在的一个例子,即实例,
对象只有一种作用:属性引用
当然了,你也可以引用一个方法,因为方法也是一个属性,只不过是一个类似函数的属性,我们也管它叫动态属性。
引用动态属性并不是执行这个方法,要想调用方法和调用函数是一样的,都需要在后面加上括号,如Alex.attack
class 类名: def __init__(self,参数1,参数2): self.对象的属性1 = 参数1 self.对象的属性2 = 参数2 def 方法名(self):pass def 方法名2(self):pass 对象名 = 类名(1,2) #对象就是实例,代表一个具体的东西 #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法 #括号里传参数,参数不需要传self,其他与init中的形参一一对应 #结果返回一个对象 对象名.对象的属性1 #查看对象的属性,直接用 对象名.属性名 即可 对象名.方法名() #调用类中的方法,直接用 对象名.方法名() 即可
2 、类命名空间与对象、实例的命名空间
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性
而类有两种属性:静态属性和动态属性
- 静态属性就是直接在类中定义的变量
- 动态属性就是定义在类中的方法
其中类的静态属性是共享给所有对象的
>>>id(egg.role) 4341594072 >>>id(Person.role) 4341594072
而类的动态属性是绑定到所有对象的
创建一个对象就会创建一个对象的名称空间,存放对象的名字,称为对象的属性
在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类(不会去全局变量中找)-..最后都找不到就抛出异常
3、面向对象的组合用法
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。
这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用
from math import pi class Circle: ''' 定义了一个圆形类; 提供计算面积(area)和周长(perimeter)的方法 ''' def __init__(self,radius): self.radius = radius def area(self): return pi * self.radius * self.radius def perimeter(self): return 2 * pi *self.radius circle = Circle(10) #实例化一个圆 area1 = circle.area() #计算圆面积 per1 = circle.perimeter() #计算圆周长 print(area1,per1) #打印圆面积和周长
from math import pi class Ring: ''' 定义了一个圆环类 提供圆环的面积和周长的方法 ''' def __init__(self,radius_outside,radius_inside): self.outsid_circle = Circle(radius_outside) self.inside_circle = Circle(radius_inside) def area(self): return self.outsid_circle.area() - self.inside_circle.area() def perimeter(self): return self.outsid_circle.perimeter() + self.inside_circle.perimeter() ring = Ring(10,5) #实例化一个环形 print(ring.perimeter()) #计算环形的周长 print(ring.area()) #计算环形的面积
用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程
class BirthDate: def __init__(self,year,month,day): self.year=year self.month=month self.day=day class Couse: def __init__(self,name,price,period): self.name=name self.price=price self.period=period class Teacher: def __init__(self,name,gender,birth,course): self.name=name self.gender=gender self.birth=birth self.course=course def teach(self): print('teaching') p1=Teacher('egon','male', BirthDate('1995','1','27'), Couse('python','28000','4 months') ) print(p1.birth.year,p1.birth.month,p1.birth.day) print(p1.course.name,p1.course.price,p1.course.period) ''' 运行结果: 27 python 28000 4 months '''
人狗大战升级版:
class Weapon: def __init__(self,name,price,aggr,protect): self.name = name self.price = price self.aggr = aggr self.protect = protect def kill(self,dog): # 技能 print('使用%s的必杀技,打中%s'%(self.name,dog.name)) dog.hp -= self.aggr print('%s的生命值减少%s,剩余%s'%(dog.name,self.aggr,dog.hp)) class Person: # 类名 Person role = '人' # 类的静态变量 是所有的对象共享的一个属性 def __init__(self,name,sex,aggr,hp): #方法 动态属性 内置的双下方法 self.name = name # 对象属性 实例属性 self.sex = sex self.aggr = aggr self.hp = hp def attack(self,dog): # 自定义方法 print('%s打了%s'%(self.name,dog.name)) dog.hp -= self.aggr class Dog: def __init__(self,name,kind,aggr,hp): self.name = name # 对象属性 self.kind = kind self.aggr = aggr self.hp = hp def bite(self,person): print('%s咬了%s'%(self.name,person.name)) person.hp -= self.aggr weapon = Weapon('屠龙宝刀',20000,999,0) alex = Person('alex','female',1,250) hei = Dog('小黑','teddy',260,10000) alex.attack(hei) print(hei.hp) hei.bite(alex) print(alex.hp) ret = input('输入1可以充值复活 :') if ret == '1': money = int(input('10000元复活一次,你要充值多少钱:')) if money>10000: alex.hp = 260 alex.money = money - 10000 print('复活成功,当前血量%s,当前账户余额%s'%(alex.hp,alex.money)) ret = input('输入1购买武器') if ret == '1': if alex.money >= 20000: alex.money -= weapon.price alex.weap = weapon print('购买成功,当前余额%s,当前武器%s'%(alex.money,alex.weap.name)) alex.weap.kill(hei) # alex使用武器打小黑 hei.bite(alex) # 小黑怒不可遏咬alex print(alex.hp) # 最终查看alex的血量
练习:
用面向对象的思想完成下列练习:
一、求圆形、正方形、长方形的周长和面积
# 计算圆面积和周长 from math import pi class Circle: def __init__(self,R): self.R = R def area(self): print(pi*(self.R**2)) def perimeter(self): print(2*self.R*pi) c = Circle(4) c.area() c.perimeter() # 计算正方形面积和周长 class Square: def __init__(self,s): self.s = s def area(self): return self.s**2 def perimeter(self): return self.s*4 a = Square(5) print(a.area()) print(a.perimeter()) # 计算长方形面积和周长 class Retangle: def __init__(self,a,b): self.a = a self.b = b def area(self): return self.a*self.b def perimeter(self): return 2*(self.a + self.b) n = Retangle(3,4) print(n.area()) print(n.perimeter())
二、人狗大战练习
# 人狗大战 class Person: def __init__(self,name,sex,aggr,hp): self.name = name self.sex = sex self.aggr = aggr self.hp = hp def attack(self,dog): print('%s打了%s,掉了%s的血'%(self.name,dog.name,self.aggr)) dog.hp -= self.aggr class Dog: def __init__(self,name,kind,aggr,hp): self.name = name self.kind = kind self.aggr = aggr self.hp = hp def bite(self,person): print('%s咬了%s,掉了%s的血'%(self.name,person.name,self.aggr)) person.hp -= self.aggr alex = Person('alex','female',200,500) hei = Dog('hei','teddy',150,300) hei.bite(alex) alex.attack(hei) print(hei.hp) print(alex.hp) >>> hei咬了alex,掉了150的血 alex打了hei,掉了200的血 100 350
三、打印如下类型语句
# 小明,男,10岁,上山去砍柴
# 小明,男,10岁,开车去东北
# 小明,男,10岁,最爱大保健
# 老张,男,90岁,上山去砍柴
# 老张,男,90岁,开车去东北
# 老张,男,90岁,最爱大保健
# 老王,男,70岁,上山去砍柴
# 老王,男,70岁,开车去东北
# 老王,男,70岁,最爱大保健
class Person: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age def drive(self): print('%s,%s,%s岁,开车去东北'%(self.name,self.sex,self.age)) def climb(self): print('%s,%s,%s岁,上山去砍柴'%(self.name,self.sex,self.age)) def hobby(self): print('%s,%s,%s岁,最爱大保健'%(self.name,self.sex,self.age)) ming = Person('小明', '男',10) ming.drive() ming.climb() ming.hobby() zhang = Person('老张','男',90) zhang.drive() zhang.climb() zhang.hobby() wang = Person('老王','男',70) wang.drive() wang.climb() wang.hobby()