初识面向对象二(组合,继承,抽象类,接口类)
面向对象
类:class Circle 规范了属性的个数和名字
对象:给类中约束的属性赋予了具体的值
实例化:创建对象的过程 对象=类名()
1.创建一个对象,产生一个类对象指针
2.调用__init__方法,将创造的对象传给self,执行__init__方法
3.将self自动的返回给调用者
在类中可以定义的:
静态属性 变量
动态属性 方法 ,函数 必须写的参数--self
类中写的所有静态变量和动态变量都是所有对象共享的
在self空间中或者在实例化过后的对象的空间中定义的变量都是属于某个对象的。
类名 :调用静态属性 实例化
对象名:方法 查看对象命名空间中的属性
描述一个圆形
属性 半径
方法 计算周长 计算面积
周长--pi*2*r
面积--pi*r**2
from math import pi
class Circle:
def __init__(self,r):
self.r=r
def area(self):
return pi*self.r**2
def perimeter(self):
return pi*2*self.r
r1=Circle(3)
print(r1.area())#半径为r1的圆的面积
print(r1.perimeter())半径为r1的圆的周长
静态属性和对象属性的区别是什么?
如果所有的对象的某一值都是相同的,就用静态属性
如果每一个对象的某个值有所不同,就是对象属性
圆的面积和周长
正方形的面积和周长
长方形的面积和周长
class Person:
def __init__(self,name,sex,hp,ad):
self.name=name
self.sex=sex
self.hp=hp
self.ad=ad
def attack(self,dog):
print('%s攻击了%s' % (self.name,dog.name))
dog.hp -= self.ad
if dog.hp>0:
print('%s掉了%s血,还剩%s滴血 ' % (dog.name,self.ad,dog.hp))
else:
print('%s掉了%s血,血量为零,gime over ,%s win' % (dog.name, self.ad, self.name))
class Dog:
def __init__(self,name,kind,hp,ad):
self.name=name
self.kind=kind
self.hp=hp
self.ad=ad
def bite(self,person):
print('%s咬了%s' % (self.name, person.name))
person.hp-=self.ad
if person.hp>0:
print('%s掉了%s血,还剩%s滴血 ' % (person.name,self.ad,person.hp))
else:
print('%s掉了%s血,血量为零,gime over ,%s win' % (person.name, self.ad, self.name))
songsong=Person('松松','不详',10,1)
taibai=Dog('太亮','不详',200,50)
songsong.attack(taibai)
taibai.bite(songsong)
装备
花钱-->装备-->攻击力上升
价格
加一些生命值,为任务添加攻击力
秘技
class Weapon:
def __init__(self,name,price,ad=0,hp=0):
self.name=name
self.price=price
self.hp=hp
self.ad=ad
self.ad_total=self.ad#此时没有添加人本身的攻击力
def kill(self,dog):
dog.hp-=self.ad_total
songsong=Person('松松','不详',10,1)
taibai=Dog('太亮','不详',200,50)
dagoubang=Weapon('打狗棒',998,180)
taibai.bite(songsong)
print(dagoubang.__dict__)#打印打狗棒的具体信息{'price': 998, 'hp': 0, 'ad_total': 180, 'name': '打狗棒', 'ad': 180}
songsong.weapon=dagoubang#给松松增加了一个.weapon属性,和name,ad,同等级,名字为dagoubang。dagoubang还在Weapon里面
songsong.weapon.kill(taibai)#-->组合
songsong.attack(taibai)#
print(taibai.hp)
升级版人狗大战
class Person:
def __init__(self,name,sex,hp,ad):
self.name=name
self.sex=sex
self.hp=hp
self.ad=ad
self.money=0
def attack(self,dog):
print('%s攻击了%s' % (self.name,dog.name))
dog.hp-=self.ad
if dog.hp>0:
print('%s掉了%s血,还剩%s滴血' % ( dog.name,self.ad,dog.hp))
else:
print('%s掉了%s血,血量为0,game over,%s win ' % (dog.name, self.ad, self.name))
def recharge(self,money):#充钱
self.money+=money
def buy_weapon(self,wq):
if self.money>=wq.price:
self.money-=wq.price
self.weap=wq#给松松的增了一个属性,武器wq
# self.ad+=wq.ad
self.weap.ad_total+=self.ad#需要理解
else:
print('余额不足,请及时充值')
class Dog:
def __init__(self,name,kind,hp,ad):
self.name=name
self.kind=kind
self.hp=hp
self.ad=ad
def bite(self,person):
print('%s咬了%s' % (self.name, person.name))
person.hp-=self.ad
if person.hp > 0:
print('%s掉了%s血,还剩%s滴血' % (person.name, self.ad, person.hp))
else:
print('%s掉了%s血,血量为0,game over,%s win ' % (person.name, self.ad, self.name))
class Weapon:
def __init__(self,name,price,ad=0,hp=0):#默认攻击和血量为0
self.name=name
self.price=price
self.ad=ad
self.hp=hp
self.ad_total = self.ad # 武器初始值为0
def kill(self,dog):
print('%s攻击了%s' % (self.name, dog.name))
dog.hp-=self.ad_total
if dog.hp > 0:
print('%s掉了%s血,还剩%s滴血' % (dog.name, self.ad, dog.hp))
else:
print('%s掉了%s血,血量为0,game over ' % (dog.name, self.ad))
songsong=Person('松松','男',10,1)
taibai=Dog('哮天犬','藏獒',200,50)
dagoubang=Weapon('打狗棒',998,200)
songsong.recharge(10000)
songsong.buy_weapon(dagoubang)
taibai.bite(songsong)
songsong.attack(taibai)
songsong.weap.kill(taibai)
组合:两个类的事
关系:一个类有另一个类 比如 人有武器
一个类的对象作为另一个类对象的属性
武器类的对象作为人类对象的一个属性
课程类对象作为学生类对象的一个属性
圆形类对象作为圆环对象的一个属性
组合
学生类 课程类 --学生和课程组合在一起
学生类:姓名,性别,手机号,课程
课程类: 名称 周期 价格
class Student:
def __init__(self,name,sex,phone,course):
self.name=name
self.sex=sex
self.phone=phone
self.course=course
class Course:
def __init__(self,name,price,period):
self.name=name
self.price=price
self.period=period
python = Course('python', 19800, 'six_month')#python在这里是个变量,方便以后的调用
java = Course('java', 16800, 'six_month')
c语言 = Course('c语言', 18800, 'six_month')
xiaoming1=Student('小明1','男',12345678910,python)#python必须是变量,不能执行不了后面的打印操作
xiaoming2=Student('小明2','男',12345678910,java)
xiaoming3=Student('小明3','男',12345678910,c语言)
print(xiaoming1.course.price)#python
print(xiaoming2.course.price)#java
print(xiaoming3.course.period)#c语言
print(xiaoming1.course.__dict__)#打印出python的内容{'period': 'six_month', 'price': 19800, 'name': 'python'}
圆环的面积
from math import pi
class Circle:
def __init__(self,r):
self.r=r
def area(self):
return pi*self.r**2
def perimeter(self):
return 2*pi*self.r# 一定要注意,别把*和.搞混了
class Ring:
def __init__(self,out_r,in_r):
self.out_circle=Circle(out_r)#将圆环的外环半径实例化成圆的半径。
self.in_circle=Circle(in_r)
def a(self):
return self.out_circle.area()-self.in_circle.area()
def p(self):
return self.out_circle.perimeter()+self.in_circle.perimeter()
# 将圆形类对象(周长)作为圆环类对象((外圆,内圆)周长)的的属性
r=Ring(10,5)
print(r.a())
print(r.p())
继承
三大特性:继承 封装 多态
继承
单继承--所有面向对象语言都支持
class 另外一个类名():pass
class 类名(另外一个类名):pass
print(类名.__bases__) #可以去查看父类 (<class '__main__.另外一个类名'>,)
多继承--python
class 另类1():pass
class 另类2():pass
class 类名(另类1,另类2):pass
print(类名.__bases__)#(<class '__main__.另类1'>, <class '__main__.另类2'>)
print(另类1.__bases__)#(<class 'object'>,) object类是所有类的基类
object类是所有类的基类
继承的作用
class Role:
def __init__(self,name,hp,ad):
print('in Role init')
self.name=name
self.hp=hp
self.ad=ad
def eat(self):
print('%s回了10滴血' % self.name)
self.hp+=10
class Person(Role):
def __init__(self,name,sex,hp,ad):
self.sex=sex
self.money=100
Role.__init__(self,name,hp,ad)#指名道姓# class Person:定义类时,不加父类也可以
# super().__init__(name,hp,ad)#super()代表父类
# super(Person.self).__init__(name,hp,ad)#super()代表父类?
def attack(self,dog):
dog.hp-=self.ad
def eat(self):
if self.money>=0:
self.money-=10
# super().eat()
Role.eat(self)
class Dog(Role):
def __init__(self,name,kind,hp,ad):
super().__init__(name,hp,ad)
self.kind=kind
def bite(self,person):
person.hp-=self.ad
继承--代码的重要性
alex=Person('alex',None,100,1)
print(alex.__dict__)#in Role init {'sex': None, 'money': 100, 'name': 'alex', 'ad': 1, 'hp': 100},调用的是class Role的__init__方法。
taibai=Person('taibai','teddy',100,1)
print(taibai.__dict__)
print(alex.name)#alex
alex.attack(taibai)
print(taibai.hp)#99
alex.eat()#调用的是父类的方法
taibai.eat()##调用的是父类的方法
继承的语法,在子类定义的时候,括号里是父类的名字。
对象在寻找名字的时候,先找自己对象空间里的,在找自己类的空间里的,再找父类空间里的
在自己的类中调用父类的同名方法,指名道姓(需要自己传self参数),super方法(不需要自己传self参数)
看结果:
class Foo:
def __init__(self):
self.func()
def func(self):
print('in foo')
class Son(Foo):
def func(self):
print('in son')
Son() #in son
组合 什么有什么的关系
一个类的对象作为另外一个类对象的属性
继承 什么是什么的关系 ---写代码用的***
节省两个类之间共有的方法或者代码
如果子类和父类一样,那么可以省略子类的,用父类的
如果子类特有的,用子类的,----派生
如果两个方法,子类父类都有,用子类的
如果两个方法,子类有,父类也有,想用父类的:指名道姓 或者super
抽象类和接口类 --了解 *
在python代码中 抽象类和接口类没有明显的区别
主要是维持了一种规范
一切皆对象
dic={'k','v'}
lst=[1,2,3]
len(lst)
print(dic.__len__(),len(dic))#2 2 len函数内部实际上执行了__len__()的方法
def len(lst):
return lst.__len__()
print(len(lst))#3
print(len(1))#数字1 没有__len__方法
抽象类:
在类的位置指定metaclass是ABCMeta
在指定的方法上面添加@abstractmethod装饰器
目的:规范所有继承这个类的子类 必须实现被@abstractmethod装饰器装饰的这个方法
特点:抽象类和接口类不能被实例化
from abc import ABCMeta,abstractmethod class Pay(metaclass=ABCMeta): @abstractmethod def pay(self,money):pass #树立了一个规范 class WechatPay(Pay): def pay(self,money): print('微信支付了%s元' % money ) class ApplepPay(Pay): def pay(self,money): print('使用苹果支付了%s元' % money) class AliPay(Pay): def pay(self,money): print('使用支付宝支付了%s元' % money) def payment(obj,money):obj.pay(money) wp=WechatPay() payment(wp,100) #编程的习惯 --归一化设计 wp.pay(100) ap=AliPay() payment(ap,100) ap.pay(100) app=ApplePay() payment(app,100)
规范
接口类
python天生支持多继承
java语言是不支持多继承的
from abc import ABCMeta,abstractmethod
class Walk_Animal(metaclass=ABCMeta):
@abstractmethod
def walk(self):pass
class Fly_Animal(metaclass=ABCMeta):
@abstractmethod
def fly(self):pass
class Swim_Animal(metaclass=ABCMeta):
@abstractmethod
def swim(self):pass
class Tiger(Walk_Animal,Swim_Animal):
def walk(self):
print('walk')
def swim(self):
print('swim')
class Parrot:
def walk(self):
print('walk')
def fly(self):
print('fly')
class Swan:
def walk(self):
print('walk')
def fly(self):
print('fly')
def swim(self):
print('swim')
砖石继承--新式类和经典类--python 程序员需要了解的