python_面向对象的介绍/构造函数/类变量和实例变量/析构函数/私有属性和私有方法/继承、多继承和继承实例/多态
在这里得感谢,老师Alex金角大王(路飞学城IT)
Python(给兄弟们挂个🔗)
Alex,面向对象
python边写边更…
一、面向对象的介绍:
<1>背景:(什么是“编程范式”)
1)编程范式:
1.程序员用(特定语法)+(数据结构)+(算法),组成代码,告诉计算机如何工作;
2.一百万个人,有一百万个不同形式;久之,就都会形成了一种“套路”,即"编程范式"
2)优劣:
1.面向过程:top-dowm language,从上到下的编程,上下具有依赖性,维护性太差(一步改,上下都得改)
2.面向对象:有的一些步骤呢,具有相同的 “相同方法” ,可以用 “函数” 实现;维护性好了一点,比较面向过程,代码减少了
3.面向对象:用 “类” 和 “对象” 来创建各种模型,来实现对真实世界的描述1.维护和扩展性高,大大提高开发效率…可以使人更加理解你的代码逻辑
<2>class(类):
是具有 “相同属性”的对象的抽象;在类中定义了这些了这些对象“都具备的属性”和“共同方法”
<3>object(对象):
类实例化后的一种实例,实例化也叫“类的初始化化”,类在实例化之后,才可以被调用;一个类可以“实例化”多个对象,每个对象亦可以有不同属性
<4>封装:
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
(…这个很抽象,enenen…这么理解,上帝造了“人”,外部访问的就只能是“你这个人”,你的内脏、器官都看知道)
<5>继承:
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
<6>多态:“一个接口,多种实现”
比如,你的老板让 “所有员工” 在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作
①、构造函数:
先来一个“cs”的面向对象实例:
#Author:Jony c#!/usr/bin/env python # -*- coding:utf-8 -*-class Role():def __init__(self,name,role,weapon,life_value=100,money=15000):self.name = nameself.role = roleself.weapon = weaponself.life_value = life_valueself.money = moneydef shot(self):print("shooting...")def got_shot(self):print("ah...,I got shot...")def buy_gun(self,gun_name):print("just bought %s" %gun_name)r1 = Role('Alex','police','AK47')r2 = Role('Jack','terrorist','B22')r1.buy_gun("AWM")
1.什么是“构造函数”???…
def __init__(self,name,role,weapon,life_value=100,money=15000):self.name = name #实例变量(“静态”属性),作用域就是 “实例”本身...self.role = roleself.weapon = weaponself.life_value = life_valueself.money = money
conclude:
“构造函数”(定义在类里),是在“实例化”一个对象时,相当于接收参数的函数;
!!!但是!!!,他与自变量赋值或者函数传参又不一样:
(如果按照函数/自变量,那样传参数,是这样…)
1.调用这个Role(“name”,“work”,“weapon”);
2.Role去开辟一个"内存空间",把这些值存起来,然后return给r1进行调用;
但是,并不是这样的…
构造函数的接收参数是这样的:
1.r1 = Role(“name”,‘role’,‘weapon’)
2.将 r1 / “name” / “role” / “weapon” ;都传给Role…其中的 r1 被self 接收
3.这样就在,def __init __(self,name,role,weapon)里面,直接操作
(把值都付给r1这个变量,放在内存空间存起来…)
self.name = nameself.role = roleself.weapon = weaponself.life_value = life_valueself.money = money
2.功能实现:
(“恐怖份子,实现开枪功能”)
r1.got_shot()#Role.got_shot(self)
这些功能定义在“类”里,而实例化之后的那些"属性"定义在r1里
def shot(self):print("shooting...")def got_shot(self):print("ah...,I got shot...")def buy_gun(self,gun_name):print("just bought %s" %gun_name)
②、实例变量和“类”变量:
(1)实例变量、“静态属性” 和 “属性”:
def __init__(self,name,role,weapon,life_value=100,money=15000):
enen…在实例化的时候,name,role,weapon,life_value…这些人物“属性”,被叫作"实例变量"、“静态属性”,这些也都是人物的基本属性…
(2)类方法、“动态属性”:
def shot(self):print("shooting...")def got_shot(self):print("ah...,I got shot...")def buy_gun(self,gun_name):print("just bought %s" %gun_name)
这些人物用来实现的“功能”,被叫作“动态属性”,也叫作“类方法”,其定义在类里面…
(3)类变量:
class Role():n = 100def __init__(self,name,role,weapon,life_value=100,money=15000):self.name = nameself.role = role
其中这个n,就代表是类变量…下面有情况用来讨论:
1)对实例变量进行修改:
class Role(object):def __init__(self,name,work,money):self.name = name;self.work = work;self.money = money;def eat(self):print("% is eating...."%self.name)man1 = Role("caixukun","rap and dancing",'2毛')#有一天,kunkun发达了...man1.money = "10块"print(man1.money)
1.实例化的时候,(类的初始化)的时候,kunkun才挣2毛钱…
2.经过长时间的rap & dance之后,enen…被发掘了,能挣10块了…
3.输出结果呢,result:10块(实例变量在外部进了修改)
2)实例变量 和 类变量:(那个优先???)
(下面kunkun给大家举个栗子…)
class Role(object):money = "100块"def __init__(self,name,work,money):self.name = name;self.work = work;self.money = money;def eat(self):print("% is eating...."%self.name)man1 = Role("caiukun","rap and dancing",'2毛')print(man1.money)
result:2毛
(kunkun一出生就有100块,kunkun说我不,我要自己打拼;然后自己打拼,挣了2毛…100块钱还没了)
1.也就是说,实力变量和类变量,都进行赋值,优先输出实例变量的赋的值…
3)对类变量进行修改:
#Author:Jony c#!/usr/bin/env python # -*- coding:utf-8 -*-class Role(object):company = "lehua"def __init__(self,name,work,money):self.name = name;self.work = work;self.money = money;def eat(self):print("% is eating...."%self.name)man1 = Role("caiukun","rap and dancing",'2毛')#kunkun膨胀了,开始换公司里了...pany = "Tencent"#kunkun runing IT 去了...print(pany)
result:Tencent
(kunkun刚开始在lehua深造,后面膨胀了,去Tencent敲代码了…)
1.输出结果为Tencent;
2.你可以理解为“修改”了类变量,(我的理解是又变了个法的搞了一个“实例变量”,实例变量优先)
enen…到底是哪种理解更好呢???…我们再实例化一个man2就行了
3.在实例化man2,“那个男人”(enen…乔治一代)
man2 = Role("qiaozhiyidai",'rap','3毛')
不修改man2的company…
#Author:Jony c#!/usr/bin/env python # -*- coding:utf-8 -*-class Role(object):company = "lehua"def __init__(self,name,work,money):self.name = name;self.work = work;self.money = money;def eat(self):print("% is eating...."%self.name)man1 = Role("caiukun","rap and dancing",'2毛')man2 = Role("qiaozhiyidai",'rap','3毛')#kunkun膨胀了,开始换公司里了...pany = "Tencent"#kunkun runing IT 去了...print(pany)#那个男人,嗯...懂的都懂...print(pany)
result:Tencent
lehua
(也就是说,类变量没被改…上面的那种我的理解起来稍微能更通顺一点…)
4)来看一种,可以改“类变量”的方法
(没有忘记局部变量的兄弟们,应该记得,局部变量也是可以在外部访问的时候改)
1.类变量,我把它定义为空列表
class Role(object):member = []
#Author:Jony c#!/usr/bin/env python# -*- coding:utf-8 -*-class Role(object):member = []def __init__(self,name,work,money):self.name = name;self.work = work;self.money = money;def eat(self):print("% is eating...."%self.name)man1 = Role("caiukun","rap and dancing",'2毛')man2 = Role("caiukun的亲戚","rap and dancing",'没钱')man1.member.append(man1)man2.member.append(man2)print(man1.member[0].name)print(man1.member[1].name)
result:caiukun
caiukun的亲戚
conclude:
实例变量 可以改 / 优先实例变量 / 字符串改不了 / 列表可以改
③、析构函数:(收尾工作,“接盘侠”/狗头)
1.class里面,我加一个析构函数:
(60年以后,kunkun和他家亲戚双双退休了…)
def __del__(self):print("60years have gone...%s退休了"%self.name)
result:60years have gone…caiukun退休了
60years have gone…caiukun的亲戚退休了
可以看到,析构函数是当"所有程序"(man1,man2)的都跑完了,才执行的“收尾工作”;enen…在这提一嘴“内存回收机制”
“内存回收机制”:
1.当程序运行完,Python把不用的变量,都会回收(上面属于这一种)
2.你自己把“门牌号”去删了,python就把内存回收了…(下面跑一下这种…)
#Author:Jony c#!/usr/bin/env python# -*- coding:utf-8 -*-class Role(object):member = []def __init__(self,name,work,money):self.name = name;self.work = work;self.money = money;def eat(self):print("%s is eating...."%self.name)def __del__(self):print("60years have gone...%s退休了"%self.name)man1 = Role("caiukun","rap and dancing",'2毛')man2 = Role("caiukun的亲戚","rap and dancing",'没钱')man1.eat()#Role.eat(man1)del man1man2.eat()#Role.eat(man2)
result:caiukun is eating…
60years have gone…caiukun退休了
caiukun的亲戚 is eating…
60years have gone…caiukun的亲戚退休了
④、私有属性 & 私有方法:
(外部访问不了你的“属性” / “方法”)
1.私有属性:(_ _money…kunkun这挣个2毛的,不好意思告诉人家)
def __init__(self,name,work,money):self.name = name;self.work = work;self.__money = money;#一个月挣多少钱,我不想告诉你
print(man1.__money)
result:报错,甚至都没有 “.” 调用这个方法…
那到底要怎么去调用???..解决:外边调用不了就在内部调用…
在class内部,写一个函数:(专门调用这个__money)
def diaoyong(self):print(self.__money)
man1.diaoyong()
result:2毛
私用方法同上…
(附上自己写的简单代码,可以试一下…)
#Author:Jony c#!/usr/bin/env python# -*- coding:utf-8 -*-class Role(object):member = []def __init__(self,name,work,money):self.name = name;self.work = work;self.__money = money;#一个月挣多少钱,我不想告诉你def diaoyong(self):print(self.__money)def eat(self):print("%s is eating...."%self.name)man1 = Role("caiukun","rap and dancing",'2毛')man2 = Role("caiukun的亲戚","rap and dancing",'没钱')man1.diaoyong()
二、面向对象的“特性”:
(封装、继承 和 多态 )
①、封装:
上面在介绍的时候已经实现了…就是外部访问的永远是man1、man2这个整体…数据都在里面(类里放的是“功能”、man放的“属性”)
②、继承:
[ “子类”继承“父类”的…“属性” & “功能”(类方法) ]
1)普通继承:
#Author:Jony c#!/usr/bin/env python# -*- coding:utf-8 -*-class people(object):def __init__(self,name,age,sex):self.name =name;self.age =age;self.sex =sex;def play(self):print("%s is playing...."%self.name)class Man(people):#Man这个子类,继承了people这个父类的“属性”、“方法”def eat(self):#除了继承“父类”的play,自己又写了一个自己方法:“eat”print("%s is eating....."%self.name)man1 =Man("chizi","25",'male')man1.eat()#实现一下自己的man1.play()#实现一下父类的
2)“重构”方法:(父类 + 新功能)
#Author:Jony c#!/usr/bin/env python# -*- coding:utf-8 -*-class people(object):def __init__(self,name,age,sex):self.name =name;self.age =age;self.sex =sex;def play(self):print("%s is playing...."%self.name)class Man(people):def play(self):people.play(self)#重构了“父类” 的方法print("%s 想再玩1个小时"%self.name)#加上一个新功能man1 =Man("chizi","25",'male')man1.play()
result:
chizi is playing…
chizi 再玩1个小时
3)“重构”属性:(子类的“特殊”属性)(父类属性+自己独有的属性)
#Author:Jony c#!/usr/bin/env python# -*- coding:utf-8 -*-class people(object):def __init__(self,name,age,sex):self.name =name;self.age =age;self.sex =sex;def play(self):print("%s is playing...."%self.name)class Man(people):def __init__(self,name,age,sex,money,weight):people.__init__(self,name,age,sex)#重构“属性”self.money = money ;self.weight =weight;man1 =Man("chizi","25",'male',100,130)print(man1.money)print(man1.weight)
result:100
130
!!!但是我们一般不用这种…用下面这种
#People.__init__(self,name,age)super(Man,self).__init__(name,age,sex)
4)“多继承”:(一次继承,2个“类”)
旧式继承:
class people()
新式继承:(object是一种“基类”)
class people(object)
1)"多继承"的一些“优先”:
[python 2.x 里面是“深度优先”(旧式类),“广度优先”(新式类);python 3.x 里面都是 “广度优先” ]
下图,如果是这样的一个“继承”:
这样一个优先顺序:1.先找自己的 2.再找B 3.再找C 4.再找“同排” 的
5.“同排” 的没有的话 6.再找 A …这样的“优先顺序”,被定义为“广度”优先
这样一个优先顺序:1.先找自己的 2.再找B 3.再找A 4.再找“C”…这样的“优先顺序”,被定义为“深度”优先
2)"多继承"的实例:
先定义两个“父类”:
class people(object):def __init__(self,name,age,sex):self.name =name;self.age =age;self.sex =sex;def play(self):print("%s is playing...."%self.name)
class relation(object):def fight(self,obj):print("%s is fighting with %s..."%(self.name,obj.name))
子类的Man,继承了people / relation,这两个父类
class Man(people,relation):def __init__(self,name,age,sex,money,weight):#people.__init__(self,name,age,sex)#重构“属性”super(Man,self).__init__(name,age,sex)self.money = money ;self.weight =weight;man1 =Man("chizi","25",'male',100,130)#实例化man2 =Man("lidan","35",'male',100000,150)#实例化man1.fight(man2)#调用“父类”函数
result:
chizi is fighting with lidan…
3)"多继承"的实例之“学校”:
__author__ = "Alex Li"class School(object):def __init__(self,name,addr):self.name = nameself.addr = addrself.students =[]self.staffs =[]def enroll(self,stu_obj):print("为学员%s 办理注册手续"%stu_obj.name )self.students.append(stu_obj)def hire(self,staff_obj):self.staffs.append(staff_obj)print("雇佣新员工%s" % staff_obj.name)class SchoolMember(object):def __init__(self,name,age,sex):self.name = nameself.age = ageself.sex = sexdef tell(self):passclass Teacher(SchoolMember):def __init__(self,name,age,sex,salary,course):super(Teacher,self).__init__(name,age,sex)self.salary = salaryself.course = coursedef tell(self):print('''---- info of Teacher:%s ----Name:%sAge:%sSex:%sSalary:%sCourse:%s'''%(self.name,self.name,self.age,self.sex,self.salary,self.course))def teach(self):print("%s is teaching course [%s]" %(self.name,self.course))class Student(SchoolMember):def __init__(self,name,age,sex,stu_id,grade):super(Student,self).__init__(name,age,sex)self.stu_id = stu_idself.grade = gradedef tell(self):print('''---- info of Student:%s ----Name:%sAge:%sSex:%sStu_id:%sGrade:%s''' % (self.name, self.name, self.age, self.sex, self.stu_id, self.grade))def pay_tuition(self,amount):print("%s has paid tution for $%s"% (self.name,amount) )school = School("老男孩IT","沙河")t1 = Teacher("Oldboy",56,"MF",200000,"Linux")t2 = Teacher("Alex",22,"M",3000,"PythonDevOps")s1 = Student("ChenRonghua",36,"MF",1001,"PythonDevOps")s2 = Student("徐良伟",19,"M",1002,"Linux")t1.tell()s1.tell()school.hire(t1)# school >>> 调的函数 >>> 都存在 "school.students[]"里面school.enroll(s1)school.enroll(s2)print(school.students)#school = School("老男孩IT","沙河")print(school.staffs)#school = School("老男孩IT","沙河")school.staffs[0].teach()for stu in school.students:stu.pay_tuition(5000)#调的 student 的 函数功能
③、多态:(“一个接口,多种实现”)
1.先来一个“父类”:
class people(object):def __init__(self,name,age,sex):self.name= name;self.age= age;self.sex= sex;
2.定义2个“子类”:
class teacher(people):def work(self):print("%s is teaching..."%self.name)class student(people):def work(self):print("%s is studing..."%self.name)
3.实例化2个“对象”:
man1 = teacher("daxiong",'25','man')man2 = student("panghu",'22','man')man1.work()man2.work()
result:daxiong is teaching…
panghu is studing…
你会发现这样实际是一个“功能”(work),调用了2次
就这样加一个“函数”,实现“一个接口,多种实现”
def working(obj):obj.work()
man1 = teacher("daxiong",'25','man')man2 = student("panghu",'22','man')working(man1)working(man2)
4.多态的实现:
(加个装饰器的语法糖…把定义好的函数加进去)
class people(object):def __init__(self,name,age,sex):self.name= name;self.age= age;self.sex= sex;@staticmethoddef working(obj):obj.work()
调用方式改变为:
man1 = teacher("daxiong",'25','man')man2 = student("panghu",'22','man')people.working(man1)people.working(man2)
python_day6_面向对象的介绍/构造函数/类变量和实例变量/析构函数/私有属性和私有方法/继承 多继承和继承实例/多态