一.面向对象编程 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>
四.属性
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
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 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
五.方法
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>>
(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
(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
(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

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

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

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