python 中 type 的使用
python
本文字数:1k 字 | 阅读时长 ≈ 4 min

python 中 type 的使用

python
本文字数:1k 字 | 阅读时长 ≈ 4 min

type 函数

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

type()方法语法如下

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

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

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

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 为字典,存储类的属性

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

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 方法来动态创建类


# 使用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](这个很难去理解,如果理解不了就忽略这部分吧)

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

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 函数了

4月 06, 2025
3月 10, 2025
12月 31, 2024