什么是面向对象?面向对象程序设计是把计算机程序的执行看做一组对象的集合,每个对象之间进行消息的传送处理。有一个显著的优点就是,对某个对象进行修改,整个程序不会受到影响,自定义数据类型就是面向对象中的类的概念,而我们需要把他们的接口处理好就很好办了。
注意:
需要有意义的面向对象的代码,不是有了类就是面向对象
核心:类 对象(类的实例化)
现在我们来看一个比较简单的例子:
class Student():
name = '' #变量:数据成员
age = 0
def print_file(self): #方法:设计层面 函数:程序运形,过程式一种称谓
print('name:' + self.name)
print('age:' + str(self.age))
student = Student()
student.print_file()
类与对象的概念
对象:对象是现实世界或者思维世界中的实体进行抽象后在计算机中的反映,它将数据以及这些数据上的操作封装在一起
类:一类事物的统称,对象是类具体化的产物,也就是不同的实例化对象有什么不同特点:比如年龄,姓名
我们通过下面的代码来对类与对象进行理解:
class Student():
name = ''
age = 0
def do_homework(self):
print('homework')
student1 = Student()
student1.do_homework()
student2 = Student()
student2.do_homework()
student3 = Student()
student3.do_homework()
print(id(student1))
print(id(student2))
print(id(student3))
执行结果:
homework
homework
homework
140105929839560
140105929839840
140105929857680
可以看到student1,student2,student3都是Student的实例化产物,但是他们又都存储在不同的存储空间。
class Student():
name = ''
age = 0
def __init__(self,name,age):
#构造函数
self.name = name
self.age = age
print('student')
# return 'student'
def do_homework(self):
print('homework')
student1 = Student('老李',38)
print(student1.name)
print(student1.age)
上面的部分代码还需要再解释一下:
object: 注意类名后面括号里有个参数object,他代表所有类的基类,也叫作超类。 这就有了一个新式类和旧式类的概念:
当用到多继承的时候,如果子类中没有想用的方法名或属性名,他会自动回到上面去找。那么按广度优先遍历的方法去寻找就是新式类(object);深度优先(括号里啥也没有)。
init():构造函数,实例化的时候若不显示的定义,那么默认调用一个无参的,是初始化的意思。
再来说一下str方法:
class Dog():
def __ init__(self, name):
self.name = name
def __ str__(self):
return '这是 %s' %(self.name) #必须返回一个字符串
Gofei = Dog('旺财')
print(Gofei)
现在我们来做两个小小的练习吧:
练习1:
老李今年50岁,身高1.75,每天早上要跑步,会去吃东西
老吴今年36岁,身高1.85,老吴不跑步,老吴喜欢吃东西
class Person():
def __init__(self,name,age,height):
self.name=name
self.age=age
self.height=height
def func(self):
if self.name == '老李':
print('每天早上要跑步,会去吃东西')
elif self.name == '老吴':
print('老吴不跑步,老吴喜欢吃东西')
def __str__(self):
return '%s今年%d岁,身高%.2f' %(self.name,self.age,self.height)
li = Person('老李',35,1.65)
练习2:
一只黄色的狗叫旺财
看见生人汪汪叫
看见家人摇尾巴
class Dog():
def __init__(self,color,name):
self.name=name
self.color=color
def shout(self):
print('看见生人摇尾巴')
def shake(self):
print('看见家人摇尾巴')
def __str__(self):
return '一只%s的狗叫%s' %(self.color,self.name)
dog = Dog('黄色','旺财')
print(dog)
猫爱吃鱼,猫要喝水
class Cat():
def eat(self,name):
self.name = name
print('%s爱吃鱼' %self.name)
def drink(self):
print('猫要喝水')
tom = Cat()
tom.name = 'Tom'
print(tom)
self:哪一个对象调用的方法,self就是哪一个对象的引用
在类封装的方法内部,self就表示当前调用方法的对象自己
class Cat():
def __ init__(self,new_name):
print('这是一个初始化方法')
self.name = new_name
def eat(self):
print('%s爱吃鱼' %self.name)
cat = Cat('tom')
print(cat.name)
hello_kitty = Cat('hk')
print(hello_kitty.name)
hello_kitty.eat()
self.name(属性名) = 形参 接收外部传递的参数
练习三:
用类实现栈的工作原理:
class Stack():
def __init__(self):
self.stack = []
def push(self,value):
self.stack.append(value)
return True
def pop(self):
#先判断栈是否为空
if self.stack:
item = self.stack.pop()
return item
else:
return False
def top(self):
if self.stack:
return self.stack[-1]
else:
return False
def length(self):
return len(self.stack)
def view(self):
return ','.join(self.stack)
s = Stack()
s.push('1')
s.push('2')
item = s.pop()
print(s.view())
封装
1.将属性和方法封装到一个抽象的类中
2.外界使用类创建对象,对象调用方法
3.对象方法的细节都被封装在类的内部
" " "
需求
1.李雷体重75.0公斤
2.李雷每次跑步会减肥0.5公斤
3.李雷每次吃东西体重会增加1公斤
需求
1.李雷和韩梅梅都爱跑步
2.韩梅梅体重45.0公斤
3.李雷体重75.0公斤
4.每次跑步都会减少0.5公斤
5.每次吃东西都会增加1公斤
" " "
class Person():
def __init__(self,name,weight):
self.name = name
self.weight = weight
def __str__(self):
return '我的名字叫 %s 体重是 %.2f' %(self.name,self.weight)
def run(self):
print('%s爱跑步' %self.name)
self.weight -= 0.5
def eat(self):
print('%s吃东西' %self.name)
self.weight += 1
Lilei = Person('李雷',75.0)
Lilei.run()
print(Lilei)
Lilei.eat()
print(Lilei)
练习:
一.
"""
需求:
1.房子有户型,总面积和家具名称列表
新房子没有任何的家具
2.家具有名字和占地面积,其中
床:占4平米
衣柜:占2平米
餐桌:占1.5平米
3.将以上三件家具添加到房子中
4.打印房子时,要求输出:户型,总面积,剩余面积,家具名称列表
"""
class Furniture():
def __init__(self,name,area):
self.name = name
self.area = area
def __str__(self):
return '[%s]占地: %.2f' %(self.name,self.area)
# bed = Furniture('bed',4)
# print(bed)
class House():
def __init__(self,house_type,area):
self.house_type = house_type
self.area = area
#剩余面积
self.free_area = area
self.item_list = []
def __str__(self):
return ('户型: %s\n总面积: %.2f[剩余面积: %.2f]\n家具:%s'
%(self.house_type,self.area,self.free_area,self.item_list))
def add_item(self,item):
#1.判断家具的面积
if item.area > self.free_area:
print('%s 的面积太大,无法添加' %item.name)
#2.添加家具
self.item_list.append(item.name)
#3.计算剩余面积
self.free_area -= item.area
bed = Furniture('bed',4)
print(bed)
yigui = Furniture('yigui',200)
print(yigui)
table = Furniture('table',1.5)
print(table)
my_house = House('独门独栋',400)
my_house.add_item(bed)
my_house.add_item(yigui)
my_house.add_item(table)
print(my_house)
二.
"""
1.士兵瑞恩有一把AK47
2.士兵可以开火(士兵开火扣动的是扳机)
3.枪 能够 发射子弹(把子弹发射出去)
4.枪 能够 装填子弹 --增加子弹的数量
Soldier Gun
------------- -----------------
name model
gun bullet_count #子弹数量足够多才能完
成射击的动作
------------- -----------------
__init__(self): __init__(self):
fire(self): add_bullet(self,count):#装填子弹的
方法
shoot(self):
"""
class Gun():
def __init__(self,model):
self.model = model
self.bullet_count = 0
def add_bullet(self,count):
self.bullet_count += count
def shoot(self):
if self.bullet_count <= 0:
print('%s没有子弹了...' %self.model)
self.bullet_count -= 1
print('%s ... %s' %(self.model,self.bullet_count))
class Soldier():
def __init__(self,name):
self.name = name
self.gun = None
def fire(self):
if self.gun == None:
print('%s还没有枪...' %self.name)
self.gun.add_bullet(5)
self.gun.shoot()
ak47 = Gun('ak47')
ak47.add_bullet(20)
ak47.shoot()
ryan = Soldier('Ryan')
ryan.gun = ak47
ryan.fire()
继承
1.封装:根据职责将属性和方法封装到一个抽象的类中
2.继承:实现代码的重用,相同的代码不需要重复的写
class Animal():
def eat(self):
print('吃')
def drink(self):
print('喝')
def run(self):
print('跑')
def sleep(self):
print('睡')
class Cat(Animal):
# def eat(self):
# print('吃')
#
# def drink(self):
# print('喝')
#
# def run(self):
# print('跑')
#
# def sleep(self):
# print('睡')
def shout(self):
print('喵')
fentiao = Cat()
fentiao.eat()
fentiao.drink()
fentiao.run()
fentiao.sleep()
fentiao.shout()
子类继承自父类,可以直接享受父类中已经封装好的方法。子类中应该根据职责,封装子类特有的属性和方法
class Animal():
def eat(self):
print('吃')
def drink(self):
print('喝')
def run(self):
print('跑')
def sleep(self):
print('睡')
class Cat(Animal):
def shout(self):
print('喵')
class Hellokitty(Cat):
def speak(self):
print('我会说日语')
class Dog(Animal):
def bark(self):
print('汪')
kt = Hellokitty()
kt.speak()
kt.shout()
kt.eat()
kt.sleep()
子类可以继承父类的所有属性和方法。继承具有传递性,子类拥有父类的父类的属性和方法
"""
当父类方法不能满足子类的需求时?可以对方法进行重写
1.覆盖父类的方法
2.对父类的方法进行扩展
"""
class Animal():
def eat(self):
print('吃')
def drink(self):
print('喝')
def run(self):
print('跑')
def sleep(self):
print('睡')
class Cat(Animal):
def shout(self):
print('喵')
class Hellokitty(Cat):
def speak(self):
print('我可以说日语')
def shout(self):
print('@#$%%@$#@#@$')
kt = Hellokitty()
kt.shout()
如果子类中,重写了父类的方法,在运形时,只会调用在子类中重写的方法
class A():
def test(self):
print('A --- test方法')
def demo(self):
print('A --- demo方法')
class B():
def test(self):
print('B --- test 方法')
def demo(self):
print('B --- demo方法')
class C(A,B):
pass
c = C()
c.test()
c.demo()
运行结果:
A — test方法
A — demo方法
新式类和旧式类
新式类和旧式(经典)类: object是Python为所有对象提供的基类,提供有一些内置的属性和方法 ,可以使用dir函数查看
新式类:以object为基类的类,推荐使用 经典类:不以object为基类的类,不推荐使用
在python3.X中定义的类时,如果没有指定父类,会默认使用object作>为基类–python3.x中定义的类都是新式类
在python2.x中定义类时,如果没有指定父类,则不会以object作为基>类为保证编写的代码能够同时在python2.x和python3.x运行 今后在定义类时,如果没有父类,建议统一继承自object
多态性
子类和父类存在相同方法时,子类会覆盖父类方法,运形时总会调用子类方法–> 多态
class Animal(object):
def run(self):
print('running...')
def cry(self):
print('crying...')
class Dog(Animal):
def run(self):
print('dog running...')
def eat(self):
print('dog eating...')
class Cat(Animal):
def run(self):
print('cat running...')
cat = Cat()
cat.run()
dog = Dog()
dog.run()
文章最后,让我们用上文所学的编写一个较复杂的代码----图书管理系统。
"""
图书管理系统
1.查询图书
2.增加图书
3.借阅图书
4.归还图书
5.退出系统
"""
# 书:书名,作者,状态,位置
# 管理系统:
class Book(object):
def __init__(self, name, author, status, bookindex):
self.name = name
self.author = author
self.status = status
self.bookindex = bookindex
def __str__(self):
if self.status == 1:
stats = '未借出'
elif self.status == 0:
stats = '已借出'
else:
stats = '状态异常'
return '书名: 《%s》 作者: %s 状态: <%s> 位置: %s' \
% (self.name, self.author, stats, self.bookindex)
class BookManage(object):
books = []
def start(self):
self.books.append(Book('python', 'guido', 1, 'ISO9001'))
self.books.append(Book('c', '谭浩强', 1, 'NFS8102'))
self.books.append(Book('java', 'westos', 1, 'PKA7844'))
# 0:借出 1:存在
# python 1
# c 1
# java 1
def Menu(self):
self.start()
while True:
print("""
图书管理系统
1.查询图书
2.增加图书
3.借阅图书
4.归还图书
5.退出系统
""")
choice = input('请选择:')
if choice == '1':
self.showAllBook()
elif choice == '2':
self.addBook()
elif choice == '3':
self.borrowBook()
elif choice == '4':
self.returnBook()
elif choice == '5':
print('欢迎下次使用...')
exit()
else:
print('请输入正确选择')
continue
def showAllBook(self):
for book in self.books:
print(book)
def addBook(self):
name = input('图书名称:')
self.books.append(Book(name, input('作者:'), 1, input('存储位置:')))
print('图书《%s》增加成功' % name)
def checkBook(self, name):
for book in self.books:
if book.name == name:
return book
else:
return None
def borrowBook(self):
name = input('借阅图书名称: ')
ret = self.checkBook(name)
print(ret)
if ret != None:
if ret.status == 0:
print('书籍《%s》已经借出' % name)
else:
ret.status = 0
print('书籍《%s》借阅成功' % name)
else:
print('书籍《%s》不存在' % name)
def returnBook(self):
name = input('归还图书名称:')
ret = self.checkBook(name)
if ret != None:
if ret.status == 0:
ret.status = 1
print('书籍《%s》归还成功' % name)
print(ret)
else:
print('书籍《%s》未借出' % name)
else:
print('书籍《%s》不存在' % name)
manager = BookManage()
manager.Menu()