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
描述器

 

 

六.继承

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
抽象

 

猜你喜欢

转载自www.cnblogs.com/yu-liang/p/9096198.html
今日推荐