Python中如何获取类属性的列表
这篇⽂章主要给⼤家介绍了在Python中如何获取类属性的列表,⽂中通过⽰例代码介绍的很详细,相信对⼤家的学习或者⼯作具有⼀定的参考借鉴价值,有需要的朋友可以参考借鉴,下⾯来⼀起看看吧。
前⾔
最近⼯作中遇到个需求是要得到⼀个类的静态属性,也就是说有个类 Type ,我要动态获取 Type.FTE 这个属性的值。
最简单的⽅案有两个:
1 2getattr(Type, 'FTE') Type.__dict__['FTE']
那么,如果要获取类属性的列表,该怎么做呢?
⾸先上场的是 dir ,它能返回当前范围的所有属性名称列表:
1 2 3 4>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__',
'__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reverd__', '__rmul__', '__tattr__', '__titem__', '__tslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'inrt', 'pop', 'remove', 'rever', 'sort']
可以配合使⽤ inspect 包中的功能来过滤:
1 2>>> [i for i in dir(list) if inspect.isbuiltin(getattr(list, i))] ['__new__', '__subclasshook__']
inspect 包中还包含:
1 2>>> [i for i in dir(inspect) if inspect.isfunction(getattr(inspect, i))]
['_archbas', 'classify_class_attrs', 'cleandoc', 'findsource', 'formatargspec', 'formatargvalues', 'getabsfile', 'getargs', 'getargspec',
'getargvalues', 'getblock', 'getcallargs', 'getclasstree', 'getcomments', 'getdoc', 'getfile', 'getframeinfo', 'getinnerframes', 'getlineno',
'getmembers', 'getmodule', 'getmoduleinfo', 'getmodulename', 'getmro', 'getouterframes', 'getsource', 'getsourcefile', 'getsourcelines',
'indentsize', 'isabstract', 'isbuiltin', 'isclass', 'iscode', 'isdatadescriptor', 'isframe', 'isfunction', 'isgenerator', 'isgeneratorfunction',
'isgettdescriptor', 'ismemberdescriptor', 'ismethod', 'ismethoddescriptor', 'ismodule', 'isroutine', 'istraceback', 'joinq', 'namedtuple', 'stack' , 'strq', 'trace', 'walktree']
还可以配合 callable 来使⽤:
1 2>>> [i for i in dir(inspect) if not callable(getattr(inspect, i))]
['CO_GENERATOR', 'CO_NESTED', 'CO_NEWLOCALS', 'CO_NOFREE', 'CO_OPTIMIZED', 'CO_VARARGS', 'CO_VARKEYWORDS',
'TPFLAGS_IS_ABSTRACT', '__author__', '__builtins__', '__date__', '__doc__', '__file__', '__name__', '__package__', '_filesbymodname', 'dis', 'imp', 'linecache', 'modulesbyfile', 'os', 're', 'string', 'sys', 'tokenize', 'types']
上⾯提到了 __dict__ ,也可以⽤它来获取属性列表:
文化自信的含义1 2>>> list.__dict__.keys()
['__getslice__', '__getattribute__', 'pop', 'remove', '__rmul__', '__lt__', '__sizeof__', '__init__', 'count', 'index', '__delslice__', '__new__', '__contains__', 'append', '__doc__', '__len__', '__mul__', 'sort', '__ne__', '__getitem__', 'inrt', '__titem__', '__add__', '__gt__',
'__eq__', 'rever', 'extend', '__delitem__', '__reverd__', '__imul__', '__tslice__', '__iter__', '__iadd__', '__le__', '__repr__', '__hash__' , '__ge__']
总结
以上就是在Python中得到类属性列表的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作能带来⼀定的帮助,如果有疑问⼤家可以留⾔交流。
原⽂链接:zengrong/post/2584.htm
⾸先通过⼀个例⼦来看⼀下本⽂中可能⽤到的对象和相关概念。
#coding:utf-8
import sys
def foo():pass class Cat(object): def __init__(lf, name='Kitty'): lf.name = name def sayHi(lf): print lf.name, 'says Hi!' cat = Cat() print Cat.sayHi print cat.sayHi
有时候我们会碰到这样的需求,需要执⾏对象的某个⽅法,或是需要对对象的某个字段赋值,⽽⽅法名或是字段名在编码代码时并不能确定,需要通过参数传递字符串的形式输⼊。举个具体的例⼦:当我们需要实现⼀个通⽤的DBM框架时,可能需要对数据对象的字段赋值,但我们⽆法预知⽤到这个框架的数据对象都有些什么字段,换⾔之,我们在写框架的时候需要通过某种机制访问未知的属性。
这个机制被称为反射(反过来让对象告诉我们他是什么),或是⾃省(让对象⾃⼰告诉我们他是什么,好吧我承认括号⾥是我瞎掰的- -#),⽤于实现在运⾏时获取未知对象的信息。反射是个很吓唬⼈的名词,听起来⾼深莫测,在⼀般的编程语⾔⾥反射相对其他概念来说稍显复杂,⼀般来说都是作为⾼级主题来讲;但在Python中反射⾮常简单,⽤起来⼏乎感觉不到与其他的代码有区别,使⽤反射获取到的函数和⽅法可以像平常⼀样加上括号直接调⽤,获取到类后可以直接构造实例;不过获取到的
心脏不好吃什么好字段不能直接赋值,因为拿到的其实是另⼀个指向同⼀个地⽅的引⽤,赋值只能改变当前的这个引⽤⽽已。
1. 访问对象的属性
以下列出了⼏个内建⽅法,可以⽤来检查或是访问对象的属性。这些⽅法可以⽤于任意对象⽽不仅仅是例⼦中的Cat实例对象;Python中⼀切都是对象。
#coding:utf-8
from a import *
cat = Cat('kitty') print cat.name cat.sayHi() #调⽤实例⽅法print dir(cat) if hasattr(cat, 'name'): #检查实例是否有这个属性 tattr(cat, 'name', 'tiger') #same as: a.name = 'tiger' print getattr(cat, 'name') #same as: print a.name getattr(cat, 'sayHi')()
dir([obj]):
往事如歌调⽤这个⽅法将返回包含obj⼤多数属性名的列表(会有⼀些特殊的属性不包含在内)。obj的默认值是当前的模块对象。
hasattr(obj, attr):
这个⽅法⽤于检查obj是否有⼀个名为attr的值的属性,返回⼀个布尔值。
getattr(obj, attr):
调⽤这个⽅法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。
tattr(obj, attr, val):
调⽤这个⽅法将给obj的名为attr的值的属性赋值为val。例如如果attr为’bar’,则相当于obj.bar = val。
2. 访问对象的元数据
当你对⼀个你构造的对象使⽤dir()时,可能会发现列表中的很多属性并不是你定义的。这些属性⼀般保存了对象的元数据,⽐如类的
__name__属性保存了类名。⼤部分这些属性都可以修改,不过改动它们意义并不是很⼤;修改其中某些属性如function.func_code还可能导致很难发现的问题,所以改改name什么的就好了,其他的属性不要在不了解后果的情况下修改。
接下来列出特定对象的⼀些特殊属性。另外,Python的⽂档中有提到部分属性不⼀定会⼀直提供,下⽂中将以红⾊的星号*标记,使⽤前你可以先打开解释器确认⼀下。
2.0. 准备⼯作:确定对象的类型
在types模块中定义了全部的Python内置类型,结合内置⽅法isinstance()就可以确定对象的具体类型了。
isinstance(object, classinfo):
检查object是不是classinfo中列举出的类型,返回布尔值。classinfo可以是⼀个具体的类型,也可以是多个类型的元组或列表。
types模块中仅仅定义了类型,⽽inspect模块中封装了很多检查类型的⽅法,⽐直接使⽤types模块更为轻松,所以这⾥不给出关于types 的更多介绍,如有需要可以直接查看types模块的⽂档说明。本⽂第3节中介绍了inspect模块。
2.1. 模块(module)
__doc__: ⽂档字符串。如果模块没有⽂档,这个值是None。
会动的房子故事
开学啦图片
*__name__: 始终是定义时的模块名;即使你使⽤import .. as 为它取了别名,或是赋值给了另⼀个变量名。
*__dict__: 包含了模块⾥可⽤的属性名-属性的字典;也就是可以使⽤模块名.属性名访问的对象。
__file__: 包含了该模块的⽂件路径。需要注意的是内建的模块没有这个属性,访问它会抛出异常!
#coding:utf-8
import fnmatch as m
print m.__doc__.splitlines()[0] print m.__name__ print m.__file__ print m.__dict__.items()[0]
__dict__ 返回属性、⽅法对象名值的字典,⽽dir仅仅是个属性、⽅法名的列表。
2.2. 类(class)
__doc__: ⽂档字符串。如果类没有⽂档,这个值是None。
*__name__: 始终是定义时的类名。
*__dict__: 包含了类⾥可⽤的属性名-属性的字典;也就是可以使⽤类名.属性名访问的对象。
__module__: 包含该类的定义的模块名;需要注意,是字符串形式的模块名⽽不是模块对象。
*__bas__: 直接⽗类对象的元组;但不包含继承树更上层的其他类,⽐如⽗类的⽗类
#coding:utf-8
from a import *
print Cat.__doc__ #None Cat类没有doc print Cat.__name__ #Cat print Cat.__module__ # a 如果在⾃⾝的module中执⾏时__main__ print
Cat.__bas__ #(<type 'object'>,) print Cat.__dict__ # ⼀个属性、⽅法对象名值的字典
2.3. 实例(instance)
实例是指类实例化以后的对象。
*__dict__: 包含了可⽤的属性名-属性对象字典。
*__class__: 该实例的类对象。对于类Cat,cat.__class__ == Cat 为 True。
#coding:utf-8
from a import *
print cat.__dict__ #{'name': 'Kitty'} 仅仅有属性,没有⽅法print cat.__class__ #<class 'a.Cat'> print cat.__class__ == Cat #True
2.4. 内建函数和⽅法(built-in functions and methods)
根据定义,内建的(built-in)模块是指使⽤C写的模块,可以通过sys模块的builtin_module_names字段查看都有哪些模块是内建的。这些模块中的函数和⽅法可以使⽤的属性⽐较少,不过⼀般也不需要在代码中查看它们的信息。
__doc__: 函数或⽅法的⽂档。
__name__: 函数或⽅法定义时的名字。
__lf__: 仅⽅法可⽤,如果是绑定的(bound),则指向调⽤该⽅法的类(如果是类⽅法)或实例(如果是实例⽅法),否则为None。
*__module__: 函数或⽅法所在的模块名。
2.5. 函数(function)
这⾥特指⾮内建的函数。注意,在类中使⽤def定义的是⽅法,⽅法与函数虽然有相似的⾏为,但它们是不同的概念。
__doc__: 函数的⽂档;另外也可以⽤属性名func_doc。
__name__: 函数定义时的函数名;另外也可以⽤属性名func_name。
*__module__: 包含该函数定义的模块名;同样注意,是模块名⽽不是模块对象。
*__dict__: 函数的可⽤属性;另外也可以⽤属性名func_dict。 不要忘了函数也是对象,可以使⽤函数.属性名访问属性(赋值时如果属性不存在将新增⼀个),或使⽤内置函数has/get/tattr()访问。不过,在函数中保存属性的意义并不⼤。
func_defaults: 这个属性保存了函数的参数默认值元组;因为默认值总是靠后的参数才有,所以不使⽤字典的形式也是可以与参数对应上的。
func_code: 这个属性指向⼀个该函数对应的code对象,code对象中定义了其他的⼀些特殊属性,将在下⽂中另外介绍。
func_globals: 这个属性指向当前的全局命名空间⽽不是定义函数时的全局命名空间,⽤处不⼤,并且是只读的。
*func_closure: 这个属性仅当函数是⼀个闭包时有效,指向⼀个保存了所引⽤到的外部函数的变量cell的元组,这个属性也是只读的。
(通过func_closure可以查看必报)
#coding:utf-8
def foo():
name = 'zhangsan' age = 11 def bar(): print name, age return bar closure = foo() print closure.func_closure # (<cell at 0x7f2fa7d36558: int object at
0x19f7b78>, <cell at 0x7f2fa7d36590: str object at 0x7f2fa7d37450>) for cell in closure.func_closure: ll_contents # zhangsan # 11
2.6. ⽅法(method)
⽅法虽然不是函数,但可以理解为在函数外⾯加了⼀层外壳;拿到⽅法⾥实际的函数以后,就可以使⽤2.5节的属性了。
__doc__: 与函数相同。
__name__: 与函数相同。
*__module__: 与函数相同。
im_func: 使⽤这个属性可以拿到⽅法⾥实际的函数对象的引⽤。另外如果是2.6以上的版本,还可以使⽤属性名__func__。
im_lf: 如果是绑定的(bound),则指向调⽤该⽅法的类(如果是类⽅法)或实例(如果是实例⽅法),否则为None。如果是2.6以上的版本,还可以使⽤属性名__lf__。
im_class: 实际调⽤该⽅法的类,或实际调⽤该⽅法的实例的类。注意不是⽅法的定义所在的类,如果有继承关系的话。
这⾥讨论的是⼀般的实例⽅法,另外还有两种特殊的⽅法分别是类⽅法(classmethod)和静态⽅法(staticmethod)。类⽅法还是⽅法,不过因为需要使⽤类名调⽤,所以他始终是绑定的;⽽静态⽅法可以看成是在类的命名空间⾥的函数(需要使⽤类名调⽤的函数),它只能使⽤函数的属性,不能使⽤⽅法的属性。
#coding:utf-8
class Dog(object):
def imeth(lf): print 'instance method ', lf @classmethod def cmeth(cls): print 'class method ', cls @staticmethod def smeth(): print 'static method ' dog = Dog() dog.imeth() #实例调⽤绑定⽅法 Dog.imeth(dog) #类调⽤未绑定⽅法 h() # 类调⽤类⽅法 Dog.smeth() # 类调⽤静态⽅法 # 实例虽然也可以调⽤类⽅法和静态⽅法,但是没有多⼤意义,类⽅法依旧绑定类本⾝h() dog.smeth() print '============================' print dog.imeth.__lf__ #<__main__.Dog object at 0x7f9a69d04e10> print Dog.imeth.__lf__ #None 未绑定h.__lf__ #<class
'__main__.Dog'> h.__lf__ #<class '__main__.Dog'> 使⽤实例调⽤类⽅法没有多⼤意义,依旧绑定类本⾝ #print Dog.smeth.__lf__ # 静态⽅法可以理解为类中的函数(function),所以没有__lf__
感触
2.7. ⽣成器(generator)
⽣成器是调⽤⼀个⽣成器函数(generator function)返回的对象,多⽤于集合对象的迭代。
__iter__: 仅仅是⼀个可迭代的标记。
gi_code: ⽣成器对应的code对象。
gi_frame: ⽣成器对应的frame对象。
gi_running: ⽣成器函数是否在执⾏。⽣成器函数在yield以后、执⾏yield的下⼀⾏代码前处于frozen状态,此时这个属性的值为0。
next|clo|nd|throw: 这是⼏个可调⽤的⽅法,并不包含元数据信息,如何使⽤可以查看⽣成器的相关⽂档。
#coding:utf-8
def gen():
for n in xrange(5): yield n g = gen() print g print g.gi_code print g.gi_frame print g.gi_running
接下来讨论的是⼏个不常⽤到的内置对象类型。这些类型在正常的编码过程中应该很少接触,除⾮你正在⾃⼰实现⼀个解释器或开发环境之类。所以这⾥只列出⼀部分属性,如果需要⼀份完整的属性表或想进⼀步了解,可以查看⽂末列出的参考⽂档。
儿童手抄报2.8. 代码块(code)
代码块可以由类源代码、函数源代码或是⼀个简单的语句代码编译得到。这⾥我们只考虑它指代⼀个函数时的情况;2.5节中我们曾提到可以使⽤函数的func_code属性获取到它。code的属性全部是只读的。
co_argcount: 普通参数的总数,不包括*参数和**参数。
co_varnames: 所有的参数名(包括*参数和**参数)和局部变量名的元组。
你什么时候需要我
co_filename: 源代码所在的⽂件名。
co_flags: 这是⼀个数值,每⼀个⼆进制位都包含了特定信息。较关注的是0b100(0×4)和0b1000(0×8),如果co_flags &