第五章节-面向对象
两种编程范式:面向过程编程和面向对象编程
面向过程
优点:复杂的问题流程化
缺点:
面向对象:核心就是对象二字,对象就是特征与技能的结合体
优点:可扩展性强
缺点:编程复杂程度高
应用场景:用户需求经常变化,互联网应用,游戏,企业内部应用
定义类与实例化出对象
名词解释:
类:一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型、模板。在类中定义了这些对象的都具备的属性(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