DAY 5. python自省
這是很久之前寫的,當時對自省和反射的概念沒理解,學習Java以后多了一點理解,自省是獲取對象的能力,反射是操縱對象的能力,python中使用getattr()
和setattr()
實現反射,而其他的則是自省,下面的內容是把兩者混在一起說的,但又不想改了,內容羅里吧嗦,把最終的總結提到前面
方法 | 作用 |
---|---|
help() | 查看函數或模塊用途的詳細說明 |
dir() | 返回對象所有屬性 |
type() | 查看對象類型 |
hasattr() | 查看對象是否有特定屬性 |
getattr() | 得到對象的特定屬性 |
setattr() | 設置對象的特定屬性 |
isinstance() | 判斷一個對象是否是一個已知的類型 |
issubclass() | 判斷一個類是不是另一個類的子類 |
id() | 返回地址值 |
callable() | 判斷對象是否可調用 |
In computing, type introspection is the ability of a program to examine the type or properties of an object at runtime. Some programming languages possess this capability.
在計算機科學中,內省是指計算機程序在運行時(Run time)檢查對象(Object)類型的一種能力,通常也可以稱作運行時類型檢查
這是維基百科對自省(內省)的解釋,通俗來說,自省就是在程序運行過程中,能夠知道對象的類型的一種能力,大部分語言都有這種能力(都有辦法在運行過程中知道對象的類型),如c++,Java等
當然自省不僅僅只針對對象的類型,如python自省還能知道對象的屬性,還有一些其他的理解
在日常生活中,自省(introspection)是一種自我檢查行為。
在計算機編程中,自省是指這種能力:檢查某些事物以確定它是什么、它知道什么以及它能做什么。自省向程序員提供了極大的靈活性和控制力。
說的更簡單直白一點:自省就是面向對象的語言所寫的程序在運行時,能夠知道對象的類型。簡單一句就是,運行時能夠獲知對象的類型。
例如c++自省(來自維基百科)
C ++通過運行時類型信息(RTTI)typeid和dynamic_cast關鍵字支持類型內省。 dynamic_cast表達式可用于確定特定對象是否屬于特定派生類。 例如:
Person* p = dynamic_cast<Person *>(obj);
if (p != nullptr) {p->walk();
}
typeid運算符檢索std :: type_info對象,該對象描述對象的派生類型:
if (typeid(Person) == typeid(*obj)) {serialize_person( obj );
}
php自省(來自維基百科)
在php中,可以使用instanceof運算符判斷一個PHP變量是否屬于某一類的實例
if ($obj instanceof Person) {// Do whatever you want
}
Java自省(來自維基百科)
Java中類型自省的最簡單示例是instanceof運算符。 instanceof運算符確定特定對象是屬于特定類(或該類的子類,還是實現該接口的類)。 例如:
if (obj instanceof Person) {Person p = (Person)obj;p.walk();
}
5.1 python實現自省的辦法
python實現自省有很多方法,常用的有 help(),dir(),type(),hasattr(),getattr(),setattr(),isinstance(),issubclass(),id(),callable()
5.1.1 help()
help() 函數用于查看函數或模塊用途的詳細說明。主要在IDE環境下是用,接受任何擁有函數或者方法的對象,打印出對象所有的函數和文檔字符串
如可以直接打印出os模塊的幫助文檔
import os
help(os)
# Help on module os:
#
# NAME
# os - OS routines for NT or Posix depending on what system we're on.
#
# DESCRIPTION
# 后面的省略了
也可以是我們自定義的類,函數,或模塊
class Demo:"""this is a Demo"""classVar = 0def __init__(self):self.var1 = 1def output(self):print(self.var1)if __name__ == '__main__':help(Demo)
運行之后會打印出這個類的完整信息
Help on class Demo in module __main__:class Demo(builtins.object)| this is a Demo| | Methods defined here:| | __init__(self)| Initialize self. See help(type(self)) for accurate signature.| | output(self)| | ----------------------------------------------------------------------| Data descriptors defined here:| | __dict__| dictionary for instance variables (if defined)| | __weakref__| list of weak references to the object (if defined)| | ----------------------------------------------------------------------| Data and other attributes defined here:| | classVar = 0
實例對象會打印出類的信息
函數會打印出幫助文檔,沒有文檔會打印none
def demoMethods(a):"""這是一個示例函數:param a: 示例形參:return: None"""print(a)help(demoMethods)
# Help on function demoMethods in module __main__:# demoMethods(a)
# 這是一個示例函數
# :param a: 示例形參
# :return: None
更詳細的請看這篇文章
Python-自省機制
5.1.2 dir()
dir() 函數不帶參數時,返回當前范圍內的變量、方法和定義的類型列表;帶參數時,返回參數的屬性、方法列表。如果參數包含方法__dir__(),該方法將被調用。如果參數不包含__dir__(),該方法將最大限度地收集參數信息。
dir()
['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'sys']
dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
5.1.3 hasattr(),getattr(),setattr()
class Demo:def __init__(self):self.var1 = 0self.var2 = 1if __name__ == '__main__':demo = Demo()if hasattr(demo,'var1'):setattr(demo,'var1',2)print(getattr(demo,'var1','not find')) # 2print(getattr(demo,'var11','not find')) # not find
- hasattr()
def hasattr(*args, **kwargs): # real signature unknown"""Return whether the object has an attribute with the given name.返回對象是否具有給定名稱的屬性。This is done by calling getattr(obj, name) and catching AttributeError.這是通過調用getattr(obj,name)并捕獲AttributeError來完成的."""pass
- setattr()
def setattr(x, y, v): # real signature unknown; restored from __doc__"""Sets the named attribute on the given object to the specified value.將給定對象的命名屬性設置為指定值。setattr(x, 'y', v) is equivalent to ``x.y = v''setattr(x,‘y’,v)等價于“x.y=v”"""pass
- getattr()
def getattr(object, name, default=None): # known special case of getattr"""getattr(object, name[, default]) -> valueGet a named attribute from an object; getattr(x, 'y') is equivalent to x.y.When a default argument is given, it is returned when the attribute doesn'texist; without it, an exception is raised in that case.從對象中獲取指定名稱的屬性;getattr(x,‘y’)等同于X.Y。如果給定了默認參數,則未找到該屬性時將返回該參數。如果未指定,則會引發異常。"""pass
5.1.4 isinstance(),issubclass()
>>> help(isinstance)
Help on built-in function isinstance in module builtins:isinstance(obj, class_or_tuple, /)Return whether an object is an instance of a class or of a subclass thereof.返回對象是類的實例還是其子類的實例。A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target tocheck against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)or ...`` etc.
instance類似于type(),只不過type() 不會認為子類是一種父類類型,不考慮繼承關系。isinstance() 會認為子類是一種父類類型,考慮繼承關系。
>>> class A:pass>>> a = A()
>>> isinstance(a,type)
False
>>> class B(A):pass>>> b=B()
>>> isinstance(b,A)
True
>>> isinstance(int,type)
True
>>> isinstance(A,type)
True
>>> isinstance(b,type)
False
>>> isinstance(True,int)
True
可以看出類是type的子類型,也驗證了前天的元類,而布爾是int的子類
而issubclass()則是用來判斷一個類是不是另一個類的子類,傳入的兩個參數都是類名
>>> issubclass(B,A)
True
5.1.5 id()和callable()
- id(): 用于獲取對象的內存地址
- callable():判斷對象是否可以被調用。
5.1.6 type()
這個函數在元類中寫過了,當傳入一個參數時會返回對象的類型,這也是python自省中比較常用的方法
5.2 總結
- 什么是自省
簡單來說就是在程序運行過程中能知道對象類型(還有屬性等)的能力
- python實現自省的方法
方法 | 作用 |
---|---|
help() | 查看函數或模塊用途的詳細說明 |
dir() | 返回對象所有屬性 |
type() | 查看對象類型 |
hasattr() | 查看對象是否有特定屬性 |
getattr() | 得到對象的特定屬性 |
seetattr() | 設置對象的特定屬性 |
isinstance() | 判斷一個對象是否是一個已知的類型 |
issubclass() | 判斷一個類是不是另一個類的子類 |
id() | 返回地址值 |
callable() | 判斷對象是否可調用 |
參考文章
python面試題
wikipedia Type introspection
Python自省(反射)指南【轉】
在這篇文章中說
在筆者,也就是我的概念里,自省和反射是一回事,當然其實我并不十分確定一定以及肯定…
但是我在維基百科看見了這句話
Introspection should not be confused with reflection, which goes a step further and is the ability for a program to manipulate the values, meta-data, properties and/or functions of an object at runtime.
也就是說自省和反射不是同一回事,自省是獲取對象類型的能力,而反射是操縱對象的值,元數據,屬性和/或函數的能力
Python常用的自省函數
Python-自省機制
Python自省
菜鳥教程