面对对象和面对过程
在此之前,无论是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)