086.面向对象和面向过程的区别_执行者思维_设计者思维
Python支持面向过程(更加关注流程,适合编写小程序)、面向对象(编写大规模)、函数式编程等多种编程范式
依然支持面向对象的基本功能:继承、多态、封装
087.对象的进化故事
进化过程:简单数据;数组;结构体;对象
088.类的定义_类和对象的关系
类:用来产生对象的对象(一切皆对象);将方法(函数)和属性放在一起;
对象的结构:方法(由同一个类创建的所有对象共享)和属性(每个对象维持自己的属性)
class Student:
def __init__(self,name,sorce):#固定用法
self.name=name
self.sorce=sorce
def any_score(self):
print("{0}的分数是:{1}".format(self.name,self.sorce))
s1=Student("lala",12)
s1.any_score()
089.构造函数__init__
__init__方法():初始化创建好的对象
__new__方法():用于创建对象,无需重定义该方法
<注>所有构造器第一个参数必须为self;名称固定__init__();构造函数通常用来初始化对象的实例属性(与C++里的一样);通过类名来调用构造函数,构造函数没有返回值;
<注>python中的self相当于C++中的self指针,Java中和C#中的this指针;Python中,self必须为构造函数的第一个参数,名字可以任意修改,但遵守惯例,都叫做self
090.实例属性_内存分析
实例属性是从属于实例对象的属性,也称为“实例变量”,其使用的要点如下:
1.实例属性一般在__init__()方法中通过:self.实例属性名=初始值 来定义
2.在本类的其他实例方法中,也是通过self进行访问:self.实例属性名
3.创建实例对象后,通过实例对象访问
class Student:
def __init__(self,name,sorce):#固定用法
self.name=name
self.sorce=sorce
def any_score(self):
print("{0}的分数是:{1}".format(self.name,self.sorce))
s1=Student("lala",12)
s1.any_score()
s1.age=18
print("年龄",s1.age)
s2=Student("www",15)
#print(s2.age) 因为age为s1的从属,只能被s1调用;
091.实例方法_内存分析方法调用过程_dir()_isinstance
实例方法是从属于实例对象
要点:a.定义实例方法时,第一个参数必须为self,和前面一样,self指当前的实例对象
b.调用实例方法时,不需要也不能给self传参,self由解释器自动传参
class Student:
def __init__(self,name,sorce):#固定用法
self.name=name
self.sorce=sorce
def any_score(self): #方法也是属性
print("{0}的分数是:{1}".format(self.name,self.sorce))
s2=Student("www",15)
#下面两句话是一样的
s2.any_score()
Student.any_score(s2)
<注>函数和方法的区别:
1.都是用来完成一个功能的语句块,本质一样
2.方法调用时,通过对象来调用,方法从属于特定实例对象,普通函数没有这个特点
3.直观上看,方法定义的时候需要传递self,函数不需要
<补充>
class Student:
def __init__(self,name,sorce):#固定用法
self.name=name
self.sorce=sorce
def any_score(self): #方法也是属性
print("{0}的分数是:{1}".format(self.name,self.sorce))
s2=Student("www",15)
#下面两句话是一样的
s2.any_score()
Student.any_score(s2)
print(dir(s2)) #可以获得对象所有的属性,方法
print(s2.__dict__) #对象的属性字典,即当前的属性
class Man: #空语句
pass
s3=Man()
print(isinstance(s3,Student)) #判断对象是不是指定类型
print(isinstance(s2,Student))
092.类对象
class Stu:
pass
print(type(Stu))
print(id(Stu))
Stu2=Stu
s1=Stu2()
print(s1)
093.类属性_内存分析创建类和对象的底层
类属性从属于“类对象”的属性,也称为“类变量”。由于,类属性从属于类对象,可以被所有实例对象共享
class Stu:
company="ss" #类属性
count=0 #类属性
def __init__(self,name,score):
self.name=name
self.score=score
Stu.count=Stu.count+1 #计数,一共调用了多少次实例对象
def s_score(self): #实例方法
print("我的公司是:",Stu.company)
print(self.name,"的分数是:",self.score)
s1=Stu("张三",100)
s1.s_score()
s2=Stu("李四",77)
s2.s_score()
print("一共创建了{0}个对象".format(Stu.count))
094.类方法_静态方法_内存分析图示
a.类方法:从属于“类对象的方法”。类方法通过装饰器@classmethod来定义;并且方法里的第一个参数为cls;
class Stu:
company="sss"
@classmethod
def dd(cls):
#操作类属性
print(cls.company)
Stu.dd()
b.静态方法:python中允许定能够与与“类对象”无关的方法,称为静态方法
“静态方法”和在模块中定义的普通函数没有区别,只不过“静态方法”放到了“类的名字空间里面”,需要通过类调用
静态方法通过装饰器@staticmethod来定义
class Stu:
company="sss"
def __init__(self,age):
self.age=age
@classmethod
def dd(cls):
#操作类属性
print(cls.company)
#print(self.age) 类方法和静态方法中,不能调用实例变量,实例方法
@staticmethod
def dd1():
#需要用类名调用
print(Stu.company)
print(3333)
Stu.dd()
Stu.dd1()
095.__del__()析构方法和垃圾回收机制
析构方法:实现对象被销毁时所需的操作;系统会自动提供,一般不需要自己定义
class M:
def __del__(self):
print("销毁对象{0}".format(self))
p1=M()
p2=M()
del p2
print("程序结束")
print(p1)
print(p2) #p2已经被销毁
096.__call__()方法和可调用对象
定义了__call__()方法的对象,成为“可调用对象”,即该对象可以像函数一样被调用
class Sa:
#工资计算
def __call__(self,salary):
print("计算工资")
ysalary=salary*12
dsalary=salary//22.5
return dict(ysalary=ysalary,dsalary=dsalary)
s=Sa()
print(s(3000))
097.方法没有重载_方法的动态性
a.方法没有重载
《注》在其他语言中,可以定义多个重名的方法,只需要保证签名唯一即可,方法签名包含:方法名、参数数量、参数类型
在python中如果在类体里定义了多个重名的方法,只有最后一个方法有效
b.方法的动态性
Python是动态语言,我们可以动态的为类添加新的方法,或者动态修改类的已有方法
class work:
def f1(self):
print("1111")
def f2(a):
print(a,"allalal")
def f3():
print("22222222")
p =work()
p.f1()
#p.f2() #不存在这个属性
#以下是定义新的方法
work.f3=f2
p.f3()
#修改旧的
p.f1=f3
p.f1()
098.私有属性:实现封装
1.两个下划线开头的属性是私有的,其他为公共的
2.类内部可以访问私有属性或方法
3.类外部不能直接访问私有属性或者方法
4.类外部可以通过“_类名__私有属性(方法)名”访问私有属性(方法)
<注>方法的本质也是属性
class S:
def __init__(self,age,num):
self.age=age
self.__num=num
e=S(1,2)
print(e.age)
print(e._S__num)
099.私有方法
class S:
__company="444444444"
def __init__(self,age,num):#私有属性
self.age=age
self.__num=num
def __f2(self):#私有方法
print("啦啦啦啦")
print("num:{0}".format(self.__num))
print(S.__company)
e=S(1,2)
print(e.age)
print(e._S__num)
#对外私有
e._S__f2()
print(e._S__company)
100.@property装饰器_get和set方法
@property可以将一个方法的调用
class s:
@property #装饰器
def f1(self):
print("!!")
return 100000
s1=s()
##s1.f1()
print(s1.f1)
101.面向对象的三大特征说明(封装、继承、多态)
(C++,Java都支持)
封装:隐藏对象的属性和实现细节;Python没有严格的语法级别的“访问控制符”
继承:可以让子类具有父类的特性,提高代码的重用性;增量进化,在原有父类设计不变的情况下,增加新的功能,或者改进算法
多态:是指同一个方法调用由于对象不同会产生不同的行为。
102.继承
class s:
def __init__(self,name,age):
self.name=name
self.age=age
def sage(self):
print("不知道")
class s1(s):
def __init__(self,name,age,num):
s.__init__(self,name,age)#必须显示调用
self.num=num
print(s1.mro())
a=s("lalla",30)
a.sage()
print(a.name)
c=s1("kkk",2,3)
c.sage()
print(c.num)
103.方法的重写
成员继承:子类继承了父类除构造方法之外的所有成员
方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类的方法,也称“重写”
重写前:
class person:
def __init__(self,name,age):
self.name=name
self.age=age
#以下为两个方法;
def say_age(self):
print("我的年龄是:",self.age)
def say_name(self):
print("我的名字是:{0}".format(self.name))
#stu继承person
class stu(person):
def __init__(self,name,age,score):
person.__init__(self,name,age)
self.score=score
s=stu("李萌",18,30)
s.say_age()
s.say_name()
重写后:
class person:
def __init__(self,name,age):
self.name=name
self.age=age
#以下为两个方法;
def say_age(self):
print("我的年龄是:",self.age)
def say_name(self):
print("我的名字是:{0}".format(self.name))
#stu继承person
class stu(person):
def __init__(self,name,age,score):
person.__init__(self,name,age)
self.score=score
#重写方法:
def say_name(self):
#子类重写了父类的方法
print("大家好!我的名字是:{0}".format(self.name ))
s=stu("李萌",18,30)
s.say_age()
s.say_name()#这是子类调用
104.object根类_dir()
a.查看类的继承层次结构
通过类的方法mro() 或者类的属性__mro__可以输出这个类的继承层次结构
class a:pass
class b(a):pass
class c(b):pass
print(c.mro())
b.object根类
object类是所有类的父类,因此所有的类都有object类的属性和方法。接下来使深入研究object类的结构
c.dir()查看对象属性
105.重写__str__()方法
object 有一个__str__()方法,用于返回一个对于“对象的描述”,对应于内置函数str()经常用于print()方法,帮助我们查看对象的信息,__str__() 可以重写
#测试重写object的__str__()
class person: #继承object
def __init__(self,name):
self.name=name
#以下两行为新增加部分,重写
def __str__(self):
return "名字是:{0}".format(self.name)
p=person("李萌")
print(p)
106.多重继承
Python支持多重继承(对比:Java不支持多继承,类的继承只有单继承),一个子类可以有多个“直接父类”。这样,就具备了“多个父类”的特点(优点:使得类的定义变得灵活)。但是由于,(坏处)这样会被“类的整体层次”搞得异常复杂,尽量避免使用
107.mro()
Python支持多继承,如果父类中有相同名字的方法,在子类没有指定父类名时,解释器将“从左向右”按顺序搜索
mro(method resolution order):方法解析顺序(是采用广度优先算法,字面上来说则是按照继承顺序的先后来执行的)。我们可以通过mro()方法获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找的
class a:
def say(self):
print("AAA")
class b:
def say(self):
print("BBB")
class c(b,a):
def cc(self):
print("cc")
m=c()
print(c.mro())
m.say()
108.super()获得父类的定义
在子类中,如果想要获得父类的方法时,我们可以通过super()来做。super()代表父类的定义,不是父类对象。
#测试super() 代表父类的定义,而不是父类的对象
class a :
def say(self):
print("a:",self)
class b(a ):
def say(self):
#a.say(self) 下面一个语句的调用与本行语句的调用的效果相同
super().say()#通过super获得父类的定义再进行say的调用
print("b:",self)
b().say()
109.多态
多态是指同一个方法调用由于对象不同可能会产生不同的行为
<注>1.多态是方法的多态,属性没有多态。
2.多态的存在有两个必要条件,继承和方法重写
#多态
class man:
def eat(self):
print("吃饭")
class c(man):
def eat(self):
print("筷子吃饭")
class e(man):
def eat(self):
print("刀叉吃饭")
class y(man):
def eat(self):
print("右手吃饭")
def maneat(q):
if isinstance(q,man): #sinstance() 会认为子类是一种父类类型,考虑继承关系。
q.eat() #多态,一个方法调用,根据对象不同调用不同的方法
else:
print("不能吃饭")
maneat(c())
maneat(e())
110.特殊方法和运算符重载
Python的运算符实际上是通过调用对象的特殊方法实现的 (每个运算符实际上都对应了相应的方法)
a=20
b=30
c=a+b
d=a.__add__(b)
print("c:",c)
print("d:",d )
#测试运算符的重载
class person:
def __init__(self,name):
self.name=name
def __add__(self, other):
if isinstance(other,person):
return "{0}-{1} ".format(self.name,other.name)
else:
return "不是同类对象不能相加"
def __mul__(self,other):
if isinstance(other,int):
return self.name*other
else:
return "不是同类对象不能相加"
p1=person("李萌")
p2=person("小萌萌")
x=p1+p2
print(x)
print(x*3)
111.特殊属性
class a:
def say(self):
print("AAA")
class b:
def say(self):
print("BBB")
class c(b,a):
#增加属性
def __init__(self,nn):
self.nn=nn
def cc(self):
print("cc")
m=c(3)
#测试以下特殊属性
print(dir(m))
print(m.__dict__)
print(m.__class__)#m所对应的类
print(c.__bases__)#获得父类
print(c.mro() )#顺序获得所继承的类
print(a.__subclasses__())#a的子类
112.对象的浅拷贝和深拷贝_内存分析
浅拷贝(把自己拷贝):Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝。因此源对象和拷贝对象会引用同一个子对象
深拷贝(把子孙都拷贝):使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象。源对象和拷贝对象所有的子对象也不同
变量的赋值操作:只是形成两个变量,实际还是指向同一个对象
#测试对象的浅拷贝、深拷贝
import copy
class phone:
def __init__(self,cpu,screen):
self.cpu=cpu
self.screen=screen
class cpu:
def calculate(self):
print("做计算")
print("cpu对象:",self)
class screen:
def show(self):
print("显示")
print("screen对象:",self)
#测试变量赋值
#m1=phone()
#m2=m1
#print(m1)
#print(m2)
#m1和m2的地址完全一样,
#c测试浅复制
print("测试浅复制")
c1=cpu()
s1=screen()
m1=phone(c1,s1)
m2=copy.copy(m1)
print(m1,m1.cpu,m1.screen)
print(m2,m2.cpu,m2.screen)
#测试深复制
print("测试深复制")
m3=copy.deepcopy(m1)
print(m1,m1.cpu,m1.screen)
print(m3,m3.cpu,m3.screen)
113.组合
继承:is-a关系使用继承。从而实现子类拥有父类的方法和属性
组合:has-a 关系使用组合。实现一个类拥有另一个类的方法和属性
继承和组合是实现代码的复用,
#测试组合
#使用继承实现代码复用
class A1:
def say_a1_(self):
print("a1a1")
class B1(A1):
pass
b1=B1()
b1.say_a1_()
#使用组合实现代码的复用
class A2:
def say__a2__(self):
print("a2a2")
class B2:
def __init__(self,a):
self.a=a
a2=A2()
b2=B2(a2)
b2.a.say__a2__()
#测试组合
class phone:
def __init__(self,cpu,screen):
self.cpu=cpu
self.screen=screen
class cpu:
def calculate(self):
print("做计算")
print("cpu对象:",self)
class screen:
def show(self):
print("显示")
print("screen对象:",self)
m1=phone(cpu(),screen())
m1.cpu.calculate()
m1.screen.show()
114.设计模式_工厂模式实现
工厂模式(造对象)实现了创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象进行统一的管理和控制
#测试工程模式GOF
#工厂模式
class car:
def createcar(self,brand):
if brand =="奔驰":
return benchi()
elif brand=="宝马":
return baoma()
elif brand=="比亚迪":
return byd()
else:
return "未知品牌,无法创建"
class baoma:
pass
class benchi:
pass
class byd:
pass
factory = car ()
c1=factory.createcar("奔驰")
c2=factory.createcar("比亚迪")
print(c1)
print(c2)
115.设计模式_单例模式实现
单例模式的核心作用是确保一个类只有一个实例,并且提供一个访问该实例的全局访问点
单例模式只生成一个实例对象,减少对系统资源的开销。当一个对象的产生需要比较多的资源,如读取配置文件、产生其他依赖对象时,可以产生一个“单例对象”,然后永久驻留内存中,从而极大的降低开销。
#单例模式
class my:
__obj=None #类属性 #定义单例需要重写new方法和构造方法,将创建好的单例放在一个属性里
flag=True
def __new__(cls,*args,**kwargs):
if cls.__obj==None:
cls.__obj=object.__new__(cls) #建好一个单例对象
return cls.__obj
def __init__(self,name):
if my.flag:
print("+++++++.....")
self.name=name
my.flag=False
a=my("aa")
b=my("bb")
print(a)
print(b)
c=my("cc")
print(c)
#单例模式和工厂模式的整合
#测试工程模式GOF
#工厂模式
class car:
__obj = None # 类属性 #定义单例需要重写new方法和构造方法,将创建好的单例放在一个属性里
flag = True
def createcar(self,brand):
if brand =="奔驰":
return benchi()
elif brand=="宝马":
return baoma()
elif brand=="比亚迪":
return byd()
else:
return "未知品牌,无法创建"
def __new__(cls, *args, **kwargs):
if cls.__obj == None:
cls.__obj = object.__new__(cls) # 建好一个单例对象
return cls.__obj
def __init__(self):
if car.flag:
print("+++++++.....")
car.flag = False
class baoma:
pass
class benchi:
pass
class byd:
pass
factory = car ()
c1=factory.createcar("奔驰")
c2=factory.createcar("比亚迪")
print(c1)
print(c2)
factory2=car()
print(factory)
print(factory2)