文章目录
前言
python中的函数式编程和面向对象编程
函数式编程:方法(函数)
面向对象编程:类
功能 : python中,面向对象编程能实现的,函数式编程也基本能都实现
面向对象编程适用:当多个函数有多个相同参数时,使用面向对象编程更为方便
一、类的创建和基本调用方式
class student: #声明一个学生类
def __init__(self,name,age): #构造方法(创建类的对象时自动执行)
self.name = name #普通字段
self.age = age
def stu_show(self):
print('%s - %s岁'%(self.name,self.age))
def ret(self): #普通方法
print('这是一个学生类')
def __del__(self): #析构方法:对象被销毁时,自动调用
print('析构方法')
stu = student('小明',17) #创建一个类的对象
stu.ret() #中间人(stu)调用类中方法
stu.stu_show()
声明的类默认继承object类
self : 可以理解为是指调用方法的对象,即上述的:stu
证明self:
class person:
def show(self,num):
print(self,num) #验证self地址
p1 = person()
print(p1)
p1.show(32)
#输出:
<__main__.person object at 0x0000022F07486700> #地址相同
<__main__.person object at 0x0000022F07486700> 32
1.对象存数据 (对象向类内传入数据)(封装)
class student:
def __init__(self,name,age):
self.name = name
self.age = age
def show(self):
print(self.name,self.age,self.hobby)
stu = student('小明',19)
stu.hobby = 'girl' #对象存数据
stu.show()
#输出:
小明 19 girl
二、面对对象三大特性简述
1.封装
class teacher:
def __init__(self,name,course):
self.name = name
self.course = course
teacher1 = teacher('王刚','高数') #这是利用__init__()方法进行封装
teacher1.hobby = '篮球' #这是封装
teacher2 = teacher('王李安','英语')
teacher2.hobby = '冲浪'
2.继承
继承运用: 不修改原类,为其添加新功能
代码编写应当遵循:开发封闭原则(修改禁止,添加扩展允许)
重写,超级
class father:
def f(self):
print('这是父方法')
def m(self):
print('父方法2')
class son(father):
def f(self): #重写:父类含有的方法,在子类内再次编写
print('父方法重写')
def function(self):
super(son,self).f() #重写后,想要调用父类方法:super():超级(超集)
father.f(self) #与super效果相同,但是推荐用super
son1 = son()
son1.f() #类内有的方法将优先调用类内
son1.m() #继承至父类的m()方法
son1.function()
#输出:
父方法重写
父方法2
这是父方法
这是父方法
python中的多继承
class father:
def show(self):
print('父1')
class father2:
def show(self):
print('父2')
class son(father2,father):
pass
son1 = son()
son1.show()
#输出:
父2
1.多继承中,父类没有继承爷爷类,子类继承多个父类时,调用父类中相同的方法,将默认从继承左端的第一个父类开始寻找。
图例:
2.多继承中,父类继承不同的爷爷类,爷爷类继承不同的祖父类,子类继承多个父类时,子对象调用继承方法,将默认从继承左端第一个父类开始寻找,接着找完该父类所有爷爷和祖父类,再开始找下一个父类,以此类推。
图例:
3.多继承中,父类继承不同的爷爷类,爷爷类继承同一个祖父类,子类继承多个父类时,子类对象调用继承方法,将默认从继承左端第一个父类开始寻找,找到该父类的爷爷类时截止,接着找下一个父类,同样找到爷爷类时截止,直到找到最后一个父类时,才找祖父类,即:根类放在最后查找
图例:
额外增加一点:
class father:
def show(self):
print('父1')
def ret(self):
self.show() #父类内调用show()方法,父类1和父类2都含有show方法,那么将调用哪个呢?
class father2:
def show(self):
print('父2')
class son(father2,father):
pass
son1 = son()
son1.show()
son1.ret()
#输出:
父2 #时刻记住,self指的是调用方法的对象,而此时self指代son1,也就是son类,而son类中,先继承父类2,才继承父类1,所以将调用父类2中的show方法
父2
3.多态
多态可以理解为定义多种数据类型,整型(int),字符型(string)等等。
在c,c++,java中,定义一个变量时,需要说明它的数据类型,而在python中,解释器将会根据运用自动判断其数据类型。
即:原生多态
三、字段和方法
1.字段
class ret:
hobby = '网游' #静态字段,数据保存在类中,可以通过对象和类调用
def __init__(self,name):
self.name = name #普通字段,数据保存在对象中,只能通过对象调用
son1 = ret('小明')
son1.name = '小刚'
ret.hobby #son1.hobby
2.方法
class test:
def ret1(self): #普通方法
print('没想到吧?')
@staticmethod #静态方法,由类直接调用
def ret2(): #静态方法中,self将不再必须,即可以删掉self后,不传入参数,也可以自主定义传入参数
print('这是静态方法')
t1 = test()
t1.ret1() #对象调用普通方法 无论哪种调用方法,都需先创建一个对象
test.ret1(t1) #类调用普通方法
test.ret2() #类直接调用静态方法,不用传入对象
四、property,.setter,.deleter装饰器(为类的方法添加属性:三种调用方式)
1.
class test:
def ret1(self):
print('没想到吧?')
@property
def ret2(self): #对应:t1.ret2
print('这是伪造成字段的方法')
@ret2.setter
def ret2(self,num): #对应:t1.ret2 = 5
print('这是方法2 num:%s'%num)
@ret2.deleter
def ret2(self): #对应:del t1.ret2
print('这是第三种调用方式')
t1 = test()
t1.ret2
t1.ret2 = 5
del t1.ret2 #为调用同一函数名的不同方法,提供了三种不同的调用方式,这里的del将不代表删除,而是用来表示一种方法的调用形式,
#输出:
这是伪造成字段的方法
这是方法2 num:5
这是第三种调用方式
2.简化(效果等同)
class seted:
def f1(self):
print('方法 1')
def f2(self,num):
print('方法 2 num:%s'%num)
def f3(self):
print('方法 3')
ret1 = property(fget=f1,fset=f2,fdel=f3)
#ret1 = property(f1,f2,f3)
set1 = seted()
set1.ret1
set1.ret1 = 4
del set1.ret1
#输出:
方法 1
方法 2 num:4
方法 3
五、类中的私有变量和私有方法
class student:
def __init__(self, name, age):
self.name = name
self.__age = age # 在变量名前加上 __(两个下划线),即使变量成为类中私有,类外将不能直接调用
def __function(self): #__<方法名> :私有方法
print("这是私有方法")
def function_show(self): #类内可以调用私有方法
self.__function()
def show(self): #类内可以调用私有变量
print('私有变量__age = %s' % self.__age)
stu1 = student('小明', 17)
print(stu1.name)
#print(stu1.__age) #报错,找不到变量__age
stu1.show() #对象通过类内的方法,调用私有变量
#stu1.__function() #报错,找不到方法__function()
stu1.function_show() ##通过类内方法调用私有方法
#输出:
小明
私有变量__age = 17
这是私有方法
提要 :继承中,子类无法直接调用父类的私有变量和私有方法。
六、类的深入(特殊成员)
1. call与类的对象()
lass student:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('这是call方法')
stu1 = student()
stu1() #在类对象后加上()括号,将自动调用类中的call方法
#输出:
这是call方法
2.int(),str()…与类
class student:
def __init__(self):
pass
def __int__(self):
return 4
stu1 = student()
stu1 = int(stu1) #调用类中的__int__方法,并取得返回值
print(stu1)
#输出
4
class student:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return '%s %s'%(self.name,self.age)
stu1 = student('小明',18)
print(stu1) #相当于print(str(stu1)) 调用类中的__str__方法并返回
#输出:
小明 18
3.__dict__方法 (重要)
__dict__方法:将类或对象中的数据制作成字典,并返回
class student:
def __init__(self,name,age):
self.name = name
self.age = age
self.hobby = 'pcgame'
stu1 = student('小明',18)
f = stu1.__dict__ #将对象中的数据制作成字典
#student.__dict__ #将类中的数据制作成字典并返回
print(f)
#输出:
{'name': '小明', 'age': 18, 'hobby': 'pcgame'}
4.1:__getitem____setitem____delitem 特殊成员方法
class student:
def __init__(self):
self.hobby = 'pcgame'
def __getitem__(self, item):
print('还是方法:item:%s'%item)
return item+1000
def __setitem__(self, key, value):
print(key,value)
def __delitem__(self, key):
print(key)
stu1 = student()
s = stu1[800] #在类的对象后加上一个[]中括号,填上参数,将默认执行类中的__getitem__方法,并传入参数,有返回值
print(s)
stu1[1000] = '这就是第二种方法' #默认执行类中__setitem__方法,没有返回值
del stu1[600] #默认执行类中__delitem__方法,没有返回值
#输出:
还是方法:item:800
1800
1000 这就是第二种方法
600
4.2 : 特殊成员getitem之:对象[ ] 切片与索引
class student:
def __init__(self):
self.hobby = 'pcgame'
def __getitem__(self, item):
print('还是方法:item:%s'%item)
if type(item) == slice:
print('切片处理')
print(item.start)
print(item.stop)
print(item.step)
else:
print('索引处理')
def __setitem__(self, key, value):
print(key,value)
def __delitem__(self, key):
print(key)
stu1 = student()
stu1[800] #在类的对象后加上一个[]中括号,填上参数
stu1[1:5:4] #默认数据类型:slice
#输出:
还是方法:item:800
索引处理
还是方法:item:slice(1, 5, 4)
切片处理
1
5
4
5.类的声明–type
# class student: #声明一个类
# def show(self):
# pass
student = type('student',(object,),{'show1':lambda x:5}) #这也是声明了一个类
stu = student()
print(stu.show1())
#输出:
5
!!! 说明类在创建时使用了解释器内部默认的type类 !!!
那么我们可以利用继承,为type添加新功能,使得我们每次创建类时,都会调用该新功能
class mytype(type):
def __init__(self,*args,**kwargs):
print('添加新功能')
class student(object,metaclass=mytype):
def __init__(self):
pass
def show(self):
print('123')
#无需对象,默认自动调用type(mytype):
添加新功能
6.深入了解类在创建对象时,默认自动执行__init__方法的原理
class mytype(type):
def __init__(self,*args,**kwargs): #步骤二
pass #或者super().__init__() :执行父类的__init__()方法
def __call__(self, *args, **kwargs): #self:student
stu = self.__new__() #步骤四
self.__init__(stu) #步骤六
class student(object,metaclass=mytype): #步骤一
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
return object.__new__(cls) #真正的创建对象 #步骤五
stu = student() #创建对象 #步骤三
步骤分析:
第一阶段:class student: #声明一个类
1.声明一个类时,首先将默认调用解释器中的type方法或上述继承至type的mytype方法中的__init__()方法。
第二阶段:stu = student() #创建一个类的对象
1.创建一个类的对象时,将会默认调用解释器中的type方法或上述继承至type的mytype方法中的__call__()方法。
2.调用__call__()方法中,对象self(此时的self是类:student)中的__new__()方法
3.类中的__new__()方法将会调用:object.__new__() 创建一个真正的类的对象,并返回对象数据给type或上述mytype中__call__方法中的stu
4.最后调用type或上述mytype中的__call__()方法中的self.__init__(stu),即调用声明的类中的__init__()方法,并将对象stu作为参数传入