概述
面向过程 面向对象(oop:object oriented programming)
面向过程:—侧重于怎么做?
1.把完成某一个需求的 所有步骤 从头到尾 逐步实现
2.根据开发要求,将某些功能独立的代码封装成一个又一个函数
3.最后完成的代码,就是顺序的调用不同的函数
特点:
1.注重步骤和过程,不注重职责分工
2.如果需求复杂,代码变得非常复杂
3.开发复杂的项目的时候,没有固定的套路,开发难度很大
面向对象:----侧重于谁来做?
相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
1.在完成某一个需求前,首先确定职责–要做的事(方法)
2.根据职责确定不同的对象,在对象内部封装不同的方法(多个)
3.最后完成代码,就是顺序的让不同的对象调用不同的方法
特点:
1.注重对象和职责,不同的对象承担不同的职责
2.更加适合对复杂的需求变化,是专门应对复杂项目的开发,提供固定的套路
3.需要在面向过程的基础上,再学习一些面向对象的语法
面向对象有两个核心的概念
类:是一类具有相同特征或行为的事物的一个统称
对象:由类创建出来的一个具体的存在
类和对象的关系:先有类再有对象
类是模板 对象是根据这个模板创建出来的
类只需要有一个 对象可以有多个
类:属性(这一类事务的共同信息) 和 方法(你能完成的动作)
1.类名:这类事物的名字(大驼峰命名法)
大驼峰命名法:
1.每个单词的首字母大写
2.单词与单词之间没有下划线
2.属性:这个类创建出来的对象有什么特征
3.方法:这个类创建出来的对象有什么行为
类名的确定
名词提炼法分析整个业务流程,出现的名词,通常就是找到的类
属性和方法的确定
对 对象的特征描述,通常可以定义成属性
对象具有的行为(动词),通常可以定义为方法
提示:需求中没有涉及的属性或方法在设计类时,不需要考虑
“”"
小明今年18岁 身高1.80 每天早上要跑步,会去吃东西
小张今年17岁 身高1.85 小张不跑步 小张喜欢吃东西
Person()
属性:
name
age
height
方法:
run()
eat()
一只黄颜色的狗叫大黄
看见陌生人汪汪叫
看见主人摇尾巴
Dog()
属性:
color
name
方法:
shout()
shake()
定义一个猫类
class Cat:
def eat(self):
print('%s 爱吃鱼' %(self.name))
def drink(self):
print('猫要喝水')
hellokitty = Cat()
hellokitty.name = 'HK'
print(hellokitty.name)
print(hellokitty)
hellokitty.eat()
hellokitty.drink()
# tom = Cat()
# tom.eat()
hellokitty是一个对象,也就是代码中的hellokitty.name和self.name是相同的
"""
self:
哪一个对象调用的方法,self就是哪一个对象的引用(指向对象的内存地址空间)
在调用方法的时候,程序员不需要传递self参数(定义的时候 第一个参数必须是self)
"""
初始化方法
初始化方法:
类名() 就可以创建一个对象
类名() 创建对象的时候,python解释器会自动执行以下操作
1.为对象在内存中分配空间–创建对象
2.调用初始化方法为对象的属性设置初始值
这个初始化方法是内置方法,是专门用来定义一个类据有哪些属性和方法的`
class Cat:
def __init__(self,new_name):
#print('这是一个初始化方法')
self.name = new_name
def eat(self):
print('%s 爱吃鱼' %(self.name))
#pass
def drink(self):
print('猫要喝水')
tom = Cat('Tom')
print(tom)
tom.eat()
hk = Cat('Hellokitty')
print(hk)
hk.eat()
str
在python中 使用print输出对象变量时候,默认情况下
会输出这个变量引用的对象是由哪一个类创建的对象以及在内存中的地址
如果在开发中,希望使用print输出变量的时候,能够打印自定义内容
就可以利用__str__这个内置的方法了
class Cat:
def __init__(self,name):
self.name = name
def __str__(self):
# 返回必须是一个字符串
return '我是 %s' %(self.name)
tom = Cat('tom')
print(tom.name)
print(tom)
addr = id(tom)
print(addr)
# 十六进制
print('%x' %(addr))
# 十进制
print('%d' %(addr))
del
del:如果希望在对象被销毁之前,再做一些事情,可以考虑一下__del__
当一个对象被从内存中销毁前(把这个对象从内存中删除掉),
会自动调用 __del__方法
class Cat:
def __init__(self,name):
self.name = name
print('%s 来了' %(self.name))
def __del__(self):
print('%s 走了' %(self.name))
tom = Cat('tom')
print(tom.name)
# del tom
print('*' * 50)
print(tom.name)
练习
栈:先进后出 入栈(push) 出栈(pop) 取栈顶元素
判断栈是否为空 显示栈元素 列表
队列:先进先出
class Stack:
def __init__(self):
self.stack = []
def push(self,value):
"""
:param value:入栈元素
:return:
"""
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')
s.push('3')
item = s.pop()
print(s.view())
封装
封装
1.封装是面向对象编程的一大特点
2.面向对象编程的第一步 将属性和方法封装到一个抽象的类中
3.外界使用类创建对象,然后让对象调用方法
4.对象方法的细节都被封装在类的内部
需求
1.小明体重75.0公斤
2.小明每次跑步都会减肥0.5公斤
3.小明每次吃东西体重都会增加1公斤
需求
1.小明和小美都爱跑步
2.小美体重45.0公斤
2.每次跑步都会减肥0.5公斤
3.每次吃东西体重都会增加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
xiaoming = Person('小明',75.5)
xiaoming.run()
xiaoming.eat()
print(xiaoming)
xiaomei = Person('小美',50)
xiaomei.eat()
xiaomei.run()
print(xiaomei)
需求:
1.房子有户型,总面积和家具名称列表
新房子是没有家具的
2.家具有名字和占地面积,其中
eg:占地 6平方米
3.将以上三件家具添加到房子中
4.打印房子的时候,要求输出:户型 总面积 剩余面积 家具名称列表
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 '户型:%sn总面积:%.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))
return
# 要将家具的名称添加到列表中去
self.item_list.append(item.name)
# 计算剩余面积
self.free_area -= item.area
# 创建家具
bed = HouseItem('床', 400)
print(bed)
chest = HouseItem('chest', 2)
print(chest)
table = HouseItem('桌子', 4.5)
print(table)
# 创建房子对象
my_home = House('两室一厅',90)
# 将家具添加到房子里面去
my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)
print(my_home)
1.士兵瑞恩有一把AK47
2.士兵可以开火(士兵开火扣动的是扳机)
3.枪 能够 发射子弹(把子弹发射出去)
4.枪 能够 装填子弹 --增加子弹的数量
class Gun:
def __init__(self,model):
self.model = model
self.bullet_count = 0
def add_bllet(self,count):
self.bullet_count += count
def shoot(self):
if self.bullet_count <= 0:
print('%s 没有子弹了...' %(self.model))
return
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))
return
self.gun.add_bllet(50)
self.gun.shoot()
ak47 = Gun('ak47')
ryan = Soldier('Ryan')
ryan.gun = ak47
ryan.fire()
ryan.fire()
多态
多态(以封装和继承为前提)
不同的子类对象调用相同的方法 产生不同的结果
Person():
work()
class Dog(object):
def __init__(self, name):
self.name = name
def game(self):
print('%s 开心的玩~' % (self.name))
class Gaofei(Dog):
# 父类方法不能满足子类的需求 重写game
def game(self):
print('%s和米老鼠一起玩~~~' %(self.name))
class Person(object):
def __init__(self,name):
self.name = name
def game_with_dog(self,dog):
print('%s和%s玩' %(self.name,dog.name))
# 创建一个狗对象
# wangcai = Dog('大黄')
wangcai = Gaofei('高飞')
# 创建一个人对象
xiaoming = Person('小明')
# 让小明和狗玩
xiaoming.game_with_dog(wangcai)
静态
class Cat(object):
@staticmethod
def call():
print('喵喵')
# 通过 类名.方法名 调用静态方法
Cat.call()
# 不需要创建对象 直接就可以调用
类方法类属性
类属性:针对类对象定义的属性 使用赋值语句在class关键字下可以定义类属性
类方法:针对类对象定义的方法 在类方法内部可以直接访问类属性或调用其他的类方法
class Toy(object):
# 使用赋值语句定义类属性 记录所有的玩具数量
count = 0
def __init__(self,name):
self.name = name
# 让类属性+1
Toy.count += 1
@classmethod
def show_toy_count(cls):
print('玩具对象的数量 %d' %(cls.count))
# 创建玩具对象
# toy1 = Toy('乐高')
# toy2 = Toy('泰迪熊')
Toy.show_toy_count()
class Cat(object):
@staticmethod
def call():
print('喵喵')
# 通过 类名.方法名 调用静态方法
Cat.call()
# 不需要创建对象 直接就可以调用
单例设计模式
单例设计模式
目的:让类创建对象,在系统中只有唯一的一个实例(对象)
每一次执行类名()返回的对象
内存地址是相同的
怎么保证 这些对象只有一个?
__new__方法:
========================================================================
我们用 类名. 的方式创建对象的时候,python解释器会帮我们做两件事情,是哪两件事情呢?
1.为对象分配空间 2.对象初始化
=======================================================================
使用类名()创建对象时,python的解释器首先会调用__new__方法为对象分配空间
__new__是一个由object基类提供的内置的静态方法,主要有两个作用:
在内存中为对象分配空间
返回对象的引用
python的解释器获得对象的引用后,将引用作为第一个参数,传递给__init__方法
#new:负责给对象分配空间 init(初始化方法)负责给对象初始化
我们要重写new方法,使用类名()创建对象的时候,返回的都是同一个地址
=========================================================
重写__new__方法的代码非常固定:
继承自父类方法
返回父类方法调用_new__方法的结果
重写__new__方法一定要return object.new(cls)
否则python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法
class MusicPlayer(object):
instance = None
def __new__(cls, *args, **kwargs):
print('创建对象 分配空间')
# 1.创建对象的时候,new方法会被自动调用
# instance = object.__new__(cls)
# return instance # 返回的就是对象的引用
# 判断类属性是否为空
if cls.instance is None:
# 调用父类方法 为第一个对象分配空间
cls.instance = object.__new__(cls)
return cls.instance
player1 = MusicPlayer()
player2 = MusicPlayer()
player3 = MusicPlayer()
print(player1)
print(player2)
print(player3)
从上述运行结果来看,单例设计模式最后分配的地址都是同一个,也就是播放器播放音乐只能播放一首,而不能同时播放两首
私有化
class Student(object):
def __init__(self, name, score):
# 前面带两个下划线表示对变量进行私有化
# 外部不能随便访问和更改
self.__name = name
self.__score = score
def get_grand(self):
print('my name is %s,my'
'grand is %d' % (self.__name, self.__score))
def __get_name(self):
return self.__name
def get_score(self):
return self.__score
def set_name(self, name):
if isinstance(name, str):
self.__name = name
else:
raise ValueError('请输入正确的名字')
def set_score(self, score):
if isinstance(score, int):
self.__score = score
else:
raise ValueError('请输入正确的成绩')
tom = Student('Tom', 89)
# print(tom.name)
# print(tom.score)
print(tom.__get_name())
# print(tom.get_score())
继承
封装:根据职责将属性和方法封装到一个抽象的类中
继承:实现代买的重用 相同的代码不需要重复的写
继承具有传递性
当父类方法不能满足子类的需求的时候
可以对方法进行重写
1.覆盖父类方法
2.对父类的方法进行扩展
class Animal:
def eat(self):
print('吃~~~')
def drink(self):
print('喝~~~')
def run(self):
print('跑~~~')
def sleep(self):
print('睡~~~')
class Cat(Animal):
def call(self):
print('喵喵')
class HelloKitty(Cat):
def sepak(self):
print('我可以说日语!!')
def call(self):
# 调用原本在父类中封装的方法
#super().call()
# Cat.call(self) python2.x
print('$#%$#%$#')
kt = HelloKitty()
kt.eat()
kt.run()
kt.call()
kt.sepak()
类的结构
术语–实例
1.使用面向对象开发,第一步是设计类
2.使用 类名() 创建对象,创建对象的动作有两步
1.在内存中为对象分配空间
2.调用初始化方法__init___ 为对象初始化
3.对象创建后,内存中就有了一个对象的实实在在的存在–实例
因此:
1.创建出来的对象叫做类的实例
2.创建对象的动作叫做实例化
3.对象的属性叫做实例属性
4.对象调用的方法叫做实例方法
在程序执行时:
1.对象各自拥有自己的实例属性
2.调用对象的方法,可以通过self
访问自己的属性
调用自己的方法
结论:
1.每一个对象都有自己独立的内存空间,保存各自不同的属性
2.多个对象的方法,在内存中之有一份,在调用方法时,
需要把对象的引用传递到方法内部
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('@#%#%#@')
self.hungry =False
else:
print('No Thanks')
# 在鸟的基础上 增加唱歌的功能
class SongBird(Bird):
def __init__(self):
super().__init__()
self.sound = 'aaaaa'
def sing(self):
print(self.sound)
brid = SongBird()
brid.eat()
brid.sing()
super().__init__()
如果不加扩展,那么子类会覆盖父类的方法,将父类的初始化覆盖掉,就会导致代码报错
新式类和旧式类
新式类和旧式(经典)类:
object是Python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看
新式类:以object为基类的类
经典类 不以object为基类的类
在python3.X中定义的类时,如果没有指定父类,会默认使用object作为基类--
python3.x中定义的类都是新式类
在python2.x中定义类时,如果没有指定父类,则不会以object作为基类
为保证编写的代码能够同时在python2.x和python3.x运行
今后在定义类时,如果没有父类,建议统一继承自object
练习
使用python面向对象的方式编写,实现银行转账
import pymysql
class TransferMoney(object):
# 构造方法
def __init__(self,conn):
self.conn = conn
self.cur = conn.cursor()
def transfer(self,source_id,target_id,money):
# 1.判断两个银行卡号是否存在
# 2.判断source_id是否有足够的钱
# 3.source_id扣钱
# 4.target_id加钱
if not self.check_account_avaialbe(source_id):
raise Exception("账户不存在")
if not self.check_account_avaialbe(target_id):
raise Exception("账户不存在")
if self.has_enough_money(source_id, money):
try:
self.reduce_money(source_id, money)
self.add_money(target_id, money)
except Exception as e:
print("转账失败:", e)
self.conn.rollback()
else:
self.conn.commit()
print("%s给%s转账%s金额成功" % (source_id,
target_id, money))
def check_account_avaialbe(self, acc_id):
"""判断帐号是否存在, 传递的参数是银行卡号的id"""
select_sqli = "select * from bankData where id=%d;" % (acc_id)
print("execute sql:", select_sqli)
res_count = self.cur.execute(select_sqli)
# res_count:返回数据记录数,只要有一条记录存在,
# 就证明账户存在
if res_count == 1:
return True
else:
return False
def has_enough_money(self, acc_id, money):
"""判断acc_id账户上金额> money"""
# 查找acc_id存储金额?
select_sqli = "select money from bankData where id=%d;" % (acc_id)
print("execute sql:", select_sqli)
self.cur.execute(select_sqli) # ((100, 100), )
# 获取查询到的金额钱数
# acc_moneys = self.cur.fetchone()
# print(acc_moneys)
acc_money = self.cur.fetchone()[0]
print(acc_money)
# 判断
if acc_money >= money:
return True
else:
return False
def add_money(self, acc_id, money):
update_sqli = "update bankData set money=money+%d where id=%d" % (money, acc_id)
print("add money:", update_sqli)
self.cur.execute(update_sqli)
def reduce_money(self, acc_id, money):
update_sqli = "update bankData set money=money-%d where id=%d" % (money, acc_id)
print("reduce money:", update_sqli)
self.cur.execute(update_sqli)
# 析构方法
def __del__(self):
self.cur.close()
self.conn.close()
# 1. 连接数据库,
conn = pymysql.connect(
host='localhost',
user='root',
password='redhat',
db='westos',
charset='utf8',
autocommit=True, # 如果插入数据,, 是否自动提交? 和conn.commit()功能一致。
)
trans = TransferMoney(conn)
#trans.add_money(100,200)
# trans.transfer(100,200,10)
#trans.has_enough_money(100,270)
def hello():
print('hello')
#hello()
#print(__name__)
if __name__ == '__main__':
hello()
最后
以上就是害怕往事为你收集整理的python-面向对象的全部内容,希望文章能够帮你解决python-面向对象所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复