Python的学习-Python中面向对象的思想

面向过程 面向对象(oop:object oriented programming)
面向过程:—侧重于怎么做?
1.把完成某一个需求的 所有步骤 从头到尾 逐步实现
2.根据开发要求,将某些功能独立的代码封装成一个又一个函数
3.最后完成的代码,就是顺序的调用不同的函数
特点:
1.注重步骤和过程,不注重职责分工
2.如果需求复杂,代码变得非常复杂
3.开发复杂的项目的时候,没有固定的套路,开发难度很大

面向对象:----侧重于谁来做?
相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
1.在完成某一个需求前,首先确定职责–要做的事(方法)
2.根据职责确定不同的对象,在对象内部封装不同的方法(多个)
3.最后完成代码,就是顺序的让不同的对象调用不同的方法
特点:
1.注重对象和职责,不同的对象承担不同的职责
2.更加适合对复杂的需求变化,是专门应对复杂项目的开发,提供固定的套路
3.需要在面向过程的基础上,再学习一些面向对象的语法

面向过程—>侧重于怎么做?
面向对象—>测中于谁来做?

面向对象有两个核心的概念
类:是一类具有相同特征或行为的事物的一个统称
对象:由类创建出来的一个具体的存在
类和对象的关系:先有类再有对象
类是模板 对象是根据这个模板创建出来的
类只需要有一个 对象可以有多个

类:属性(这一类事务的共同信息) 和 方法(你能完成的动作)
1.类名:这类事物的名字(大驼峰命名法)
大驼峰命名法:
1.每个单词的首字母大写
2.单词与单词之间没有下划线
2.属性:这个类创建出来的对象有什么特征
3.方法:这个类创建出来的对象有什么行为

类名的确定
名词提炼法分析整个业务流程,出现的名词,通常就是找到的类

属性和方法的确定
对 对象的特征描述,通常可以定义成属性
对象具有的行为(动词),通常可以定义为方法
提示:需求中没有涉及的属性或方法在设计类时,不需要考虑类的结构
术语–实例
1.使用面向对象开发,第一步是设计类
2.使用 类名() 创建对象,创建对象的动作有两步
1.在内存中为对象分配空间
2.调用初始化方法__init___ 为对象初始化
3.对象创建后,内存中就有了一个对象的实实在在的存在–实例
因此:
1.创建出来的对象叫做类的实例
2.创建对象的动作叫做实例化
3.对象的属性叫做实例属性
4.对象调用的方法叫做实例方法
在程序执行时:
1.对象各自拥有自己的实例属性
2.调用对象的方法,可以通过self
访问自己的属性
调用自己的方法
结论:
1.每一个对象都有自己独立的内存空间,保存各自不同的属性
2.多个对象的方法,在内存中之有一份,在调用方法时,需要把对象的引用传递到方法内部

类的创建

class dog:
def eat(self):
print(’%s爱吃肉’ % (self.name))
def des(self):
print(’%s爱拆家’ % (self.name))
def shake(self):
print(’%s爱汪汪叫’ % (self.name))

dahuang = dog()
dahuang.name = ‘大黄’
dahuang.eat()
dahuang.shake()

erha = dog()
erha.name = ‘二哈’
erha.eat()
erha.shake()
erha.des()

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方法

__ 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)
在这里插入图片描述

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)
print(’*’ * 50)
print(tom.name)
在这里插入图片描述
class Cat:
def __ init__(self,name):
self.name = name
print(’%s 来了’ %(self.name))
def __ del__(self):
print(’%s 走了’ %(self.name))
tom = Cat(‘tom’)
在这里插入图片描述
栈:先进后出 入栈(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)
在这里插入图片描述

继承

我们不想把同一段代码写好几次,之前使用的函数避免了这种情况。但现在又有个更微妙的问题。如果已经有了一个类,又想建立一个非常类似的类,只是添加几个方法。
比如有人类,我们又想在人类的基础上建立学生类、医生类,教师类。因为他们都具有共同的属性和方法,比如都有 姓名 、年龄 、性别 等共同属性,还有吃饭、睡觉等共同方法。我们就可以写一个人类作为父类,包括姓名、年龄、性别等属性和吃饭睡觉等方法。然后再写多个子类继承父类的这些属性和方法。
但需要注意的是,父类的私有属性和方法不会被子类继承
class person:
def run(self):
print(‘跑步’)
def work(self):
print(‘工作’)
def sleep(self):
print(‘睡觉’)

class man(person):
def __ init__(self,name):
self.name=name
def eat(self):
print(’%s吃得多’ %self.name)

class woman(person):
def __ init__(self,name):
self.name=name
def eat(self):
print(’%s吃得少’ %self.name)

xm=man(‘小明’)
xm.run()
xm.eat()

mdm=woman(‘马冬梅’)
mdm.sleep()
mdm.eat()
在这里插入图片描述
继承具有传递性
当父类方法不能满足子类的需求的时候
可以对方法进行重写
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):
print(’KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲%#%$#’)

kt = HelloKitty()
kt.eat()
kt.run()
kt.call()
kt.sepak()
在这里插入图片描述
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()
在这里插入图片描述
一个子类继承多个父类:
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(B,A): #B将A覆盖了
pass

c = C()
c.test()
c.demo()
在这里插入图片描述
多态(以封装和继承为前提)
不同的子类对象调用相同的方法 产生不同的结果
当子类和父类都存在相同的方法时,我们说,子类的方法覆盖了父类的方法,在代码运行的时候,总是会调用子类的方法。这样,我们就获得了继承的另一个好处:多态。
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)
在这里插入图片描述
在这里插入图片描述

练习

需求:
1.房子有户型,总面积和家具名称列表
新房子是没有家具的
2.家具有名字和占地面积,其中
eg:占地 6平方米
3.将以上三件家具添加到房子中
4.打印房子的时候,要求输出:户型 总面积 剩余面积 家具名称列表
class HouseItem:
# 初始化方法
def __ init__(self, name, area):
self.name = name
self.area = area
def __ str__(self):
return ‘[%s] 占地 %.2f’ % (self.name, self.area)

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))
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()
在这里插入图片描述

新式类和旧式类

新式类和旧式(经典)类:
object是Python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看
新式类:以object为基类的类
经典类 不以object为基类的类

在python3.X中定义的类时,如果没有指定父类,会默认使用object作为基类–
python3.x中定义的类都是新式类
在python2.x中定义类时,如果没有指定父类,则不会以object作为基类

为保证编写的代码能够同时在python2.x和python3.x运行
今后在定义类时,如果没有父类,建议统一继承自object

[dd@foundation0 bin]$ /usr/local/python3/bin/python3
Python 3.6.4 (default, Aug 10 2018, 11:14:49)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
Type “help”, “copyright”, “credits” or “license” for more information.

class A:
… pass

dir(A)
[‘class’, ‘delattr’, ‘dict’, ‘dir’, ‘doc’, ‘eq’, ‘format’, ‘ge’, ‘getattribute’, ‘gt’, ‘hash’, ‘init’, ‘init_subclass’, ‘le’, ‘lt’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’]
class B(object):
… pass

dir(B)
[‘class’, ‘delattr’, ‘dict’, ‘dir’, ‘doc’, ‘eq’, ‘format’, ‘ge’, ‘getattribute’, ‘gt’, ‘hash’, ‘init’, ‘init_subclass’, ‘le’, ‘lt’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’]

类属性和类方法

类属性:针对类对象定义的属性 使用赋值语句在class关键字下可以定义类属性
类方法:针对类对象定义的方法 在类方法内部可以直接访问类属性或调用其他的类方法
class eat(object):
count = 0
def __ init__(self, name):
self.name = name
eat.count += 1
@classmethod
def show_eat_count(cls):
print(‘吃饭的次数为:%d’ % (cls.count))

eat1 = eat(‘面包’)
eat2 = eat(‘米饭’)
eat.show_eat_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.__get_name())
在这里插入图片描述

终极练习

用数据库实现银行的转账功能:
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)
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值