上文传送门,又见面向对象,不变的是思想,变的只是语言。
今日开始,我们深入来了解面向对象。
四、创建与引用
1、创建对象的流程
在创建对象时,看不见的手,帮我们做了三件事情,如下图:

1class Student:
2 name = ''
3 height = 0
4 weight = 0
5 age = 0
6 gender = 0
7 def __new__(cls, name, height, weight, age, gender):
8 print("new对象。。")
9 return object.__new__(cls)
10
11 def __init__(self, name, height, weight, age, gender):
12 print('初始化属性。。')
13 = name
14 self.height = height
15 self.weight = weight
16 self.age = age
17 self.gender = gender
18
19 def study(self):
20 print("我要好好学习。。")
21 def introduce(self):
22 print("""基本信息如下:23 姓名:%s24 性别:%s25 身高:%d26 体重:%d27 年龄:%d28 """ % (, '女' if self.gender == 0 else '男', self.height, self.weight, self.age))
29
30# 实例化对象
31s = Student("小王", 170, 180, 18, 0)
32s.introduce()创建对象,内部执行过程:
调用__new__方法创建一个对象,默认会调用object的__new__方法;
在调用__init__()方法进行属性的声明,就可以对这个对象进行一些操作,或者调用这个对象的方法了,__init__方法仅仅是初始化实例属性的方式之一。关注点:__new__(cls)和__init__(self)区别:
1)__new__()方法是一个类方法,第一个参数是class,而__init__()方法是实例方法,第一个参数是实例化的对象
2)__new__()方法比__init__()方法先执行
3)__new__()方法如果不返回对象的话,不会有任何对象被创建。__init__方法就不会被调用,__init__()方法只是初始化参数。
2、对象的地址拷贝
1class Student(object):
2 name = ''
3 height = 0
4 weight = 0
5 age = 0
6 gender = 0
7 def study(self):
8 print("我要好好学习。。")
9 def smile(self):
10 print("不要发出迷你的微笑。。")
11 def introduce(self):
12 print("""基本信息如下:13 姓名:%s14 性别:%s15 身高:%d16 体重:%d17 年龄:%d18 """ % (, '女' if self.gender == 0 else '男', self.height, self.weight, self.age))
19 # """ % (, '女' if s.gender == 0 else '男', s.height, s.weight, s.age))
20
21# 实例化对象
22s1 = Student()
23 = "张三"
24s1.height = 170
25s1.weight = 180
26s1.age = 18
27s2 = s1
28print("修改前:s对象中的name = %s,s2对象中的name = %s" % (, ))
29 = '张三李四'
30print("修改后:s对象中的name = %s,s2对象中的name = %s" % (, ))新建一个学生类,然后创建s1对象(s = student()),再把这个对象赋值给另外的变量s2 = s1,在修改s2的name属性,会发现s1对象中的name属性会也会修改,这是因为s1和s2指向同一个地址。内存图如下:

3、获取引用对象的计数器
1class Student:
2 def __init__(self, name, age):
3 self.__name = name
4 self.__age = age
5stu = Student('张三李四', 18)
6import sys
7print(sys.getrefcount(stu ))
8stu1 = stu
9print(sys.getrefcount(stu))
10stu2 = stu1
11print(sys.getrefcount(stu))执行结果为:
12
23
34注意:打印计数器的时候你会发现会多1个,多的一个是getrefcount()的形参。参考getrefcount的注释:
1getrefcount(object) -> integer
2
3Return the reference count of object. The count returned is generally
4one higher than you might expect, because it includes the (temporary)
5reference as an argument to getrefcount().五、另一种类定义方式
使用class格式定义类,是很常用的方式,不过以后你可能会见到利用type创建类的方式,虽然不那么常见。Type创建类方式本质是手动模拟class创建类的过程,将创建类的步骤拆分开,手动去创建。
1def play(self,sth):
2 print("play",sth)
3Person = type("a", (object,), {'name': '马云', 'play':play})
4p = Person()
5print()
6p.play("王者荣耀")
7print(dir(p))1def fn(self,name='world'):
2 print('hello,%s.' % name)
3Hello = type('Hello',(object,),dict(hello=fn))
4h = Hello()
5h.hello()
6h.hello('python')
7print(type(Hello))
8print(type(h))五、另一种类定义方式
使用class格式定义类,是很常用的方式,不过以后你可能会见到利用type创建类的方式,虽然不那么常见。Type创建类方式本质是手动模拟class创建类的过程,将创建类的步骤拆分开,手动去创建。
1def play(self,sth):
2 print("play",sth)
3Person = type("a", (object,), {'name': '马云', 'play':play})
4p = Person()
5print()
6p.play("王者荣耀")
7print(dir(p))1def fn(self,name='world'):
2 print('hello,%s.' % name)
3Hello = type('Hello',(object,),dict(hello=fn))
4h = Hello()
5h.hello()
6h.hello('python')
7print(type(Hello))
8print(type(h))六、动态特性
Python动态语言,在运行中可变,其灵活特性使得我们可以轻松加入相关属性、方法,当然内部也提供__slots__简单的制约我们,在python中一切都是自由的、都是自发地遵循规范编写代码,这点务必牢记。
1、变
之前接触过变量,变量的数据类型随使用的数据改变而改变,如万能的盒子:
1box = 'hello'
2box = 100
3def add(x,y):
4 return x+y
5box = add同理,在类的对象上也可以随意加入属性
1class F:
2 def __init__(self):
3 pass
4f1 = F()
5f2 = F()
6f1.box = 100
7print(f1.box)
8# print(f2.box) # 对f2没有影响同理也可以给类动态添加函数
1class F:
2 def __init__(self):
3 pass
4f1 = F()
5f2 = F()
6F.test =lambda self:print('动态添加,so happy')
7f1.test()
8如果为类方法,也可以动态绑定
9class F:
10 def __init__(self):
11 pass
12@classmethod
13def cm(cls):
14 print("class method")
15f1 = F()
16F.cm = cm
17F.cm()
18f1.cm()同理为静态方法,也简单加入。
1class F:
2 def __init__(self):
3 pass
4@staticmethod
5def sm():
6 print("static method")
7f1 = F()
8F.sm = sm
9F.sm()
10f1.sm()这种动态特性,灵活的超乎想象,要是可以一次定义完善,很好,若是不能,这可是很好的助手。
2、不变
由于python的灵活特性,所以可以在任何时刻加自己的属性、方法,如果想制约,可以借助slots来限制,及保护属性和方法
1class Cat(object):
2 def __init__(self,nick,age,gender):
3 self.nick = nick
4 self.age = age
5 self.gender = gender
6 __slots__ = ('nick','age','gender') #这里限定了实例属性
7
8if __name__ == '__main__':
9 cat = Cat('xiaohua',2,0)
10 # cat.kind = 'bosi'
11 print(cat.__dict__)内部就是干掉了dict而已。
如果还想更清楚的了解,可以从接下来的视频获取答案。
python面向对象的实例
两种类的定义
















