上文传送门,又见面向对象,不变的是思想,变的只是语言。

今日开始,我们深入来了解面向对象。

四、创建与引用

1、创建对象的流程

在创建对象时,看不见的手,帮我们做了三件事情,如下图:

python 根据pid 创建process 对象 python中创建对象_初始化

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指向同一个地址。内存图如下:

python 根据pid 创建process 对象 python中创建对象_python_02

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面向对象的实例

两种类的定义