第五章节-面向对象
两种编程范式:面向过程编程和面向对象编程
面向过程
优点:复杂的问题流程化
缺点:
面向对象:核心就是对象二字,对象就是特征与技能的结合体
优点:可扩展性强
缺点:编程复杂程度高
应用场景:用户需求经常变化,互联网应用,游戏,企业内部应用
定义类与实例化出对象
名词解释:
类:一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型、模板。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
类就是一系列对象相似的特征与技能的结合体
如何使用类?
类在定义的时候就产生了名称空间
#先定义类
class Luffstudent:
school ='luffcity'
def learn(self):
print('is learning')
def learn(self):
print('is sleeping')
#查看类的名称空间
print(Luffstudent.__dict__)
特征用变量表示
技能用函数表示
类的增删改查
#定义类
class ldddd:
school = "luff" #类的数据属性
def learn(self):#函数属性
print("is learning")
#查看类的名称空间
# print(ldddd)
# print(ldddd.__dict__['school'])
# print(ldddd.__dict__['learn'])
# print(ldddd.school) #ldddd.__dict__['school']
# print(ldddd.learn) #ldddd.__dict__['learn']
#增加
ldddd.county ='china'
print(ldddd.__dict__)
print(ldddd.county) #访问属性的语法
#删掉
# del ldddd.county
# print(ldddd.__dict__)
# print(ldddd.county)
#改
ldddd.school = 'LAFF'
print(ldddd.__dict__)
属性:人类包含很多特征,把这些特征用程序来描述的话,叫做属性,比如年龄、身高、性别、姓名等都叫做属性,一个类中,可以有多个属性
方法:人类不止有身高、年龄、性别这些属性,还能做好多事情,比如说话、走路、吃饭等,相比较于属性是名词,说话、走路是动词,这些动词用程序来描述就叫做方法。
实例(对象):一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
实例化:把一个类转变为一个对象的过程就叫实例化
先定义类
#造类的语法:class
后产生对象
如何使用对象?
__init__方法用来为对象定制对象自己独有的特征
class Luffcitystudent: school = 'luffcity' #数据属性 def __init__(self,name,sex,age): self.Name = name self.Sex = sex self.Age = age def learn(self): #函数属性 print('is learning') def eat(self): print('is sleeping') stu1 = Luffcitystudent('王二丫','女',30) print(Luffcitystudent.__init__)
输出
<function Luffcitystudent.__init__ at 0x0000000001E33288>
加上_init_方法后,实例化的步骤
#1 先产生一个空对象stu1
#2 Luffcitystudent('stu','王二丫','女',30)
class Luffcitystudent: school = 'luffcity' #数据属性 def __init__(self,name,sex,age): self.Name = name self.Sex = sex self.Age = age def learn(self): #函数属性 print('is learning') def eat(self): print('is sleeping') stu1 = Luffcitystudent('王二丫','女',30) print(Luffcitystudent.__init__) print(stu1.__dict__) #查 print(stu1.Name) print(stu1.Sex) print(stu1.Age) #改 stu1.Name = '李二丫' print(stu1.__dict__) print(stu1.Name) #增 stu1.class_name = "python开发" print(stu1.__dict__) print(stu1.class_name) #删 del stu1.class_name print(stu1.__dict__)
属性查找
#类中的函数属性:是绑定给对象使用的,绑定不到不同的对象是不同的绑定方法,对象调用绑定方法时,会把对象本身当做一个参数传入,传给self class Luffcitystudent: school = 'luffcity' #数据属性 def __init__(self,name,sex,age): self.Name = name self.Sex = sex self.Age = age def learn(self): #函数属性 print(' %s is learning' %self.Name) def eat(self): print('is sleeping') #后产生对象 stu1=Luffcitystudent('王二丫','女',18) stu2=Luffcitystudent('李三炮','男',38) stu3=Luffcitystudent('张铁蛋','男',48) #对象:特征与技能的结合体 #类:类是一系列对象相似特征与相似技能的结合体 #类中的数据属性:是所有对象共有的 print(Luffcitystudent.school,id(Luffcitystudent.school)) print(stu1.school,id(stu1.school)) print(stu2.school,id(stu2.school)) print(stu3.school,id(stu3.school)) #类中的函数属性:是绑定给对象使用的,绑定不到不同的对象是不同的绑定方法,对象调用绑定方法时,会把对象本身当做一个参数传入,传给self print(Luffcitystudent.learn) Luffcitystudent.learn(stu1) Luffcitystudent.learn(stu2) Luffcitystudent.learn(stu3)
继承
#属性的查找方法 class Foo: def f1(self): print('from Fpp.f1') def f2(self): print('from Foo.f2') self.f1() class Bar(Foo): def f1(self): print('from Bar.f1') b=Bar() b.f2()
输出结果
from Foo.f2 from Bar.f1
继承与重用性
派生
子类也可以添加自己新的属性或者在自己这了重新定义这些属性(不会影响到父类)
***一旦重新定义了自己属性且与父类重名,那么调用新增的属性时,就以自己为准了。
class hero: def __init__(self,name,life_value,agg): self.name = name self.life_value = life_value self.agg =agg def attack(self,enemy): enemy.life_value -=self.agg class Garem(hero): camp = 'dem' #派生出属性 def attack(self,enemy): print('from Garem class') class Riven(hero): camp = 'Nox' g = Garem('CAO',100,30) r = Riven('RUIWENWEN',80,50) print(g.camp) g.attack(r) #print(g.life_value)
继承的实现原理
遵循的原则
- 子类会先于父类被检查
- 多个父类会根据它们在列表中的顺序被检查
- 如果对下一个类存在两个合法的选择,选择第一个父类
#经典类 #新式类 python3中默认都继承,一个类没有继承object类,默认就继承object类 #验证多继承的情况下属性查找 class A(): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class E(C): def test(self): print('from E') class D(B): def test(self): print('from D') class F(D,E): def test(self): print('from F') f = F() f.test() print(F.mro())
mro可以查找属性的查找顺序以列表的形式展示出来
多继承的情况下就按照mro展示的顺序查找,即广度优先
组合
给一个对象赋予一个属性,指向了另外一个对象
class People: school = 'luffycity' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex class teacher(People): def __init__(self,name,age,sex,level,salary): super().__init__(name,age,sex) self.level = level self.salary = salary def teach(self): print('%s is teaching ' %self.name) class student(People): school = 'luffycity' def __int__(self,name,age,sex,class_time): super().__init__(name,age,sex) self.class_time = class_time def learn(self): print('%s is learning' %self.name) class cour: def __init__(self,cour_name,cour_price,cour_time): self.cour_name = cour_name self.cour_price = cour_price self.cour_time = cour_time def tell_info(self): print('课程名<%s> 课程价钱<%s> 课程周期<%s>' %(self.cour_name,self.cour_price,self.cour_time)) python = cour('python',3000,'4mons') linux = cour('linux',4000,'5mons') tea1 = teacher('alex',18,'male',10,3000) stu1 = student('张三',28,'male') tea1.cour = python stu1.cour = python stu1.cour1 = linux tea1.cour.tell_info() stu1.cour1.tell_info()
抽象类
的的的
多态与多态性
的的
鸭子类型
的的
封装之如何实现属性的隐藏
在类定义阶段已经实现变形,且只在类定义阶段才会变形,类定义之后不会变形
这种变形的特点:
1.在类外部无法直接obj._AttrName
2.在类内部可以直接使用obj._AttrName
3.子类无法覆盖父类__开头的属性
class Foo: def __func(self):#变形后_Foo__func(self) print('from Foo') class Bar(Foo): def __func(self):#变形后_Bar__func(self) print('from Bar') b = Bar() b._Bar__func()
封装的意义
1.封装数据属性:明确区分内外,控制外对隐藏的属性的操作行为
class People:
def __init__(self,name,age):
self.__name = name
self.__age = age
def tell_info(self):
print('name:<%s> age:<%s>' %(self.__name,self.__age))
'''
定制一个接口,通过接口去访问隐藏的数据属性
'''
def set_info(self,name,age):
self.__name = name
self.__age = age
'''
如果想修改数据的输入名称,则需要另外定制一个接口
通过接口实现
'''
p = People('alex',18)
p.set_info('hjj',30)
p.tell_info()
2.封装方法:隔离复杂度
class ATM: def __card(self): print('插卡') def __auth(self): print('用户认证') def __input(self): print('输入取款金额') def __print_bill(self): print('打印账单') def __take_money(self): print('取款') def withdraw(self): self.__card() self.__auth() self.__input() self.__print_bill() self.__take_money() a=ATM() a.withdraw()
封装与扩展性
property的使用
class People: def __init__(self,name): self.__name = name def name(self): return self.__name p = People('egon') p.name() print(p.name())
class People: def __init__(self,name): self.__name = name @property def name(self): return self.__name p = People('egon') p.name print(p.name)
绑定方法与非绑定方法
在类内部定义的函数,分为两大类
一、绑定方法
绑定给谁,就应该由谁来调用,谁来调用就回把调用者当做第一个参数自动传入
①绑定给对象
在类定义的没有被任何装饰器修饰的
②绑定给类
在类定义的有被装饰classmethod修饰的方法
二、非绑定方法
@staticmethod
没有自动传值这么一说了,就类中定义的一个普通工具,对象和类都可以使用
非绑定方法:不与类或者对象绑定
绑定给对象:
class Foo: def __init__(self,name): self.name = name def tell(self): print("名字是%s" %self.name) f = Foo('egon') f.tell()
绑定给类
class Foo: def __init__(self,name): self.name = name def tell(self): print("名字是%s" %self.name) @classmethod def func(cls): print(cls) f = Foo('egon') Foo.func()
非绑定方法:
class Foo: def __init__(self,name): self.name = name def tell(self): print("名字是%s" %self.name) @classmethod def func(cls): print(cls) @staticmethod def func1(x,y): print(x+y) f = Foo('egon') Foo.func1(1,2) f.func1(3,5)
绑定方法与非绑定方法的使用
import settings import hashlib import time class People: def __init__(self,name,age,sex): self.id=self.create_id() self.name=name self.age=age self.sex=sex def tell_info(self): #绑定到对象的方法 print('Name:%s Age:%s Sex:%s' %(self.name,self.age,self.sex)) @classmethod def from_conf(cls): obj=cls( settings.name, settings.age, settings.sex ) return obj @staticmethod def create_id(): m=hashlib.md5(str(time.time()).encode('utf-8')) return m.hexdigest() # p=People('egon',18,'male') #绑定给对象,就应该由对象来调用,自动将对象本身当作第一个参数传入 # p.tell_info() #tell_info(p) #绑定给类,就应该由类来调用,自动将类本身当作第一个参数传入 # p=People.from_conf() #from_conf(People) # p.tell_info() #非绑定方法,不与类或者对象绑定,谁都可以调用,没有自动传值一说 p1=People('egon1',18,'male') p2=People('egon2',28,'male') p3=People('egon3',38,'male') print(p1.id) print(p2.id) print(p3.id)
反射
class people: def __init__(self,name,age): self.name = name self.age = age def talk(self): print('%s is talking ' %self.name) obj = people('egon',18) print(obj.__dict__) print(hasattr(obj,'name')) print(hasattr(obj,'talk')) print(hasattr(obj,'talk1')) print(getattr(obj,'name')) print(getattr(obj,'talk')) setattr(obj,'sex','male') print(obj.sex) print(obj.__dict__) delattr(obj,'age') print(obj.__dict__)
hasattr
getattr
setattr
delattr