一、面向对象oop(object oriented programming)
介绍:把函数和数据封装在一起,具有封装、继承、多态的特点。
类:可以理解为现实中的一个工厂或者某样实际物质的蓝图,按照类可以生产出一个对象。也就是常说的,类是对象的抽象,而对象是类的实例。
实例方法:在类的内部使用def关键字定义,第一个参数默认是self(名字标识可以是其他的,但是位置必须存在),归属于类的实例所有。
类属性:在类内部,在实例方法外部,定义的变量,归属于类,直接使用类去调用。
实例属性:在实例方法内部定义的变量,归属于实例,使用实例去调用。
二、__init__函数
介绍:在类内部创建的一个函数,通过此函数我们可以初始话实例属性。这个方法在创建实例对象时自动执行,我们可以通过对此方法设置形式参数,达到将类更加通用化的目的。
class Pepole:
#双下划线开始结束的方法,是python内置的方法,称为魔术方法,自动执行
def __init__(self,name,sex,age):#这边加了形参的话,在创建实例对象时,一定要一个坑位一个占好了,不然缺参数报错
self.name=name
self.sex=sex
self.age=age
xz=Pepole('鹿鸣松','男',24)
print(xz.name,xz.age,xz.sex)
三、理解self
在上面实例方法的创建中,IDE自动生成了self变量,这个self是什么?
介绍:self和对象指向同一个内存地址,可以认为self就是对象的引用。这个只有在实例方法调用的时候才有意义,调用时不必传入相应的参数。
class Person:
def eat(self):
print('self的内存地址{}'.format(id(self)))
pass
xw=Person()
print('xw的内存地址{}'.format(id(xw)))
xw.eat()
上面代码执行下来发现,打印出的两个内存地址是一样的。
四、魔术方法
4.1__init__函数
参考二中描述
4.2__str__函数
def __str__(self):
return '自定义对象的内容格式'
这个方法主要是方便在打印对象的时候能看懂这个对象是什么,有什么用处。跟Java的tostring方法相似。
4.3__new__函数
创建实例对象时需要执行的方法,需要注意的是必须要返回该实例,不然对象创建不成功。至少有一个参数cls代表要实例化的类,此参数在实例化时由python解释器自动提供。
def __new__(cls, *args, **kwargs):
'''
场景:可以控制创建对象的一些属性限定,经常用来做单例模式的时候用
:param args:
:param kwargs:
'''
print('执行此new函数了')
return object.__new__(cls)#创建真正的实例对象
4.4_del__函数
程序结束后自动执行的方法,释放内存空间。
class Animal:
def __init__(self,name):
self.name=name
print('这是构造初始化方法')
def __del__(self):
#主要的应用就是来操作对象的释放,一旦释放完毕 对象便不能再使用
print('当在某个作用域下面,没有使用【引用】的情况下,解析器会自动的调用此函数,来释放内存空间')
print('这是析构方法')
print('%s对象被彻底清理了,内存空间也释放了'%(self.name))
dog=Animal('小白')
# del dog #手动删除对象,也会执行__del__函数,这样下面打印对象的名字属性,就会报错,没有定义这个对象
input('程序等待中……')
print(dog.name)
五、类方法和静态方法
实例方法只能通过实例对象去调用,而有时候需要类对象也能去调用这个实例方法,所以只需要在方法上一行加个类方法的装饰器。
@classmethod
def sleep(params):
print('这个是类方法,通过类对象或者实例对象都可以调用')
pass
静态方法不需要传任何参数,同样可以通过类对象或者实例对象去访问。但一般情况下不会去用实例对象访问。
@staticmethod
def getName():
print('这是静态方法,可以通过类对象或者实例对象调用')
return Person.name
那么为什么要使用静态方法呢?它的使用场景是什么?
静态方法主要来存放逻辑性的代码,本身和类以及实例对象没有交互,也就是不会涉及到类中的方法和属性的操作。这样能使数据资源得到有效的充分利用。
五、实操案例
决战紫禁之巅,重现西门飞雪和叶孤城的王者之战。
import random
import time
class Person:
def __init__(self,name,boold):
self.name=name
self.boold=boold
def tong(self,enemy):
enemy.boold-=10
print('%s捅了%s一刀'%(self.name,enemy.name))
time.sleep(1)
print('%s掉10滴血'%(enemy.name))
def kan(self,enemy):
enemy.boold-=20
print('%s砍了%s一刀' % (self.name, enemy.name))
time.sleep(1)
print('%s掉20滴血'%(enemy.name))
def chiyao(self):
self.boold+=5
print('%s加5滴血'%(self.name))
def __str__(self):
return '%s的当前血量剩余%d'%(self.name,self.boold)
xmfx=Person('西门飞雪',100)
ygc=Person('叶孤城',100)
def xingdong(me,enemy):
i = random.randint(0, 2)
if i == 0:
me.tong(enemy)
time.sleep(1)
print(enemy)
elif i == 1:
me.kan(enemy)
time.sleep(1)
print(enemy)
else:
if me.boold==100:
print('HP满,无需吃药')
else:
me.chiyao()
time.sleep(1)
print(me)
while xmfx.boold >=0 and ygc.boold >=0:
x = random.randint(0,1)
if x==0:
print('西门飞雪发起行动')
time.sleep(1)
xingdong(xmfx,ygc)
else:
print('叶孤城发起行动')
time.sleep(1)
xingdong(ygc,xmfx)
if xmfx.boold<=0:
print('%s失败'%(xmfx.name))
break
if ygc.boold<=0:
print('%s失败'%(ygc.name))
break
这段代码我执行了十次,八次都是西门老哥赢了,两次叶老弟险胜。
其中有一把西门老哥连发五次大招,直接将叶老弟抬走,叶老弟惊呼:是不是玩不起???
这还不是最好玩的,更好玩的一把是两个人只加血不打架。
我:板凳都搬好了,就给我看这个???
优化下代码……
加血时做下判断,血量100就不加了,浪费一次行动机会。
然后还有一把叶老弟玩起诈尸,血量到0了,还能发起行动给自己来一口春哥。
叶孤城:我还能抢救一下……
我:…………
优化下代码……
给最后两个判断加上break退出循环,不然血量在0的时候还有可能来个回首掏……