python_面向对象的介绍/构造函数/类变量和实例变量/析构函数/私有属性和私有方法/继承、多继承和继承实例/多态
在这里得感谢,老师Alex金角大王(路飞学城IT)
Python(给兄弟们挂个🔗)
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 = name
self.role = role
self.weapon = weapon
self.life_value = life_value
self.money = money
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)
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 = role
self.weapon = weapon
self.life_value = life_value
self.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 = name
self.role = role
self.weapon = weapon
self.life_value = life_value
self.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 = 100
def __init__(self,name,role,weapon,life_value=100,money=15000):
self.name = name
self.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膨胀了,开始换公司里了...
man1.company = "Tencent"
#kunkun runing IT 去了...
print(man1.company)
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膨胀了,开始换公司里了...
man1.company = "Tencent"
#kunkun runing IT 去了...
print(man1.company)
#那个男人,嗯...懂的都懂...
print(man2.company)
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 man1
man2.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 = name
self.addr = addr
self.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 = name
self.age = age
self.sex = sex
def tell(self):
pass
class Teacher(SchoolMember):
def __init__(self,name,age,sex,salary,course):
super(Teacher,self).__init__(name,age,sex)
self.salary = salary
self.course = course
def tell(self):
print('''
---- info of Teacher:%s ----
Name:%s
Age:%s
Sex:%s
Salary:%s
Course:%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_id
self.grade = grade
def tell(self):
print('''
---- info of Student:%s ----
Name:%s
Age:%s
Sex:%s
Stu_id:%s
Grade:%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;
@staticmethod
def working(obj):
obj.work()
调用方式改变为:
man1 = teacher("daxiong",'25','man')
man2 = student("panghu",'22','man')
people.working(man1)
people.working(man2)