Python 反射怎么用?如何通过反射获取和操作类属性与方法?

文章导读
Previous Quiz Next 在面向对象编程中,reflection(反射)指的是提取正在使用中的任何对象信息的特性。您可以了解对象的类型、它是否是其他 class 的子类、它的属性是什么,以及更多信息。Python 的标准库提供了几个函数来反射对象的不同属性。Re
📋 目录
  1. type() 函数
  2. isinstance() 函数
  3. issubclass() 函数
  4. callable() 函数
  5. getattr() 函数
  6. setattr() 函数
  7. hasattr() 函数
  8. dir() 函数
A A

Python - 反射



Previous
Quiz
Next

在面向对象编程中,reflection(反射)指的是提取正在使用中的任何对象信息的特性。您可以了解对象的类型、它是否是其他 class 的子类、它的属性是什么,以及更多信息。Python 的标准库提供了几个函数来反射对象的不同属性。Reflection 有时也被称为 introspect(内省)。

以下是 Python 中的反射函数列表 −

  • type() Function
  • isinstance() Function
  • issubclass() Function
  • callable() Function
  • getattr() Function
  • setattr() Function
  • hasattr() Function
  • dir() Function

type() 函数

我们已经多次使用过这个函数。它告诉您对象属于哪个 class。

示例

以下语句打印不同内置数据类型对象的相应 class

print (type(10))
print (type(2.56))
print (type(2+3j))
print (type("Hello World"))
print (type([1,2,3]))
print (type({1:'one', 2:'two'}))

这里,您将得到以下 输出

<class 'int'>
<class 'float'>
<class 'complex'>
<class 'str'>
<class 'list'>
<class 'dict'>

让我们验证用户定义 class 的对象类型 −

class test:
   pass
   
obj = test()
print (type(obj))

它将产生以下 输出

<class '__main__.test'>

isinstance() 函数

这是 Python 中的另一个内置函数,用于确定对象是否是给定 class 的实例。

语法

isinstance(obj, class)

这个函数总是返回一个布尔值,如果对象确实属于给定的 class 则为 true,否则为 false。

示例

以下语句返回 True −

print (isinstance(10, int))
print (isinstance(2.56, float))
print (isinstance(2+3j, complex))
print (isinstance("Hello World", str))

它将产生以下 输出

True
True
True
True

相反,这些语句打印 False。

print (isinstance([1,2,3], tuple))
print (isinstance({1:'one', 2:'two'}, set))

它将产生以下 输出

False
False

您也可以对用户定义的 class 进行检查

class test:
   pass
   
obj = test()
print (isinstance(obj, test))

它将产生以下 输出

True

在 Python 中,class 本身也是对象。所有 class 都是 object class 的对象。这可以通过以下代码验证 −

class test:
   pass
   
print (isinstance(int, object))
print (isinstance(str, object))
print (isinstance(test, object))

以上所有打印语句都会输出 True。

issubclass() 函数

这个函数检查一个 class 是否是另一个 class 的子类。它适用于 class,而不是它们的实例。

如前所述,所有 Python class 都继承自 object class。因此,以下打印语句的输出均为 True。

class test:
   pass
   
print (issubclass(int, object))
print (issubclass(str, object))
print (issubclass(test, object))

它将产生以下 输出

True
True
True

callable() 函数

如果一个对象能够调用某个过程,则称其为可调用对象。Python 函数执行某个过程,因此是可调用对象。因此 callable(function) 返回 True。任何函数,包括内置函数、用户定义函数或方法,都是可调用对象。内置数据类型如 int、str 等的对象不是可调用对象。

示例

def test():
   pass
   
print (callable("Hello"))
print (callable(abs))
print (callable(list.clear([1,2])))
print (callable(test))

字符串对象不是可调用对象。但 abs 是一个函数,是可调用对象。list 的 pop 方法是可调用对象,但 clear() 实际上是函数的调用,而不是函数对象,因此不是可调用对象。

它将产生以下输出

False
True
True
False
True

如果一个 class 实例具有 __call__() 方法,则它是可调用对象。在下面的示例中,test class 包含 __call__() 方法。因此,其对象可以像调用函数一样使用。因此,具有 __call__() 函数的 class 对象是可调用对象。

class test:
   def __init__(self):
      pass
   def __call__(self):
      print ("Hello")
      
obj = test()
obj()
print ("obj is callable?", callable(obj))

它将产生以下输出

Hello
obj is callable? True

getattr() 函数

getattr() 内置函数用于获取对象的指定属性的值。

示例

class test:
   def __init__(self):
      self.name = "Manav"
      
obj = test()
print (getattr(obj, "name"))

它将产生以下输出

Manav

setattr() 函数

setattr() 内置函数为对象添加新属性并为其赋值。它也可以更改现有属性的值。

在下面的示例中,test class 的对象只有一个属性 − name。我们使用 setattr() 添加 age 属性并修改 name 属性的值。

class test:
   def __init__(self):
      self.name = "Manav"
      
obj = test()
setattr(obj, "age", 20)
setattr(obj, "name", "Madhav")
print (obj.name, obj.age)

它将产生以下输出

Madhav 20

hasattr() 函数

这个内置函数如果对象参数具有指定的属性,则返回 True,否则返回 False。我们使用相同的 test class 来检查它是否具有某个属性。

class test:
   def __init__(self):
      self.name = "Manav"
      
obj = test()
print (hasattr(obj, "age"))
print (hasattr(obj, "name"))

它将产生以下输出

False
True

dir() 函数

如果这个内置函数在没有参数的情况下被调用,它会返回当前作用域中的名称。对于任何作为参数的对象,它会返回给定对象及其可达属性的属性列表。

  • 对于 module object − 该函数返回 module 的属性。

  • 对于 class object − 该函数返回其属性,以及其基类的属性(递归)。

  • 对于任何其他对象 − 其属性、其 class 的属性,以及其 class 的基类属性(递归)。

示例

print ("dir(int):", dir(int))

它将产生以下输出

dir(int): ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

示例

print ("dir(dict):", dir(dict))

它将产生以下输出

dir(dict): ['__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__ior__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

示例

class test:
   def __init__(self):
      self.name = "Manav"

obj = test()
print ("dir(obj):", dir(obj))

它将产生以下输出

dir(obj): ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']