Python 面向对象和内存分析

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)

Python 面向对象和内存分析_第1张图片

 

<注>函数和方法的区别:

       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()

 

Python 面向对象和内存分析_第2张图片


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)


 

你可能感兴趣的:(Python,学习)