python中type的使用

type函数

python中type函数可以有一个参数,也可以有三个参数,分别返回对象的类型新的类型对象

type()方法语法如下

  • type(object)
  • type(name, bases, dict)

其中object为对象,name为类名,bases为基类的元组,dict为字典,存储类的属性

1. type方法返回对象的类型

在python语法中,一切皆为对象,如下所示,变量1为int类型,变量1.1为float类型等等

1
2
3
4
5
6
print(type(1))  # <class 'int'>
print(type(1.1)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type([1, 1])) # <class 'list'>
print(type((1, 1))) # <class 'tuple'>
print(type({"1": 1})) # <class 'dict'>

这里的int,float,str,list,tuple,dict均为类对象,而11.1等均为类对象实例化出来的实例对象,type方法可以返回实例对象的类型

2. type方法返回新的类型对象

在python中可以静态创建类,也可以动态创建。type的第二个使用方法是动态创建新的类型对象,语法为type(name, bases, dict),其中name为类名,bases为基类的元组,dict为字典,存储类的属性

下面是静态创建类的一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Student(object):
s = 'harry' # 类属性

def __init__(self, name): # 实例方法
self.name = name # 实例属性

@classmethod # 类方法
def read(cls):
print("read paper")

@staticmethod # 静态方法
def song():
print("sing a song")


s1 = Student("bob")
s1.read() # read paper
s1.song() # sing a song

这里我们创建了一个Student类,其中有类属性,实例属性,类方法,静态方法,实例方法。随后我们实例化了这个类,并调用了两个函数,这就是静态创建类的方法。下面,我们可以使用type方法来动态创建类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 使用type()函数定义类
def __init__(self, name): # 实例方法
self.name = name # 实例属性

@classmethod # 类方法
def read(cls):
print("read paper")

@staticmethod # 静态方法
def song():
print("sing a song")

Student = type(
'Student',
(object,),
{
's': 'harry', # 类属性
'__init__': __init__,
'read': read,
'song': song
})

s1 = Student("bob") #同样都可以创建实例
s1.read() # read paper
s1.song() # sing a song

平时我们惊天创建类对象时,解释器内部会自动调用type函数来帮助我们创建对象

3. 什么时候用type方法?

在实际应用中,type的写法并不优美,并且缺乏整体性,不易读,书写麻烦,所以我们一般不会使用type方法来创建类,那什么时候会用呢?在实际构造神经网络时,我遇到了一个调用type函数的场景:现在我有一个语言模型A,一共有6个模块X,平时我们调用A就足够完成工作了,但是突然有一天我们需要对他进行改进,要在两两模块之间加入一个新模块Y,一个方法是将A拆开,然后再加入Y,这样写并不优美。另一个方法是使用type函数,单独写一个类B,里面有Y模块,然后用A继承B,并在B中将A模块的X与Y融合,然后替换X,即[X, Y] --> [X](这个很难去理解,如果理解不了就忽略这部分吧)

下面就用一个简单的例子展示一下怎么用(这个例子和我上面描述的没关系,只是给大家演示一个场景)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import torch.nn as nn
import torch

def extend_instance(obj, fc2):
fc1_cls = obj.__class__
fc1_cls_name = obj.__class__.__name__
obj.__class__ = type(
fc1_cls_name, (fc2, fc1_cls), {}
)

class fclayer1(nn.Module):
"Construct a linear module."
def __init__(self, features=10):
super(fclayer1, self).__init__()
self.linear = nn.Linear(features, features*2)

def forward(self, x):
x = self.linear(x)
return x

class fclayer2(nn.Module):
"Construct another module."
def doublex(self, x):
return x * 2

fc1 = fclayer1()
extend_instance(fc1, fclayer2)
print(fc1.doublex(10)) # 20

这里fclayer1本身没有doublex函数,通过extend_instance函数,我们将fclayer2中的doublex函数加入到了fclayer1中(其实就是将已经实例化的类对象再次实例化一下,额外继承了fclayer2类),这样我们就可以在fclayer1中调用doublex函数了

Error: API rate limit exceeded for 54.92.211.66. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)