写在前面:笔记全部是跟着老师一起敲的代码,最近电脑瓦特了,所以只能用老爷机的日记本记下老师上课讲的东西,但我运行不了
特别感谢的是xx学院的的刘老师,我都是边看他的课,边学他一起敲代码,然后晚上自己看,自己理解,感谢老师。
-单继承和多继承:
-单继承:每个类智能继承一个类
-多继承:每个类允许继承多个类
-单继承和多继承的优缺点:
-单继承
-优点:传承有序逻辑,清晰,语法简单,隐患少
-缺点:功能不能无限扩展,只能在当前唯一的继承链中扩展
-多继承
-优点:类的功能扩展方便
-缺点:继承关系混乱
#例:
#子类而已直接拥有父类的属性和方法,私有的除外
class Fish():
def __init__(self,name):
self.name = name
def swim(self):
print("i am swimming")
class Bird():
def __init__(self,name):
self.name = name
def fly(self):
print("i am flying")
class Preson():
def __init__(self,name):
self.name = name
def working(self):
print("i am working")
class SuperMan(Person,Bird,Fish):
def __init__(self,name):
self.name = name
s = SuperMan(siqi)
s.fly()
s.swim()
-菱形继承/砖石继承的问题,很难,是多继承的问题
-多个子类继承同一个父类,这些子类由被同一个类继承,浴室继承关系图形成一个菱形图谱
-关于多继承的MRO
-MRO就是多继承中,用于保存继承顺序的一个列表
-python本省采用C3算法来计算并得到结果
-MRO列表的计算原则:
-子类永远在父类前面
-如果多个父类,则根据继承语法括号类的书写顺序存放
-如果多个类继承同一个父类,孙子类中只会选取继承语法括号中第一个父类的父类
例:
class A():
pass
class B(A):
pass
class C(A):
pass
class D(B,C):
pass
-构造函数
-在对象进行实例化的时候,系统自动调用一个函数叫做构造函数,通常此函数用来对实例对象进行初始化工作
-构造函数一定要有,如果没有,则会自动向上查找
#构造函数例子:
class Person():
#对Person类进行实例化的时候
#姓名要确定
#年龄得确定
#地址得确定
def __init__(self):
self.name = "NO name"
self.age = 19
self.address = "dormitory"
pass
#实例化一个人
p = Person()
#构造函数的调用顺序-1
#如果子类没有写构造函数,则会按照MRO的顺序自动向上查找,一直找到为止
class A():
def __init__(self):
print("A")
class B():
DEF __init__(self):
print("B")
class C(B):
pass
c = C()
#构造函数的调用顺序-2
#如果子类没有写构造函数,则会按照MRO的顺序自动向上查找,一直找到为止
class A():
def __init__(self):
print("A")
class B():
DEF __init__(self):
print("B")
print(name)
class C(B):
#C中想扩展B的构造函数,即电泳B的构造函数后再添加一些功能
#第一种方法:通过父类名调用
def __init__(self,name):
#首先调用父类构造函数
B.__init__(self,name)
#其次,增加自己的功能
print("这是C添加的新功能")
#第二种方法,使用super调用
def __init__(self,name):
#首先调用父类构造函数
super(C,self).__init__(name)
#其次,增加自己的功能
print("这是C添加的新功能")
pass
c = C(“我是C”)
#3.3多态
-多态就是同一个对象在不同情况下以不同的状态出现
-多态不是语法,是一种设计思想
-多态性:一种调用方式,不同的执行效果
-多态:同一事物的多重形态,如动物分为人类、狗类、鱼类、鸟类
-Mixin设计模式
-主要采用多继承方式对类的功能进行扩展
-关于其概念,可以看看别的大牛写的博客,写的很好。
-使用多继承语法来实现Mixin
-使用Mixin实现多继承时要非常小心
-首先他表示某单一功能,而不是变成了某物
-职责必须单一,如果有多个功能,则要写多个Mixin
-Mixin不能依赖子类的实现
-子类即时没有继承这个Mixin类,也能照样工作,只是缺少了某个功能
-优点:
-使用Mixin可以在不对类进行任何修改的情况下,扩充功能
-可以方便的组织和维护不同功能组件的划分
-可以根据需要任意调整功能类的组合
-可以避免创建很多的类,导致类的继承混乱
#Mixin的例子
class Person():
name = "siqi"
age = 18
def eat(self):
print("Eat")
def drink(self):
print("Drink")
def sleep(self):
print("Sleeping")
class TeacherMixin():
def work(self):
print("Work")
class StudentMixin():
def work(self):
print("Study")
class TutorM(Person,TeacherMixin,StudentMixin):
pass
tt = TutorM()
print(TutorM.__mro__)
print(tt.__dict__)
print(TutorM.__dict__)
#4、类相关函数
-issubclass:检测一个类是否是另一个类的子类
class A():
pass
class B(A):
pass
class C():
pass
print(issubclass(B,A))#True
print(issubclass(C,A))#False
print(issubclass(C,object))#True,在python中,所有的类都是object的子类
-isinstance:检测一个对象是否是一个类的实例
class A():
pass
a = A()
print(isinstance(a,A))
-hasattr:检测一个对象是否有成员xx
class A():
name "NoNname"
a = A()
print(hasattr(a,"name"))
-dir:获取对象的成员列表
例子:
class A():
pass
a = A()
dir(a)
#5、类的成员属性
-类的成员描述符是为了在类中对类的成员属性进行相关操作而创建的一种方式
-get:获取属性
-set:修改或者添加属性的操作
-delete:删除属性的操作
-如果想使用类的成员描述符,有三种方法
-使用类实现描述器
-使用属性修饰符
-使用property函数(很简单)
-property(fget,fset,fdel,doc)
#属性案例
#创建Studengt类,描述学生类
#学生具有Student.name属性
#但name格式并不统一
class Student():
def __init__(self,name,age):
self.name = name
self.age = ahe
#介绍下自己
def intro(self):
print("my name is {0}".format(self.name))
def setName(self.name):
self.name = name.upper()
s1 = Student("siqi",18)
s2 = Student("houzi Xu",20)
s1.tro()
s2.tro()
#property案例
#定义一个Person类,具有name,age属性
#对于任意输入的姓名,我们希望都用大写保存
#对于任意输入的年龄,我们希望用整数保存
#property(fget,fset,fdel,doc)
class Person():
def fget(self):
return self._name*2
def fset(self,name):
self._name = name.upper()
def fdel(self):
self.name = "NoName"
name = property(fget,fset,fdel,"对name进行下操作")
p1 = Person()
p1.name = "siqi"
print(p1._name)
#6、类的内置属性
__dict__:以字典的方式显示类的成员组成
__doc__:获取类的文档信息
__name__:获取类的名称,如果再模块中使用,获取模块的名称
__bases__:获取某个类的所有父类,与元组方式显示
print(Person.__dict__)
#7、类的常用魔术方法
-魔术方法就是不需要人为调用的方法,基本是在特定的时刻自动触发
-魔术方法的统一特征,方法名被前后各两个下划线包裹
-操作类
#__init__:构造函数
例:
class A():
def __init__(self,name = 0):
print("魔法函数被调用“)
a = A()
#__new__:对象实例化方法,此函数叫特殊,一般不需要使用
#__call__:对象当函数使用时触发
例
class A():
def __call__(self):
print("魔方函数又被调用")
a()
#__str__:当对象被当做字符串使用时触发
例
class A():
def __str__(self):
print("魔法函数被调用“)
a = A()
print(a)
#__repr__:返回字符串,跟str有少许区别
-描述符相关
__set__
__get__
__delete__
-属性操作相关
__getattr__:访问一个不存在的属性时触发
#例
class A():
name = "NoName"
age = 18
def __getattr__(self,name):
print("没找到")
print(name)
a = A()
print(a.name)
print(a.addr)
__setattr__:对成员属性进行设置的时候触发
-参数:
-self用来获取当前对象
-被设置的属性名称,以字符串形式出现
-需要对属性名称设置值
-作用:进行属性设置的时候进行验证或者修改
-注意:在该方法中不能对属性直接进行赋值操作,否则进入死循环
#例
class Person():
def __init__(self):
pass
delf __setattr__(self,name,value):
print("设置属性:{0}".format(name))
#下面语句会导致问题,死循环
self.name = value
#为了避免死循环,规定统一调用父类魔法函数
super().__setattr__(name,value)
p = Person()
print(p.__dict__)
p.age
-运算类相关魔术方法
__gt__:进行大于判断的时候触发的函数
-参数:
-self
-第二个参数是第二个对象
-返回值可以是任意值,推荐返回布尔值
#例
class Student():
def __init__(self,name):
self._name = name
def __gt__(self,obj):
print("{0}大于{1}".format(self.obj))
return self._name > obj._name
stu1 = Student("one")
stu2 = Student("two")
print(stu1 > stu2)
#8、类和对象的三种方法:
-实例方法:
-需要实例化对象才能使用的方法
-静态方法:
-不需要实例化,通过类直接访问
-类方法
-不需要实例化
#案例
class Person:
#实例方法
def eat(self):
print(self)
print("Eating")
#类方法:第一个参数,一般命名为cls,区别于self
def play(cls):
print(cls)
print("Playing")
#静态方法:#不需要用第一个参数表示自身或者类
def say():
print("Saying")
siqi = Person()
#实例方法
siqi.eat()
#类方法
siqi.play()
#静态方法
siqi.say()
#变量的三种用法
class A(): def __init__(self): self.name = "haha" self.age = 18 a = A()
#属性的三种用法
1、赋值
2、读取
3、删除
a.name = "siqi"
print(a.name)
del a.name
#类属性 property
#应用场景:对变量除了普通的三种操作,还想增加一些附加的功能,可以通过property完成
class A():
def __init__(self):
self.name = "haha"
self.age = 18
#此功能,是对类变量进行读取操作的时候应该执行的函数功能
def fget(self):
print("读取")
return self.name
#模拟的是对变量进行写操作的时候执行的功能
def fset(self,name):
print("写入")
self.name = "siqi"+name
#模拟的是删除变量的时候进行的操作
def fdel(self):
pass
#默认调用下面四个中的第一个函数
name2 = property(fget,fset,fdel,"property举例")
a = A()
print(a.name)
print(a.name2)
#10、抽象类
-抽象方法:没有具体实现内容的方法称为抽象方法
-抽象方法规范了子类的行为和接口
-抽象类的使用需要借助abc模块
import abc
-抽象类:包含抽象方法的类叫抽象类,通常称为ABC类
抽象类的使用
-抽象类可以包含抽象方法,也可以包含具体方法
-抽象类中有方法也可以有属性
-抽象类不允许实例化
-必须继承才可以使用,且继承的子类必须实现所有继承来的抽象方法
-抽象类的作用是设定类的标准,以便于开发的时候具有统一的规范
#抽象类的实现
import abc
#声明一个类并且指定当前类的元素
class Human(metaclass = abc.ABCMeta)
#定义一个抽象的方法
@abc.abstractmethod
def smoking(self):
pass
#定义类抽象的方法
@abc.abstractmethod
def drink():
pass
#定静态抽象的方法
@abc.abstractmethod
def play():
pass
#11、自定义类
-可以定义类和函数,然后自己通过类直接赋值
-介意借助于MethodType实现
-借助于type实现
#自定义一个类-1 #可直接绑定类 class A(): pass def say(self): print("saying") A.say = say a = A() a.say() #自定义一个类-2 #要想绑定实例对象,必须借助MethodType模块 from types import MethodType class A(): pass def say(self): print("saying") a = A() a.say() = MethodType(say,A) a.say() #利用type造一个类 #先定义类应该具有的成员函数 def say(self): print("Saying") def talk(self): print("Talking") #用type来创建一个类 A = type("AName",(object,),{"class_say":say,"class_talk":talk}) #然后可以像正常访问一样使用类 a = A() a.class_say() a.class_talk()