zoukankan      html  css  js  c++  java
  • python3 面向对象编程

    一.面向对象编程 OOP (Object Oriented Programming)

    1.OOP是一种计算机编程架构,计算机程序是由单个能够起到子程序作用的单元或对象组合而成,即把对象作为程序的基本单元。

    2.面向对象本身是对面向过程的封装。

    3.OOP的三大特点:封装、继承和多态。

    4.python是一门彻底的面向对象编程(opp)的语言,python中万物皆对象。

    5.python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

    6.python中,一个对象包括:属性和方法(变量+函数)

     

    二.类(Class)和实例(Instance)

    1.对象:类和实例

    (1)类:用来描述具有相同的属性和方法的对象的集合,类本质上也是对象

    (2)实例:具有属性和方法的对象,实例本质上也是对象,在python中实例也被称为对象,为了区别于整个的对象概念,把它称作实例

    (3)实例抽象出类,类实例化为实例,一个类可以有多个实例

    (4)类和实例相当于抽象和具体的关系:比如:类:学生;实例:张三

    2.python中默认继承(object)的类,也被称作新式类

    3.python中通过一个类对象来创建另一个类对象或对应的实例对象,

    4.创建类对象的类被称作元类,type是终极元类

    5.类和对象:(1)类=对象=类对象;类属性(2) 对象=对象=一般对象=实例;对象属性=实例属性

     

    三.创建类和实例

    1.通过class 创建一个类

    2.类的创建流程:检测__metaclass__属性:该类--父类--模块中--type元类

    3.根据类名实例化一个实例

    4.类名(money)是变量(money),变量(类名)引用该类,类实例化对象,由变量(one)引用该对象,由该对象里面的__class__找到该类

     1 class Money:
     2     pass
     3 one=Money()
     4 print(type(Money))
     5 print(type(one))
     6 print(Money.__name__)#访问类的名称
     7 print(one.__class__)#访问实例对应的类
     8 ----------------------------------------------------------------------
     9 <class 'type'>
    10 <class '__main__.Money'>
    11 Money
    12 <class '__main__.Money'>
    创建类和实例

     1 #type(cls, what, bases=None, dict=None):
     2 # 创建类:类名=type(类,父类(),{__dict__})
     3 #通过元类创建
     4 a=10
     5 print(type(a))
     6 xxx=type('dog',(),{'count':0})
     7 print(xxx)
     8 print(xxx.__dict__)
     9 d=xxx()
    10 print(d)
    11 -------------------------------------------
    12 <class 'int'>
    13 <class '__main__.dog'>
    14 {'count': 0, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'dog' objects>, '__weakref__': <attribute '__weakref__' of 'dog' objects>, '__doc__': None}
    15 <__main__.dog object at 0x0307C4B0>
    类对象的创建方式2

     

    四.属性

    1.类属性和实例属性

    (1)类属性:定义在类中且在函数体之外,可以通过类名访问其属性;类属性被对应的各个实例中共享;类属性通常不作为实例属性使用

    (2)实例属性:定义在方法中的属性,只作用于当前实例的类

    (3)类对象的__dict__属性(只读属性)默认不能被赋值修改,可以通过setattr方法修改;而一般对象里面的__dict__属性能被直接修改

    (4)一般情况下,属性存储在__dict__的字典中,有些内置对象没有这个__dict__属性

    (5)能通过实例找到类属性,不能通过类访问实例属性

    (6)变量后面加_:表示与系统关键字进行区分的命名方式;变量后面加__:表示系统内置的写法

    (7)实例属性访问机制:getattribute方法---调用描述器方法的get方法---实例自身的dict字典---对应类的dict字典---父类(上层)的dict字典---调用getattr方法

    2.类属性的增、删、改、查

     1 class money:
     2     age=19
     3     num=123  #直接在类中添加属性
     4 money.count=1#给类增加一些属性,类属性=值
     5 money.age=3#给类的属性直接赋值;来改变属性值
     6 print(money.count)
     7 print(money.age)
     8 print(money.__dict__)#查看类的所有属性,以字典形式返回(类的内置属性和创建的属性)
     9 
    10 m=money
    11 print(m.age)#通过对象访问类的属性
    12 print(m.__name__)
    13 print(m.__class__)
    14 
    15 #del 删除类的直系属性
    16 #不能通过对象删除累属性
    17 -----------------------------------------------------
    18 1
    19 3
    20 {'__module__': '__main__', 'age': 3, 'num': 123, '__dict__': <attribute '__dict__' of 'money' objects>, '__weakref__': <attribute '__weakref__' of 'money' objects>, '__doc__': None, 'count': 1}
    21 3
    22 money
    23 <class 'type'>
    24 
    25 类属性
    类属性的增、删、改、查

    3.实例属性的增、删、改、查

     1 class Person:
     2     pass
     3 p=Person()
     4 
     5 #给p对象增加一些属性,对象属性=值
     6 p.age=18
     7 #验证是否有添加成功
     8 print(p.age)
     9 print(p.__dict__)#查看对象的所有属性,以字典形式返回
    10 
    11 p.age=[1,3]#修改操作,直接赋值修改对象的属性,id会变
    12 print(p.age)
    13 
    14 p.age.append('小花')#访问操作,操作(添加)值,id不变
    15 print(p.age)
    16 
    17 #del 删除
    18 ---------------------------------------------------------
    19 18
    20 {'age': 18}
    21 [1, 3]
    22 [1, 3, '小花']
    实例属性的增、删、改、查

    4.限制实例属性的添加__slots__

    1 class person:
    2     __slots__ = ['age']#限制对象属性的添加
    3     pass
    4 p1=person()
    5 p1.age=10
    6 # p1.num=10 报错AttributeError: 'person' object has no attribute 'num'
    7 print(p1.age)
    8 ----------------------------------------------
    9 10
    限制对象属性的添加__slots__

    5.python中对象的属性查找机制:优先到对象自身去查找属性,找到则结束;如果没找到,则根据__class__找到对象对应的类,到类里面查找

    6.公有属性、受保护属性、私有属性

    (1)公有属性:共享的属性,一般的属性

    (2)受保护属性:受到保护的属性,用 _ 前缀表示

    (3)私有属性:防止外界直接访问,防止被子类同名称属性覆盖,进行数据保护和数据过滤,用 __ 前缀表示,实例不能访问私有属性

     1 class person:
     2     def __init__(self):
     3         self.__age=18
     4 
     5     def setAge(self,value):
     6         if isinstance(value,int) and 0<value<200:#数据过滤
     7             self.__age=value
     8         else:
     9             print('数据错误')
    10 
    11     def getAge(self):
    12         return self.__age
    13 
    14 p=person()
    15 print(p._person__age)
    16 p.setAge(20)
    17 print(p._person__age)
    18 print(p.getAge())
    19 -------------------------------------------------
    20 18
    21 20
    22 20
    私有化属性

     私有属性的访问(名字重整):__类名 变为 _类名__x

     1 class Animal:
     2     __x = 10
     3     def test(self):
     4         print(Animal.__x)
     5         print(self.__x)
     6 
     7 print(Animal.__dict__)
     8 print(Animal._Animal__x)
     9 -------------------------------------------------
    10 {'__module__': '__main__', '_Animal__x': 10, 'test': <function Animal.test at 0x0304C618>, '__dict__': <attribute '__dict__' of 'Animal' objects>, '__weakref__': <attribute '__weakref__' of 'Animal' objects>, '__doc__': None}
    11 10
    私有属性名称重整

    7.只读属性(只能读取,不能写入):(1)先私有化,再部分公开,;利用@property装饰器(2)__setattr__

     1 class Person:
     2     def __init__(self):
     3         self.__age=18
     4 
     5     def getAge(self):
     6         return self.__age
     7 
     8     @property  # 可以将一些属性的操作方法关联这个方法
     9     # property(fget=Nofne, set=None, fdel=None, doc=None)
    10     def age(self):
    11         return self.__age
    12 p=Person()
    13 print(p.getAge())
    14 print(p.age)
    15 # p.age=666 #AttributeError: can't set attribute
    16 -------------------------------------------------------------
    17 18
    18 18
    只读属性1
     1 class Person:
     2     def __setattr__(self, key, value):
     3         print(key, value)
     4         if key=='age'and key in self.__dict__.keys():
     5             print('只读属性')
     6         else:
     7             self.__dict__[key]=value
     8 
     9 p=Person()
    10 p.age=19
    11 p.name='sz'
    12 print(p.__dict__)
    13 print(p.age)
    14 p.age=12
    15 print(p.age)
    16 -------------------------------------------
    17 age 19
    18 name sz
    19 {'age': 19, 'name': 'sz'}
    20 19
    21 age 12
    22 只读属性
    23 19
    只读属性2

     

    五.方法

    1.在类内部,使用 def 关键字来定义一个方法;调用:对象.方法

    2.与一般函数定义不同,方法必须包含形式参数 self, 且为第一个参数,self 代表的是对象本身

    3.self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类,self 不是 python 关键字,可以认为方法中的self其实就是实例对象的唯一标志

    4.实例方法、类方法、静态方法

    (1)无论哪种类型的方法,都是存储在类中,在类的__dict__指向的字典中,没有在实例当中的方法

     1 class person:
     2     def shilifangfa(self):
     3         print('实例方法',self)
     4 
     5     @classmethod
     6     def leifangfa(cls):
     7         print('类方法',cls)
     8 
     9     @staticmethod
    10     def jingtaifanggfa():
    11         print('静态方法')
    12 
    13 p=person()
    14 p.shilifangfa()
    15 print(p)
    16 # person.shilifangfa()#TypeError: shilifangfa() missing 1 required positional argument: 'self'
    17 
    18 person.leifangfa()
    19 person.jingtaifanggfa()
    20 -----------------------------------------------------------------
    21 实例方法 <__main__.person object at 0x052B6070>
    22 <__main__.person object at 0x052B6070>
    23 类方法 <class '__main__.person'>
    24 静态方法
    定义在类中的方法

    (2)实例方法:默认第一个参数需要接受到一个实例;调用:对象.方法

    (3)类方法:默认第一个参数需要接受到一个类,绑定在类上的方法

     1 class Person:
     2     @classmethod#类方法装饰器
     3     def leifangfa(cls,a):#第一个参数默认为类
     4         print('类方法',cls,a)
     5 
     6 Person.leifangfa(123)#通过类来调用
     7 p=Person()
     8 p.leifangfa(666)#通过实例来调用
     9 
    10 func=Person.leifangfa#通过定义函数的形式来调用
    11 func(111)
    12 
    13 class A(Person):
    14     pass
    15 A.leifangfa(1)#通过衍生类来调用
    16 ----------------------------------------------------------
    17 类方法 <class '__main__.Person'> 123
    18 类方法 <class '__main__.Person'> 666
    19 类方法 <class '__main__.Person'> 111
    20 类方法 <class '__main__.A'> 1
    21 
    22 类方法
    类方法的调用

    (4)静态方法:第一个参数什么也不默认接受;

     1 class Person:
     2     @staticmethod#静态方法装饰器
     3     def jingtai():
     4         print('静态方法')
     5 
     6 Person.jingtai()#通过类来调用
     7 p=Person()
     8 p.jingtai()#通过实例来调用
     9 func=Person.jingtai#通过定义函数的形式来调用
    10 func()
    11 ------------------------------------------
    12 静态方法
    13 静态方法
    14 静态方法
    静态方法

    (5)三种方法的访问权限

     1 class Person:
     2     age=5
     3     def shilifangfa(self):
     4         print('实例方法',self)
     5         print(self.age)
     6         print(self.num)
     7 
     8     @classmethod
     9     def leifangfa(cls):
    10         print('类方法',cls)
    11         print(cls.age)
    12         print(cls.num)
    13     @staticmethod
    14     def jingtaifanggfa():
    15         print('静态方法')
    16         print(Person.age)#访问类属性
    17 
    18 p=Person()
    19 p.num=10
    20 p.shilifangfa()#实例方法既能访问实例属性,又能访问类属性
    21 
    22 # p.leifangfa()#AttributeError: type object 'Person' has no attribute 'num'
    23 #Person.leifangfa()#AttributeError: type object 'Person' has no attribute 'num'
    24 #类方法不能访问实例属性,但能访问类属性
    25 
    26 Person.jingtaifanggfa()
    27 #静态方法可以访问类属性,但不能访问实例属性
    28 --------------------------------------------------------------------
    29 实例方法 <__main__.Person object at 0x054B6170>
    30 5
    31 10
    32 静态方法
    33 5
    三种方法的访问

    5.类的私有方法__private_method(相似私有属性):声明该方法为私有方法,只能在类的内部调用 ,不能在类地外部调用,self.__private_methods

    6.类的特殊方法

    (1)init初始化

     1 class myclass:
     2     """一个简单是实例"""
     3     i=21313
     4     def f(self):
     5         return 'hello world'
     6 
     7 #__init__()将对象创建为有初始状态的
     8 #类定义了 __init__() 方法的话,类的实例化操作会自动调用 __init__() 方法
     9 # __init__() 方法可以有参数,参数通过 __init__() 传递到类的实例化操作上
    10     def __init__(self,realpart):
    11         self.r = realpart
    12 
    13 
    14 x=myclass(3.4)   # 实例化类
    15 print(x.r)
    16 print(x.f)
    17 ------------------------------------------------------------------
    18 3.4
    19 <bound method myclass.f of <__main__.myclass object at 0x057C73D0>>
    init()

    (2)信息格式化操作,用字符串描述实例:__str__和__repr__

     1 class person:
     2     def __init__(self,n,a):
     3         self.name=n
     4         self.age=a
     5     def __str__(self):#信息格式化,用字符串描述实例,面向用户,通过print或str触发
     6         return '姓名:{},年龄:{}'.format(self.name,self.age)
     7     def __repr__(self):#信息格式化,用字符串描述实例,面向开发人员,通过实例本身或repr触发
     8         return 'repr'
     9 #先找__str__,如果没有,再找__repr__
    10 p=person('sz',18)
    11 print(p.name)
    12 print(p,type(p))#方法里的返回值#没有__str__方法时<__main__.person object at 0x04C86070>
    13 print(str(p),type(str(p)))#字符串
    14 print(repr(p))#获取实例的本质信息,可以用eval再次转换
    15 -------------------------------------------
    16 sz
    17 姓名:sz,年龄:18 <class '__main__.person'>
    18 姓名:sz,年龄:18 <class 'str'>
    19 repr
    str和repr

    (3)调用操作:__call__方法,使对象具备当做函数来调用的能力

     1 class person:
     2     def __init__(self,name):
     3         self.name=name
     4     def __call__(self,age):
     5         print('姓名:{},年龄:{}'.format(self.name,age))
     6 
     7 
     8 p=person('zyl')
     9 p(28)#使实例能被调用,传入参数
    10 p(23)
    11 p(14)
    12 ---------------------------------------------
    13 姓名:zyl,年龄:28
    14 姓名:zyl,年龄:23
    15 姓名:zyl,年龄:14
    __call__

    (4)索引操作:对一个实例进行索引,三个内置方法:setitem,getitem,delitem

     1 class person:
     2     def __init__(self):
     3         self.cache={}#增加一个字典属性
     4     def __setitem__(self, key, value):#设置/增添键值
     5         print('setitem',key,value)
     6         self.cache[key]=value
     7 
     8     def __getitem__(self, item):#获取键值
     9         # print('getitem',item)
    10         return self.cache[item]
    11 
    12     def __delitem__(self, key):#删除操作
    13         # print('setitem',key)
    14         del self.cache[key]
    15 
    16 
    17 p=person()
    18 p['name']='sz'#setitem
    19 print(p['name'])#getitem
    20 del p['name']
    21 print(p.cache)#查询字典
    22 ---------------------------------------------------
    23 setitem name sz
    24 sz
    25 {}
    索引

    (5)切片操作:对一个实例进行切片操作,三个内置方法:setitem,getitem,delitem

     1 class person:
     2     def __init__(self):
     3         self.items=[1,2,3,4,5,6,7,8,]#初始化以列表形式
     4     def __setitem__(self, key, value):#切片时只能修改,不能新增
     5         print(key,value)
     6         print(key.start)
     7         print(key.stop)
     8         print(key.step)
     9         self.items[key]=value
    10         #if isinstance(key,slice):#容错处理
    11         #    self.items[key.start:key.stop:key.step]=value
    12 
    13     def __getitem__(self, item):#获取信息
    14         print('getitem',item)
    15 
    16     def __delitem__(self, key):#删除
    17         print('setitem',key)
    18 
    19 
    20 p=person()
    21 print(p)
    22 print(p.items)
    23 p[0:4:2]=['a','b']#对进行切片操作,修改列表
    24 print(p.items)
    25 -------------------------------------------------------------------
    26 <__main__.person object at 0x0352C4B0>
    27 [1, 2, 3, 4, 5, 6, 7, 8]
    28 slice(0, 4, 2) ['a', 'b']
    29 0
    30 4
    31 2
    32 ['a', 2, 'b', 4, 5, 6, 7, 8]
    切片

    (6)比较操作:比较大小,真假

     1 class person:
     2     def __init__(self,age,height):
     3         self.age=age
     4         self.height=height
     5     def __eq__(self, other):#实现相等操作
     6         print(other)
     7         return self.age==other.age#返回操作后的值
     8     def __ne__(self, other):#不相等
     9         print('xxx')
    10     def __gt__(self, other):#大于
    11         pass
    12     def __ge__(self, other):#大于等于
    13         pass
    14     def __lt__(self, other):#小于
    15         print('lt')
    16     def __le__(self, other):#小于等于
    17         pass
    18     def __bool__(self):#布尔类型,返回实例是True还是False
    19         return self.age>18#返回值控制实例是True还是False
    20 
    21 
    22 p1=person(18,180)
    23 p2=person(17,190)
    24 print(p1==p2)
    25 print(p1!=p2)
    26 print(p1<p2)
    27 -------------------------------------------------
    28 <__main__.person object at 0x059A60D0>
    29 False
    30 xxx
    31 None
    32 lt
    33 None
    比较

    (7)遍历操作:getitem、iter、next,类中同时有iter和next方法的实例才是一个迭代器,利用iter获取迭代器对象,利用next访问迭代器

     1 class person:
     2     def __init__(self):
     3         self.result=1
     4     def __getitem__(self, item):
     5         self.result+=1
     6         if self.result>=6:
     7             raise StopIteration('停止遍历')
     8         return self.result
     9 
    10 p=person()
    11 for i in p:
    12     print(i)
    13 --------------------------------------------
    14 2
    15 3
    16 4
    17 5
    getitem
     1 class person:
     2     def __init__(self):
     3         self.result=1
     4 # iter优先级高于getitem
     5     def __iter__(self):#获取实例的迭代器
     6         print('iter')
     7         return self#返回是一个迭代器对象
     8     def __next__(self):#对于迭代器调用next方法
     9         self.result+=1
    10         if self.result>=6:
    11             raise StopIteration('停止遍历')
    12         return self.result#对于迭代器进行遍历
    13 p=person()
    14 for i in p:
    15     print(i)
    16 --------------------------------------------
    17 iter
    18 2
    19 3
    20 4
    21 5
    iter

    (8)描述器:可以描述一个属性操作的对象;property用来管理属性访问。资料描述器(get/set)>实例属性>非资料描述器(get)

     1 class Person(object):
     2     def __init__(self):
     3         self.__age=18
     4     def get_age(self):
     5         return self.__age
     6     def set_age(self,value):
     7         self.__age=value
     8     #property(fget=None, fset=None, fdel=None, doc=None)
     9     age=property(get_age,set_age)
    10 p=Person()
    11 print(p.age)
    12 p.age=98
    13 print(p.age)
    14 print(p.__dict__)
    15 
    16 
    17 
    18 class Person2(object):
    19     def __init__(self):
    20         self.__age=18
    21     @property
    22     def age(self):
    23         return self.__age
    24     @age.setter
    25     def age(self,value):
    26         self.__age=value
    27 p2=Person2()
    28 print(p2.age)
    29 p2.age=98
    30 print(p2.age)
    31 print(p2.__dict__)
    32 ----------------------------------------------------------------------
    33 18
    34 98
    35 {'_Person__age': 98}
    36 18
    37 98
    38 {'_Person2__age': 98}
    property
     1 class Age:
     2     def __get__(self, instance, owner):
     3         print('get')
     4     def __set__(self, instance, value):
     5         print('set')
     6     def __delete__(self, instance):
     7         print('delete')
     8 class person:
     9     age=Age()#描述器
    10     def __getattribute__(self, item):
    11         print('xxx')
    12 
    13 #通过实例操作描述器
    14 p=person()
    15 p.age=10#调用了set,get
    16 print(p.age)#调用的方法中没有返回值
    17 del p.age#调用了delete
    18 #一般不通过类来操作描述器
    19 print(person.age)#只是调用了get方法
    20 person.age=19
    21 del person.age#没有用delete方法
    22 ---------------------------------------------------------------------
    23 set
    24 xxx
    25 None
    26 delete
    27 get
    28 None
    描述器

     

     

     7.补充

    (1)__new__方法:创建实例对象,将对象创建出来,返回实例对象,主要用于继承一些不可变的类,一般默认

    (2)__init__方法:初始化实例对象,一般用于定义初始化属性,当对象被创建,自动执行,无需返回值,若还有new方法,则执行new

    (3)__call__方法:使得类能像函数那样调用,一般放类的执行

    六.继承

    class DerivedClassName(BaseClassName):
           <statement>


    class DerivedClassName(modname.BaseClassName):

           <statement>

    其中DerivedClassName子类     BaseClassName基类

     1 class people:                   # 类定义
     2     name = ''                   # 定义基本属性
     3     age = 0                     # 定义基本属性
     4     __weight = 0                # 定义私有属性,私有属性在类外部无法直接进行访问
     5 
     6     def __init__(self, n, a, w):# 定义构造方法
     7         self.name = n
     8         self.age = a
     9         self.__weight = w
    10 
    11     def speak(self):            # 定义构造方法
    12         print("%s 说: 我 %d 岁。" % (self.name, self.age))
    13 
    14 class student(people):          # 单继承示例,定义基类
    15     grade = ''
    16 
    17     def __init__(self, n, a, w, g):
    18         people.__init__(self, n, a, w)# 调用父类的构函
    19         self.grade = g
    20 
    21     def speak(self):            # 覆写父类的方法
    22         print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade))
    23 
    24 class speaker():                # 另一个类,多重继承之前的准备
    25     topic = ''
    26     name = ''
    27 
    28     def __init__(self, n, t):
    29         self.name = n
    30         self.topic = t
    31 
    32     def speak(self):
    33         print("我叫 %s,我是一个演说家,我演讲的主题是 %s" % (self.name, self.topic))
    34 
    35 # 多重继承
    36 class sample(speaker, student):
    37     a = ''
    38 
    39     def __init__(self, n, a, w, g, t):
    40         student.__init__(self, n, a, w, g)
    41         speaker.__init__(self, n, t)
    42 
    43 
    44 test = sample("Tim", 25, 80, 4, "Python")
    45 test.speak()  # 方法名同,默认调用的是在括号中排前地父类的方法
    46 ------------------------------------------------------------------------------
    47 我叫 Tim,我是一个演说家,我演讲的主题是 Python
    继承

    1.子类(派生类)继承父类(超类)(基类):子类拥有父类一些资源的'使用权'

    2.父类---共性;子类---特性

    3.单继承:仅仅继承一个父类;多继承:继承多个父类;多继承分为无重叠的多继承,有重叠的多继承

    4.可以在子类中重写父类的方法

    5.supper()调用父的一个方法,自动找到所有基类以及对应的方法

     1 class Dongwu():
     2     def __init__(self,name):
     3         self.name=name
     4     def shengming(self):
     5         print('dongwu')
     6 
     7 class Gou(Dongwu):
     8     def __init__(self,name,color):
     9         super().__init__(name)  #调用父类的一个方法,从父类获得继承
    10         self.color=color        #在子类中添加新的内容
    11     def shengming(self):
    12         print('gou')
    13     def kanjia(self):
    14         print('kanjia')
    15 
    16 a1=Dongwu('a1')
    17 a2=Gou('a2',1)
    18 print(a1.shengming(),a2.shengming())
    19 ----------------------------------------------------------------------------
    20 dongwu
    21 gou
    super
     1 class D:
     2     def __init__(self):
     3         print('d')
     4 class B(D):
     5     def __init__(self):
     6         D.__init__(self)#调用父类的方法
     7         print('b')
     8 class C(D):
     9     def __init__(self):
    10         super().__init__()
    11         print('c')
    12 class A(C,B):
    13     def __init__(self):
    14         # B.__init__(self)
    15         # C.__init__(self)调用了两次
    16         #super沿着mro链条,找到下一级节点,去调用对应的方法
    17         #super(__class__, <first argument>)沿着参数二的mro链条,找参数一的下一个节点
    18         #使用参数二进行调用
    19         super(A, self).__init__()
    20         # super().__init__()
    21         print('a')
    22 C()
    23 A()
    24 -------------------------------------
    25 d
    26 c
    27 d
    28 b
    29 c
    30 a
    super

    6.type和object

    (1)type:元类,实例化其他类,包括object类,type类实例化object类

    (2)object:所有类的父类,包括type类,type类继承object类

    7.资源:除了私有的方法和属性,其他的基本都能继承;资源的‘使用权’实质上指资源的访问权,并不是指资源的复制

    8.资源的使用:

    (1)单继承链:从下到上

    (2)无重叠的多继承链:从左到右,从上到下

    (3)有重叠的多继承链:从上到下,从左到右,(新式类,c3算法)

     1 #查看资源查找顺序
     2 import inspect
     3 class animal:
     4     pass
     5 class person(animal):
     6     pass
     7 inspect.getmro(person)#查看类资源的访问循序
     8 print(person.__mro__)
     9 print(person.mro())
    10 ---------------------------------------------------------------
    11 (<class '__main__.person'>, <class '__main__.animal'>, <class 'object'>)
    12 [<class '__main__.person'>, <class '__main__.animal'>, <class 'object'>]
    资源查找
     1 class D:
     2     pass
     3 class B(D):
     4     pass
     5 class C(D):
     6     pass
     7 class A(C,B):
     8     pass
     9 print(A.mro())
    10 -----------------------------------------------
    11 [<class '__main__.A'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class 'object'>]
    资源查找

    9.资源的覆盖:属性的覆盖和方法的重写;本质是访问优先级顺序决定的

     

    七.内存管理机制

    1.所有对象都会在内存中开辟一块空间进行存储;根据不同的类型及内容开辟不同的空间大小进行存储,并返回该空间的地址给外界接受(引用),用于后续对这个对象的操作

    2.对于整数和短小的字符,python会进行缓存,不会创建多个相同对象

    3.容器对象(列表,元组,字典,自定义类对象等),存储的其他对象,仅仅是其他对象的引用,并不是其他对象本身

    4.引用计数器:对象自身被引用的个数

     1 import sys
     2 class person:
     3     pass
     4 p1 = person()  # p1引用person类对象====把person类对象的地址赋值给p1
     5 print(sys.getrefcount(p1))#查看p1引用的对象的引用个数,注意初始为一即结果是:实际引用个数加一
     6 p2 = p1#把p1的值赋值给p2,p1的值是person类对象的地址,p2引用person类对象,p2的值是person类对象的地址
     7 print(sys.getrefcount(p1))  # 查看对象(person类对象)引用个数,注意初始为一即结果是:实际引用个数加一
     8 del p2
     9 print(sys.getrefcount(p1)) #查看p1引用的对象的引用个数
    10 
    11 #引用计数加一:
    12 #p1=person()对象被创建
    13 p2=p1#对象被引用,3
    14 print(sys.getrefcount(p1))
    15 l=[p1]#对象作为一个元素存储在容器中,引用次数加一,4
    16 print(sys.getrefcount(p1))
    17 
    18 # 引用次数+2
    19 def log(obj):
    20     print(sys.getrefcount(obj))
    21 log(p1)#对象被作为参数,传入到一个函数中,6
    22 
    23 #引用次数减一:
    24 #del p1对象的别名被显示销毁
    25 #p1 = 123 对象的别名被赋予新的对象
    26 #一个对象离开它的作用域:一个函数执行完毕时;内部的局部变量关联的对象,它的引用会被释放
    27 #对象所在的容器被销毁,或从容器中删除对象
    28 ---------------------------------------------------------------------
    29 2
    30 3
    31 2
    32 3
    33 4
    34 6
    引用计数器
     1 #循环引用
     2 import objgraph
     3 class person:
     4     pass
     5 class dog:
     6     pass
     7 
     8 p=person()
     9 d=dog()
    10 print(objgraph.count('person'))#垃圾回收器,查看跟踪的对象个数
    11 print(objgraph.count('dog'))
    12 p.pet=d
    13 d.master=p
    14 print(objgraph.count('person'))
    15 print(objgraph.count('dog'))
    16 
    17 del p
    18 del d
    19 print(objgraph.count('person'))#对象并没有被释放
    20 print(objgraph.count('dog'))
    21 -----------------------------------------------------------------
    22 1
    23 1
    24 1
    25 1
    26 1
    27 1
    循环引用

    5.垃圾回收机制:解决循环引用问题:找到循环引用并干掉相关对象

     1 #垃圾回收机制
     2 #找到循环引用
     3 #1.收集所有容器对象,通过一个双向链表进行引用
     4 #2.对于每一个‘容器对象’,通过gc_refs来记录当前对应的引用计数
     5 #3.对于每一个‘容器对象’,找到它引用的‘容器对象’,并将这个‘容器对象’的引用计数-1
     6 #4.通过引用计数判断是否是循环引用,计数器为0的为循环引用,可以被释放
     7 
     8 
     9 #垃圾回收器中,新增的对象个数-消亡的个数达到一定阈值是才会触发垃圾检测
    10 #垃圾回收的周期顺序:0代垃圾回收一定次数才会触发0,1代回收;1代垃圾回收一定次数才会触发0,1,2代回收
    11 import gc
    12 import objgraph
    13 print(gc.get_threshold())#得到垃圾检测的参数(阈值,10代,10代)
    14 gc.set_threshold(800,10,10)#设置垃圾检测的参数
    15 print(gc.get_threshold())
    16 
    17 #垃圾回收:
    18 #自动回收:开启垃圾回收机制;达到垃圾回收的阈值
    19 print(gc.isenabled())#检测垃圾回收机制是否开启
    20 gc.disable()#关闭垃圾回收机制
    21 print(gc.isenabled())
    22 gc.enable()#开启垃圾回收机制
    23 print(gc.isenabled())
    24 
    25 #手动回收:
    26 class person:
    27     def __del__(self):
    28         print('person对象被释放了')
    29 class dog:
    30     def __del__(self):
    31         print('dog对象被释放了')
    32 p=person()
    33 d=dog()
    34 #两个实例对象之间相互引用,造成循环引用
    35 p.pet=d
    36 d.master=p#python2中弱引用weakref.ref()
    37 del p
    38 del d
    39 gc.collect()#手动回收垃圾,无关垃圾自动清理机制是否开启
    40 print(objgraph.count('person'))
    41 print(objgraph.count('dog'))
    42 --------------------------------------------------------------------
    43 (700, 10, 10)
    44 (800, 10, 10)
    45 True
    46 False
    47 True
    48 person对象被释放了
    49 dog对象被释放了
    50 0
    51 0
    垃圾回收机制

     

    八.补充

    1.如果对象的属性和方法名相同,属性会覆盖方法

    1.封装:把操作和属性封装在一个对象中

    2.多态:对象行为和属性的多态;python中并没有真正的多态,也不需要多态

    3.一个迭代器一定是一个可迭代对象,一个可迭代对象不一定是迭代器;可迭代对象:iter;迭代器:iter和next

    4.重载

     1 class Dw():
     2     def __init__(self,name):
     3         self.name=name
     4 #<__main__.Dw object at 0x02BD73D0>
     5     
     6    def __str__(self):
     7         return self.name
     8 #a
     9    
    10    def __repr__(self):
    11         return 'name:' +self.name
    12 #name:a
    13 
    14 a=Dw('a')
    15 print(a)
    16 ------------------------------------------------
    17 a
    重载

    5.组合:直接在类定义中把需要的类放进去实例化

     1 #组合:把类和实例化方方放到新类中,把几个没有关系的类放到一起
     2 class Turtle:
     3     def __init__(self,x):
     4         self.num=x
     5 class Fish:
     6     def __init__(self,x):
     7         self.num = x
     8 class Pool:
     9     def __init__(self,x,y):
    10         self.turtle=Turtle(x)
    11         self.fish=Fish(y)
    12     def print_num(self):
    13         print(self.turtle.num,self.fish.num)
    14 
    15 pool=Pool(1,10)
    16 pool.print_num()
    17 ----------------------------------------------------------------------
    18 1 10
    组合

    6.生成项目文档pydoc:(1):cmd--转到查看python文件的目录;查看文档描述: python -m pydoc 模块名称

         (2)启动本地服务,浏览web文档:python -m pydoc -p 端口号

         (3)生成指定模块html文档 :  python -m pydoc -w 模块名称

         (4)-k 查看相关的模块

          (5)-h帮助文档python -m pydoc -h 模块

         (6)-b自己开启端口python -m pydoc -b

    7.抽象类和抽象方法:抽象类:抽象出来的类,不能直接创建实例的类,创建会报错;抽象方法:抽象出来的方法,不具备具体实现,不能直接调用,子类不实现会报错

     1 import abc
     2 class animal(object,metaclass=abc.ABCMeta):
     3     @abc.abstractmethod
     4     def jiao(self):
     5         pass
     6 class dog(animal):
     7     def jiao(self):
     8         print('wang')
     9 
    10 class cat(animal):
    11     def jiao(self):
    12         print('miao')
    13 
    14 def test(obj):
    15     obj.jiao()
    16 
    17 d=dog()
    18 d.jiao()
    19 --------------------------------------
    20 wang
    抽象

     

  • 相关阅读:
    二叉树计数2(卡特兰数+高精乘低精+高精除低精)
    奶牛的身高(差分约束)
    海底高铁(差分)
    假期(动态规划+单调队列)
    RY哥查字典(字符串双模hash初步)
    元素查找(hash初步)
    【模板】单源最短路径 堆优化的dijkstra
    【模板】单源最短路径spfa
    【并查集】noi2001食物链
    【带权并查集】银河英雄传说
  • 原文地址:https://www.cnblogs.com/yu-liang/p/9096198.html
Copyright © 2011-2022 走看看