2.md 3.8 KB
Newer Older
1 2
# 二、使用 `type()` 动态创建类 #

T
TwoWater 已提交
3 4 5 6 7 8 9
因为类也是对象,所以我们可以在程序运行的时候创建类。

Python 是动态语言。

**动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。**

在之前,我们先了了解下 `type()` 函数。
10 11 12 13 14 15 16 17 18 19


首先我们新建一个 `hello.py` 的模块,然后定义一个 Hello 的 class ,

```python
class Hello(object):
    def hello(self, name='Py'):
        print('Hello,', name)
```

T
TwoWater 已提交
20 21 22
然后在另一个模块中引用 hello 模块,并输出相应的信息。

其中 `type()` 函数的作用是可以查看一个类型和变量的类型。
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

```python
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from com.twowater.hello import Hello

h = Hello()
h.hello()

print(type(Hello))
print(type(h))

```

输出的结果是怎样的呢?

```
Hello, Py
<class 'type'>
<class 'com.twowater.hello.Hello'>
```

T
TwoWater 已提交
46 47 48 49 50 51 52
上面也提到过,`type()` 函数可以查看一个类型或变量的类型,`Hello` 是一个 `class` ,它的类型就是 `type` ,而 `h` 是一个实例,它的类型就是 `com.twowater.hello.Hello`

前面的 `com.twowater` 是我的包名,`hello` 模块在该包名下。

在这里还要细想一下,上面的例子中,我们使用 `type()` 函数查看一个类型或者变量的类型。

其中查看了一个 `Hello` class 的类型,打印的结果是: `<class 'type'>`
53

T
TwoWater 已提交
54 55 56 57 58
**其实 	`type()` 函数不仅可以返回一个对象的类型,也可以创建出新的类型。**

class 的定义是运行时动态创建的,而创建 class 的方法就是使用 `type()` 函数。

比如我们可以通过 `type()` 函数创建出上面例子中的 `Hello` 类,具体看下面的代码:
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103

```python
# -*- coding: UTF-8 -*-

def printHello(self, name='Py'):
    # 定义一个打印 Hello 的函数
    print('Hello,', name)


# 创建一个 Hello 类
Hello = type('Hello', (object,), dict(hello=printHello))

# 实例化 Hello 类
h = Hello()
# 调用 Hello 类的方法
h.hello()
# 查看 Hello class 的类型
print(type(Hello))
# 查看实例 h 的类型
print(type(h))

```

输出的结果如下:

```
Hello, Py
<class 'type'>
<class '__main__.Hello'>
```

在这里,需先了解下通过 `type()` 函数创建 class 对象的参数说明:

1、class 的名称,比如例子中的起名为 `Hello`

2、继承的父类集合,注意 Python 支持多重继承,如果只有一个父类,tuple 要使用单元素写法;例子中继承 object 类,因为是单元素的 tuple ,所以写成 `(object,)`

3、class 的方法名称与函数绑定;例子中将函数 `printHello` 绑定在方法名 `hello`

具体的模式如下:

```python
type(类名, 父类的元组针对继承的情况可以为空),包含属性的字典名称和值)
```

T
TwoWater 已提交
104 105 106 107 108 109 110 111 112
好了,了解完具体的参数使用之外,我们看看输出的结果,可以看到,通过 `type()` 函数创建的类和直接写 class 是完全一样的。

这是因为Python 解释器遇到 class 定义时,仅仅是扫描一下 class 定义的语法,然后调用 `type()` 函数创建出 class 的。

不过一般的情况下,我们都是使用 `class ***...` 的方法来定义类的,不过 `type()` 函数也可以让我们创建出类来。

也就是说,动态语言本身支持运行期动态创建类,这和静态语言有非常大的不同,要在静态语言运行期创建类,必须构造源代码字符串再调用编译器,或者借助一些工具生成字节码实现,本质上都是动态编译,会非常复杂。

**可以看到,在 Python 中,类也是对象,你可以动态的创建类。**
113

T
TwoWater 已提交
114
其实这也就是当你使用关键字 class 时 Python 在幕后做的事情,而这就是通过元类来实现的。 
115