面向对象
Posted FRESHMANS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象相关的知识,希望对你有一定的参考价值。
面向过程:程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题,把一个大问题分解成多个小问题
面向对象:oop,利用类和对象来创建各种模型来实现对真实世界的描述(类,object对象)object对象即是一个类实例化后实例,一个类必须经过实例化后方可在过程中调用,一个类可实例化多个对象
面向对象的3个特性:
- 封装 :将数据和操作组装到一起,对外只暴露一些接口供类外部或子类访问,隐藏数据和操作的实现细节(对相同的属性和方法封装到类中;将数据封装到对象中)
- 继承 :一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
- 多态 :一个接口,多种实现,通过一个接口可以做多种工作
面向对象基础
示例
#!/usr/bin/env python # -*- coding:utf-8 -*- class Role: n = 123 #类变量(公用的变量) name = "我是类name" #类变量(公用的变量) #构造函数,在实例化时做一些类的初始化的工作(self....) 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
注释:
上面的这个__init__()叫做初始化方法(或构造方法), 在类被调用时,这个方法(虽然它是函数形式,但在类中就不叫函数了,叫方法)会自动执行,
进行一些初始化的动作,所以我们这里写的__init__(self,name,role,weapon,life_value=100,money=15000)就是要在创建一个角色时给它设置这些属性,
##析构函数:在类的实例释放或销毁的时候执行(即最后执行),通常关闭一些数据库链接,关闭一些打开的临时文件 def __del__(self): ####析构函数 print("%s 彻底死了。。。。" %self.name) ####类的方法,功能 def show_status(self): print("name:%s weapon:%s life_val:%s" %(self.name,self.weapon,self.__life_value)) def __shot(self): # 私有方法,从类的外面是无法调用的,只能从内部调用 print("shooting...") def got_shot(self): self.__life_value -=50 ##(“__”开头的)私有属性,只有内部可以调用的属性,在类外部无法调用(查看私有属性的方法就是定义一个函数然后查看) print("%s:ah...,I got shot..."% self.name) #return Role.__shot #可在类内部引用这个私有方法
def buy_gun(self, gun_name): print("%s just bought %s" % (self.name,gun_name) )
###r1 又叫做Role的实例 r1 = Role(\'tom\', \'police\', \'AK47\') ###实例化,初始化一个类,造了一个对象,这个对象就叫做实例,r1 为Role下的self r1.name = "类变量测试" r1.buy_gun("AK47") ###即,Role.buy_gun(r1) Role.buy_gun(r1,\'bob\') ###把一个类变成一个具体对象的过程叫 实例化(初始化一个类,造了一个对象)
打印结果:
类变量测试 just bought AK47 #r1.buy_gun("AK47")的结果
类变量测试 just bought bob #Role.bug_gun(r1,\'bob\')的结果
类变量测试 析构函数测试。。。。 #析构函数的结果
说明:(类里面既有类变量也有实例变量,会首先从实例变量里面找,实例变量里面没有才会从类变量里面找)name先从实例本身找,如果实例本身没有则从类里面找,如果类变量发生变化,如果实例变量又和类变量相同的,则默认先找实例变量再找类变量
类变量示例:
#类变量:大家共用的属性或者变量 class person: cn = "中国" ###,静态字段,属于类,类变量写在这里,如果有10亿人只要赋值一次就行(节省开销) def __init__(self,name,age,addr,cn): self.cn = cn ###如果类变量写在这里,如果有10亿人,每个人都要赋值一次(如果有特殊的可直接修改)
类的继承
通过例子详细说明
###经典类和新式类的区别在多继承上 class People(object): ###现在的标准写法(新式类,多继承的方式变了) def __init__(self,name,age): self.name = name self.age =age def eat(self): print ("%s is eating" % self.name) def sleep(self): print ("%s is sleeping..." % self.name)
class Relation(object): def makefriend(self, obj): print("%s is makeing friend" % self.name, obj.name)
class Man(People,Relation): ###类的继承,从左到右依次执行 def __init__(self,name,age,money): ###重构父类,重新初始化父类所有参数,然后加上自己新的参数 #People.__init__(self,name,age) ###调用父类的方法(经典类写法,与super效果一样) super(Man,self).__init__(name,age) ###调用父类的方法(新式类写法)另一种调用父类的方法,与上面的效果一样 #self.person = Person(self,job) ###组合继承(假设有个类,Person,参数为job,如果此处无法重构,可用此方法) self.money = money print ("shopping cost %s" % self.money) def piao(self): print ("%s is piaoing" % self.name)
class Woman(People,Relation): def get_birth(self): print ("%s is born a baby" % self.name) m1 = Man("sb",23,23) #__init__初始化的而时候有三个参数,所以传三个实参(继承了父类2个参数,自己一个参数) # m1.eat() w1 = Woman("wm",22) # w1.get_birth() m1.makefriend(w1) ####多继承,此时的w1为relation类下的obj, m1 首先从man类下找makefried方法,man下没有就从继承 的类 Relation下找,参数为w1
#说明:
m1和w1 都继承了people类,所以m1和w1除了可以调用自己类下的方法之外,还可以调用继承的people类下的所有方法
如果父类和自己都有相同的方法名(或者不想调用父类下的某个方法),默认会先调用自己类下的方法
打印结果:
shopping cost 23 #由上面代码发现没有调用任何方法,打印的这一条为类 Man在实例化时,__init__初始化时打印的 sb is makeing friend wm #m1.makefried(w1) 即为m1继承类Relation,Relation的self为m1,将w1作为参数传递给makfriend函数,及obj=w1,则self.name = m1.name,obj.name=w1.name
多继承示例一
多继承: class f0(object): def a0(self): print ("a0") class f1(f0): def a0(self): print ("a1") class f2(object): def a0(self): print ("a2") class f3(f1,f2): def a3(self): print ("a3") c = f3() c.a0() 说明: c调用a0方法时,会先从本类找,本类找不到会从 f1 类下找,如果f1父类下找不到,会从f1的父类f0下找(f1继承f0),如果类f0下还找不到,则会从类f2下找; 如果f1和f2 继承了相同的父类,则最后去这个相同父类找
多继承示例二
#!/usr/bin/env python #-*-coding:utf-8-*- class a1(object): def test_a1(self): print ("test_a1") self.test_b1() def test_b1(self): print ("test_b1") class a2(object): def test_b1(self): print ("test_a2") class cust(a2,a1): #c.test_a1(),会先去类a1下查找test_a1的方法(执行打印test_a1),然后会执行self.test_b1()方法,执行流程为 ,先回到实例化对象c这里,先从继承的类a2查找有没有test_b1()方法,如果有,就会直接执行,不会再去类a1下查找test_b1方法
pass c = cust() c.test_a1()
#打印结果:
test_a1
test_a2
示例:
新式类和旧式类的区别在于类继承的顺序问题: python2 旧式类按深度优先继承(竖向),新式类按广度优先继承 python3 新/旧式类按广度优先继承(横向) class School(object): def __init__(self,name,addr): self.name = name self.addr = addr self.students = [] self.tecacher = [] self.staffs = [] def enroll(self,stu): print ("为 %s 办理注册手续" % stu.name) self.students.append(stu) 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): print (".....") 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 teache %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 %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 print(\'\'\'info of student %s : name:%s age:%s sex:%s stuid:%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 %s" % (self.name,amount)) sh = School("胡北","黄冈") t1 = Teacher("freshman",23,"w",100,"linux") s1 = student("sa",23,"m",12321,54) #t1.teach() #t1.tell() sh.hire(t1) sh.enroll(s1) sh.staffs[0].teach() ###在上面sh.hire(t1)中继承了Teacher类,所以可以直接调用teach方法 for stu in sh.students: print (stu.name) s1.pay_tuition(5000)
打印结果: info of student sa : name:sa age:23 sex:m stuid:12321 grade:54 雇佣员工 freshman 为 sa 办理注册手续 freshman is teaching linux sa sa has paid 5000
类的方法
静态方法
class a1(object): def test_a1(self): print ("test_a1") @staticmethod #静态方法,使用静态方法,不用创建对象,self可不用填写,由类直接调用(相当于执行函数) def test_b1(): print ("test_b1") @staticmethod def test_b2(a,b): print("test_b2",a,b) a1.test_b1() a1.test_b2(1,2) #由类直接调用
property 属性
class a1(object): def test_a1(self): print ("test_a1") @property def test_b1(self): print ("test_b1") c = a1() c.test_b1 #创建对象后调用时不用加()
以上是关于面向对象的主要内容,如果未能解决你的问题,请参考以下文章