Python 系列学习之十:面向对象编程 - 类型和属性检查

前言

打算写一系列文章来记录自己学习 Python 3 的点滴;本章主要介绍 Python 有关面向对象编程中的类型和属性检查的相关内容;

本文为作者的原创作品,转载需注明出处;

类型检查

有些时候,我们并不知道传入的对象的类型,便需要对其进行类型检查,备注,需要类型检查的场景在 Python 中更为常见,因为 Python 的参数是弱类型的,任何参数类型都可以传入;一般用于类型检查的方法有两个 typeisinstance 内置方法;

type

对象类型

  1. 判断类类型

    1
    2
    >>> type(Student)
    <class 'type'>

    可见类对象是签名为type的 class 类型,

  2. 判断实例类型

    1
    2
    3
    >>> linda = Student('Linda Boston', 100)
    >>> type(linda)
    <class '__main__.Student'>

    可见,实例同样是 class 类型,不过与 class 类型不同的是,它的签名是'__main__.Student',所以两者是不相等的

    1
    2
    >>> type(Student) == type(linda)
    False

    同一个 class 的不同实例拥有过相同的类型;

    1
    2
    3
    >>> jodan = Student('Jodan Tina', 20)
    >>> type(linda) == jodan
    True

不过用心的读者会发现,type 没有提供实例与类判断方法,既是通过判断方法得出该实例属于哪个类;这个场景将由 isinstance 提供;

基本类型

1
2
3
4
5
6
7
8
9
10
>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False

函数类型

这里需要使用到 Python 的内置对象types

1
2
3
4
5
6
7
8
9
10
11
12
>>> import types
>>> def fn():
... pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True

isinstance

对象类型

实例和类的直接关系,

1
2
3
>>> linda = Student('Linda Boston', 100)
>>> isinstance(linda, Student)
True

继承关系,

1
2
3
4
5
>>> linda = PrimaryStudent('Linda Boston', 100)
>>> isinstance(linda, PrimaryStudent)
True
>>> isinstance(linda, Student)
True

基本类型

1
2
3
4
5
6
>>> isinstance('a', str)
True
>>> isinstance(123, int)
True
>>> isinstance(b'a', bytes)
True

函数类型

1
2
3
4
5
6
7
8
9
10
11
12
>>> import types
>>> def fn():
... pass
...
>>> isinstance(fn, types.FunctionType)
True
>>> isinstance(abs, types.BuiltinFunctionType)
True
>>> isinstance(lambda x: x, types.LambdaType)
True
>>> isinstance((x for x in range(10)), types.GeneratorType)
True

总结

从上述分析可以看到,但凡是可以通过 type 的检查的方式统统可以由 isinstance 所替代,而且 isinstance 提供了更多的有用的工具方法,所以,笔者提倡在日常编码中尽量使用 isinstance;

属性检查

对象的属性检查主要通过如下两个方法来进行 dir()hasattr()

dir

比如说,我们要看 PrimaryStudent 的实例 linda 所拥有的所有属性和方法,

1
2
>>> dir(linda)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'print_score', 'say_hello', 'score']

可以看到,除了 PrimaryStudent 自定的属性(name、score)和方法(print_score、say_hello)意外,还有大量 Python 内置的方法和属性;而这些内置的方法和属性统统有一个规律就是使用__作为前缀和后缀;

下面,再来看一个 str 类型对象的所有属性和方法,

1
2
>>> dir('ABC')
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

hasattr

hasattr()是一个非常有用的方法,用来判断当前的实例对象是否有某个属性或者方法

1
2
3
4
>>> hasattr(linda, 'name')
True
>>> hasattr(linda, 'hobby')
False