面对对象和面对过程
在此之前,无论是ATM,还是购物车,我们用的都是简单的面向过程,那么面向过程和面向对象进行比较,又有哪些优缺点呢?
面向过程
优点:复杂问题流程化,进而简单化
确定:可扩展性差
面向对象
优点:可扩展性高
缺点:编写复杂
类与对象
对象是属性和方法的结合体
类是一系列共同的属性和方法
程序中的类和现实中的类是类似的,现实中的家禽类,鸟类都是一些相似的,有共同的生物的集合,而程序中的类的作用也是如此,可以将有相同的方法或者属性的对象放到类中
当然,现实中和程序里的类还是有不小区别的,比如说,现实中肯定是先有对象接下来才有类,因为你需要将那些对象归到类中。而程序中则恰好相反,必须得定义类,随后再生成对象
类的定义
有如下俩个学生:
'''
学生1:
学校:哈佛大学
姓名:李铁蛋
性别:女
年龄:18
方法:
选课
学习
学生1:
学校:哈佛大学
姓名:李钢蛋
性别:男
年龄:48
方法:
选课
学习
'''
有如上俩个学生,可以发现,他们的学校是一样的,方法也是一样的,都是选课和学习,那么该如何定义类呢?
首先,定义类的方式为:class(关键字) + 类名:
class Student:
#变量表示属性
school = '哈佛大学'
def choose(self):
print("选课....")
def study(self):
print('学习')
生成对象
生成对象其实很简单,就是类加括号
stu1 = Student()
获取属性和方法,通过.获取
print(stu1.school) # '哈佛大学'
print(stu1.choose) # choose方法的内存地址
查看类中的属性和函数
首先我们可以使用__dict__方法来以字典的形式输出类中的属性和方法
print(Student.__dict__)
结果为:
{'__module__': '__main__', 'school': 'oldboy', 'choose': <function Student.choose at 0x000001E5A5753A60>, 'study': <function Student.study at 0x000001E5A5753AE8>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
既然如此,我们肯定也可以通过从字典中根据key值来检索value值从而可以获取方法:
print(Student.__dict__['school']) # '哈佛大学'
Student.__dict__['choose'](123) # 选课...
Student.choose(123) # 选课...
print(Student.school) # '哈佛大学'
获取对象的属性和方法
stu1 = Student()
print(stu1.school) # '哈佛大学'
# 对象来调用方法,第一个参数不用传
print(stu1.choose) # choose内存地址
stu2=Student()
print(stu2.school) # '哈佛大学'
对象自己的属性和方法
如果某个类中的对象,它的某个属性需求和类中的不同,那该怎么办?这时只要对象中自己定义就可以了,这种改变并不会影响到类
属性查找顺序:先从对象自身找------>类中找----->没有则报错
stu1=Student()
stu1.name='nick sb'
stu1.school='xxxx'
# print(stu1.xxx) # 报错
print(stu1.school) # 'xxxx'
print(stu1.__dict__) # 对象的属性和方法以字典形式表达
如果没有定义对象的话,直接print(stu1.__dict__)会得到空字典
向对象中放属性的方式
方式一
stu1=Student()
stu1.name='李铜蛋'
方式二:
通过__init__方法
class Student:
#变量表示属性
school='oldboy'
def __init__(self,name):
self.name=name
def choose(self):
print("选课....")
def study(self):
print('学习')
产生对象:
对象
# stu1=Student() # 报错
stu1=Student('nick')
#内部帮我们做了一些事:当我在实例化产生对象的时候,会自动调用__init__方法,完成对象的初始化
print(stu1.name)
stu2=Student('jason')
print(stu2.name)
绑定方法
定义在类内部的方法
如果类来调用,就是一个普通的函数,有几个参数就需要传几个参数
如果对象来调用:它叫对象的绑定方法,第一个参数不需要传,自动传递
class Student:
#变量表示属性
school='oldboy'
def __init__(x,name):
x.name=name
def choose(self):
print("选课....")
def study(self):
print('%s学会了python'%self.name)
stu1=Student('张全蛋')
stu1.study()
stu1=Student('李铁蛋')
stu1.study()
结果为:
张全蛋学会了python
李铁蛋学会了python
一切皆对象
在Python中,无论是字符串还是列表,都是对象
比如一个列表:
l1=[1, 2, 3]
它也可以这样打:
l1=list([1, 2, 3])
l2=list([5, 7, 8])
对比一下类和对象,有没有发现这俩者及其类似吗
再想一下列表的内置方法:
list.append(l1, 9)
有没有发现和类里的方法的调用方式一模一样
其实你点开列表的内置方法,就会发现就是类里的一个个_init_
类的初步实战:人狗大战
#人狗大战
#定义一个狗类
class Dog:
type_dog='藏獒'
def __init__(self,name,aggressivity,hp=100):
self.name=name
self.aggressivity=aggressivity
self.hp=hp
def bite(self,target):
#当期狗的攻击力:self.aggressivity
#人的血量:target.hp
target.hp-=self.aggressivity
print('''
狗的品种:%s
%s狗咬了一下%s人,
人掉血:%s
人的血量剩余:%s
'''%(self.type_dog,self.name,target.name,self.aggressivity,target.hp))
#人类
class Human:
def __init__(self,name,aggressivity,hp=100):
self.name=name
self.aggressivity=aggressivity
self.hp=hp
def bite(self,target):
target.hp-=self.aggressivity
print('''
%s人咬了一下%s狗,
狗掉血:%s
狗的血量剩余:%s
'''%(self.name,target.name,self.aggressivity,target.hp))
#实例化产生狗对象
# dog1=Dog('旺财',10)
dog1=Dog('旺旺财',10,200)
nick=Human('nick',50)
dog1.bite(nick)
print(nick.hp)
dog1.bite(nick)
print(nick.hp)
nick.bite(dog1)