一、继承
1.1单继承
class Animal:
def eat(self):
print('吃饭')
pass
def drink(self):
pass
class dog(Animal):
def wwj(self):
print('汪汪叫')
class cat(Animal):
def mmj(self):
print('喵喵叫')
d1=dog()
d1.eat()#由于dog类继承了父类Animal,所以可以使用eat方法
将多个类共有的属性、方法提取出来作为一个父类去继承,可以减少代码量,提高开发效率。
1.2多继承
在单继承的基础上,同时继承多个父类就是多继承。
问题是当多个父类中存在相同方法时,应该去调用哪一个呢?
class A:
name='A'
def act(self):
print('使用的是%s的方法'%(self.name))
class B:
name='B'
def act(self):
print('使用的是%s的方法'%(self.name))
class C(A):
# def act(self):
# print('C的方法')
pass
class D(A,B):
pass
class E(C,B):
pass
d=D()
d.act()
print(d.name)
e=E()
e.act()
print(e.name)
print(E.__mro__)
当父类中存在相同的方法或属性时,程序会按深度优先去查找方法,也就是先找第一个父类,包括父类的父类,以此类推。找不到的话,再去找第二个父类,再找第二个父类的父类,以此类推……
找到方法后会直接执行,不会继续找了。
1.3方法覆盖
子类继承父类的方法时,可以覆盖覆盖父类的方法,这样在子类就不会继承父类的方法,在调用时会使用自己的方法。
class functionA:
def act(self):
print('functionA的方法')
class functionB(functionA):
def act(self):
print('functionB的方法')
class functionC(functionB):
pass
a=functionC()
a.act()
二、多态
介绍:即多种状态,也就是同一种行为,对于不同的子类对象有不同的行为表现。
特点:1.要想实现多态,则必须先要有继承
2.子类重写父类方法
总结一下就是,重写是多态的实现方式,多态是重写的表现形式。
class Person:
def say_who(self):
print('我是一个人')
class China(Person):
def say_who(self):
print('我是中国人')
class Japan(Person):
def say_who(self):
print('我是一个日本人')
def commonFunction(obj):
obj.say_who()
listObj=[China(),Japan()]
for item in listObj:
commonFunction(item)
优点:1.增加程序的灵活性
2.增加程序的扩展性
个人理解,多态其实是种思想。多态本身并不限制你要统一哪个接口或者继承哪个父类,只要你有统一的一类行为方式,这个行为方式的表现形式不同、实现过程如何并不需要关注,这就是多态。
二、私有化
2.1私有化属性
为了更好的保证属性的安全,可以将属性定义为私有属性,添加一个可调用的方法去访问。
私有化属性特点:
1.只能在类内部去访问,不能通过类对象或者实例对象去访问
2.不可以被继承
3.定义属性名字时以两个下划线开头,就是定义为私有属性
#使用私有属性的场景
#1.把特定的一个属性隐藏起来,不想让类的外部进行直接调用
#2.我想保护这个属性,不想属性的值随意的改变
#3.保护这个属性,不想让派生类(子类)去继承
class Person:
__hobby='编程'
def __init__(self):
self.__name='鹿鸣松'
self.age=25
def __str__(self):
return '{}喜欢{}'.format(self.__name,Person.__hobby)
class Student(Person):
pass
stu=Student()
print(stu)
# print(stu.__name)
# xl=Person()
# print(Person().age)
2.2私有化方法
私有化方法特点:
1.无法被子类继承
2.只能在类内部使用,无法通过类对象或者实例对象去调用
class Animal:
def __eat(self):
print('吃东西')
pass
class Cat(Animal):
def run(self):
print('跑')
pass
cat=Cat()
# cat.__eat()#没有继承eat方法
cat.run()
animal=Animal()
# animal.__eat()
# Animal.__eat()
2.3下划线说明
1.单下划线:_xxx前面加了一个下划线,以单下划线开头的表示是protected类型的变量,只允许本身和子类进行访问,不能使用from xxx import *的方式导入。
2.前后双下划线:__xxx__前后两个下划线,魔术方法,一般是python自带的
3.后单下划线:xxx_避免属性名和python关键字冲突
4.前面双下划线:__xxx类内部定义私有属性或私有方法
三、属性函数(property)
可以通过属性函数去让类对象或者实例对象,看上去是可以直接调用私有属性。
class Aniaml:
def __init__(self):
self.__name='大白'
def getName(self):
return self.__name
def setName(self,obj):
self.__name=obj
name=property(getName,setName)
animal=Aniaml()
animal.name='小白'
print(animal.name)
也可以通过装饰器去实现上述功能,但是需要注意的是被装饰的两个方法名字需要映射到对应的私有属性上
class Aniaml:
def __init__(self):
self.__name='大白'
@property #使用装饰器修饰,添加属性标志,提供一个getter方法
def name(self):
return self.__name
@name.setter
def name(self,obj):
self.__name=obj
# name=property(getName)
animal = Aniaml()
print(animal.name)
animal.name='小白'
print(animal.name)
四、单例模式
#是一种常用的软件设计模式,确保某一个类只有一个实例存在
#如果希望在整个系统中,某个类只能出现一个实例的时候,那么这个单例对象就能满足要求
#创建一个单例对象,基于__new__去实现,这是一种比较推荐的方式
class DataBaseClass(object):
def __new__(cls, *args, **kwargs):
# cls._instance=cls.__new__(cls) 不能使用自身的new方法,容易造成一个深度递归,造成死循环,应该调用父类的new方法
if not hasattr(cls,'_instance'):#如果不存在此对象才能创建
cls._instance=super().__new__(cls)
return cls._instance
class DBoptSingle(DataBaseClass):
pass
db1=DataBaseClass()
print(id(db1))
db2=DataBaseClass()
print(id(db2))
db3=DBoptSingle()
print(id(db3))
db4=DBoptSingle()
print(id(db4))
五、异常处理
5.1python中已有的异常处理
#except在捕获错误异常的时候,需要根据具体的错误类型来捕获的
# try:
# print(a)
# li=[1,2]
# print(li[10])
# a=10/0
# except NameError as msg:
# #捕获到的错误,才会在这边执行
# print(msg)
# pass
# except IndexError as msg:
# print(msg)
# except ZeroDivisionError as msg:
# print(msg)
#万能异常捕获,当对于出现问题或者错误不确定的情况下,可以使用Exception去捕获
# except Exception as msg:
# print(msg)
#在这边尽量处理掉异常,不然做这个异常捕获意义不大
# print('异常处理')
#不需要在每个可能出现错误的地方去捕获,只要在合适的层次去捕获错误就行,这样就可以减少代码量
def A(s):
return 32/int(s)
def B(s):
print(A(s)*4)
def main():
try:
B(2)
except Exception as msg:
print(msg)
main()
#如果程序发生异常,解释器会查找相应的异常捕获类型;如果没在当前函数中找到,它会将异常传递给上层的调用函数,看能否处理
#如果在最外层都没找到,解释器就会退出
try:
# print(a)
print('正确执行代码')
except Exception as msg:
print(msg)
else:
print('当try里的代码没有异常的情况下,才会执行else里的代码')
finally:
print('不管有没有捕获到错误,都会去执行')
5.2自定义异常
class ToolongMyException(Exception):
def __init__(self,leng):
self.leng=leng
def __str__(self):
return '输入的数据长度是'+str(self.leng)
def name_Test():
name=input('请输入姓名')
try:
if len(name)>4:
raise ToolongMyException(len(name))#raise是自定义异常的关键字
else:
print(name)
except ToolongMyException as msg:#这边捕获到自己定义的异常错误,然后打印错误信息
print(msg)
name_Test()
六、动态添加属性和方法
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '{}今年{}岁了'.format(self.name,self.age)
lms=Student('鹿鸣松',25)
lms.hobby='编程'#动态添加这个实例属性,归lms这个实例所有
print(lms.hobby)
Student.weight=120#动态去添加这个类属性,归类所有
print(Student.weight)
import types#动态添加实例方法的库
def dymicMethod(self,obj):
print('这是一个动态添加的方法')
print(obj)
lms.printFunction=types.MethodType(dymicMethod,lms)
lms.printFunction(lms)
#绑定类方法
@classmethod
def dymicClassTest(self):
print('这个是动态绑定的类方法')
Student.TestMethod=dymicClassTest
Student.TestMethod()
#绑定静态方法
@staticmethod
def staticMethodTest():
print('这是一个动态绑定的静态方法')
Student.TestStaticMethod=staticMethodTest
Student.TestStaticMethod()
七、__slots__属性
规则:
1.在限制实例属性之后,在限制以外的实例属性不允许被添加
2.子类未声明__slots__时,那么是不会继承父类的__slots__的,此时子类是可以随意的对实例属性赋值的。
3.当子类声明__slots__时,那么会继承父类的__slots__,也就是子类的__slots__范围是自身+父类的__slots__
class Student(object):
__slots__ = ('name','age')#只允许添加name和age这两个实例属性
# def __init__(self):
# # self.weight=60
# self.hobby='打游戏'
def __str__(self):
return '{}今年{}岁'.format(self.name,self.age)
pass
xw=Student()
xw.name='小王'
xw.age=20
# print(xw.__dict__)#所有的可用属性都存储在这里,不足的地方就是占用内存空间大
#但是在定义slots变量之后,不允许再随意创建不在slots中定义的实例属性,同时__dict__也不再有了
print(xw)
# xw.hobby='打游戏'#无法添加hobby这个属性,因为没有在限制属性里
class subStudent(Student):
__slots__ = ()
lyn=subStudent()
# lyn.hobby='打游戏'#这个属性没有被允许添加,所以会报错
lyn.name='李艳楠'
print(lyn.name)