python的__dict__与dir()的区别,与python3对不显式继承的自定义类默认继承自object类的隐含操作

1、dir(object)

在python3.8解释器中help(dir):

Help on built-in function dir in module builtins:

dir(...)
    dir([object]) -> list of strings
    
    If called without an argument, return the names in the current scope.
    Else, return an alphabetized list of names comprising (some of) the attributes
    of the given object, and of attributes reachable from it.
    If the object supplies a method named __dir__, it will be used; otherwise
    the default dir() logic is used and returns:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.

翻译:dir()是定义在builtins模块的内置函数,语法为dir([object]),返回一个字符串列表。如果不带参数调用,则返回当前作用域中的名字。如果给定参数,则返回构成给定对象的属性的名字的按字母排序的列表(字符串列表),以及从它可获得的属性(attributes reachable from it)(比如类型对象的递归基类的属性,类实例对象的递归基类的属性)

如果对象提供了一个名为"__dir__"的方法,则会使用这个方法;否则使用默认的dir()逻辑并返回。

对一个模块对象:返回模块的属性

对一个类型对象<class 'type'>:返回它的属性以及递归的基类的属性

对任何其他对象:返回它的属性,它的类的属性,(类型对象的属性可以与类的属性不同,详见后面),以及递归地它的类的基类的属性

参考自:python的dir()和__dict__属性的区别,里面所说的"只要是有属性的数据对象(不一定是面向对象的对象实例,而是指具有数据类型的数据对象),都可以通过__dict__和dir()来显示对象属性"讲的意思就是dir(object)的object可以是一个模块对象、一个类型对象<class 'type'>、一个函数对象、一个类方法对象、或任何其他面向对象的类实例对象

         另外,对类实例对象object,dir(object)只有当对象调用某实例方法创建了某非实例方法的属性后,这个属性才会被加进dir(object)函数返回的对象属性名列表中

        举个栗子:        

#-*-encoding:utf-8-*-
class person:
    def SetBaseData(self):
        self.basedata='base'

if __name__ == "__main__":
    print('--------------------1')

    print('dir(类型对象person):')
    print(dir(person)) #dir(基类类型对象)
     
    objbase=person()
    print('dir(实例对象objbase):')
    print(dir(objbase))

    objbase.SetBaseData()
    
    print('--------------------2')
    print('dir(类型对象person):')
    print(dir(person)) #dir(基类类型对象)
     
    print('dir(实例对象objbase):')
    print(dir(objbase))

        python2.7的输出结果:

​
haypin@ubt:~/Files$ python2.7 m07263.py
--------------------1
dir(类型对象person):
['SetBaseData', '__doc__', '__module__']
dir(实例对象objbase):
['SetBaseData', '__doc__', '__module__']
--------------------2
dir(类型对象person):
['SetBaseData', '__doc__', '__module__']
dir(实例对象objbase):
['SetBaseData', '__doc__', '__module__', 'basedata']
haypin@ubt:~/Files$ 

​

        可以看到,dir(类型对象)始终只输出类方法与'__doc__'与'__module__',而在类的实例对象调用方法SetBaseData()创建了属性basedata后,dir(类型对象)才输出属性名'basedata'

2、object.__dict__

        __dict__是对象的一个属性,object.__dict__返回对象的名字空间(对象的属性名:属性值的一个字典)自己定义的类就算不定义并初始化__dict__属性,python解释器也会帮助生成__dict__属性

#-*-encoding:utf-8-*-
class person:
    def SetBaseData(self):
        self.basedata='base'

print(type(person)) #类型对象<class 'type'>(python3.8)  <type 'classobj'>(python2.7)
print('person.__dict__:') 
for k, v in person.__dict__.items():
    print("%s : %s" % (k,v))

print('--------------')
obj1=person()
print(type(obj1)) #类实例对象<class '__main__.person'>(python3.8) <type 'instance'>(python2.7)
print('obj1.__dict__:') 
for k, v in obj1.__dict__.items():
    print("%s : %s" % (k,v))

print('--------------')
obj1.SetBaseData()
print('obj1.__dict__:') 
for k, v in obj1.__dict__.items():
    print("%s : %s" % (k,v))

用python2.7执行输出:

haypin@ubt:~/Files$ python2.7 m07262.py
<type 'classobj'>
person.__dict__:
__module__ : __main__
SetBaseData : <function SetBaseData at 0x7f4bbde01d50>
__doc__ : None
--------------
<type 'instance'>
obj1.__dict__:
--------------
obj1.__dict__:
basedata : base
haypin@ubt:~/Files$

用python3.8执行输出:

haypin@ubt:~/Files$ python3.8 m07262.py
<class 'type'>
person.__dict__:
__module__ : __main__
SetBaseData : <function person.SetBaseData at 0x7f4e48c2fca0>
__dict__ : <attribute '__dict__' of 'person' objects>
__weakref__ : <attribute '__weakref__' of 'person' objects>
__doc__ : None
--------------
<class '__main__.person'>
obj1.__dict__:
--------------
obj1.__dict__:
basedata : base
haypin@ubt:~/Files$

因为python中一切都是对象,模块、类型、类实例、函数、方法,都被python视为对象,而对象的特征就是要有属性去描述它,上面自定义的person类,虽然没有定义__dict__属性,但python2.7与python3.8都会自动为类型person及其实例对象增加属性__dict__,类型person(或者说类型对象person)具有①类型定义所在模块__module__;②用户定义的属性;③属性__dict__;④__weakref__;⑤类型的文档字符串__doc__;

        类实例则只有当已经调用某方法为类实例创建某属性后才具有那个属性,比如不传参生成的类实例obj1由于没有定义__init__(self,*)初始化方法创建任何属性,所以定义后没有任何属性,只有当调用方法SetBaseData()为类实例创建某属性后,该实例才算具有了那个属性,也才会被录入实例的__dict__属性的对象属性字典中。

        另外python2将type(类型对象)称作<type 'classobj'>,将type(类实例对象)称作<type 'instance'>;而python3将type(类型对象)称作<class 'type'>,将type(类实例对象)称作<class '模块.类名'>,如上<class '__main__.person'>

3、dir(object)与object.__dict__的区别

         参考自python的dir()和__dict__属性的区别:只要是有属性的数据对象(不一定是面向对象的类实例对象,而是指具有数据类型的数据对象),即可以是一个模块对象、一个类型对象<class 'type'>、一个函数对象、一个类方法对象、或任何其他面向对象的类实例对象

        用(object).__dict__举个栗子:

#-*-encoding:utf-8-*-
class person:
    def SetBaseData(self):
        self.basedata='base'

print(type(person)) #类型对象<class 'type'>(python3.8)  <type 'classobj'>(python2.7)
print('类型对象person.__dict__:') 
for k, v in person.__dict__.items():
    print("%s : %s" % (k,v))

print('--------------1')
obj1=person()
print(type(obj1)) #类实例对象<class '__main__.person'>(python3.8) <type 'instance'>(python2.7)
print('类实例对象obj1.__dict__:') 
for k, v in obj1.__dict__.items():
    print("%s : %s" % (k,v))

print('--------------2')
obj1.SetBaseData()
print('类实例对象obj1.__dict__:') 
for k, v in obj1.__dict__.items():
    print("%s : %s" % (k,v))

def sayhalo():
    print('Hallo')
print('--------------3')
print('函数sayhalo.__dict__:') #函数对象
for k, v in sayhalo.__dict__.items():
    print("%s : %s" % (k,v))

print('--------------4')
print('类方法对象person.SetBaseData.__dict__:') #类方法对象
for k, v in person.SetBaseData.__dict__.items():
    print("%s : %s" % (k,v))

        python2.7输出:

haypin@ubt:~/Files$ python2.7 m07262.py
<type 'classobj'>
类型对象person.__dict__:
__module__ : __main__
SetBaseData : <function SetBaseData at 0x7fa642677150>
__doc__ : None
--------------1
<type 'instance'>
类实例对象obj1.__dict__:
--------------2
类实例对象obj1.__dict__:
basedata : base
--------------3
函数sayhalo.__dict__:
--------------4
类方法对象person.SetBaseData.__dict__:
haypin@ubt:~/Files$

        object.__init__可以看作是数据对象object的名字空间,所以只包含自己的属性名:属性值的字典,且可以直接增、删、改、查字典内容

        dir(object),dir()是定义在builtins模块的内置函数,语法为dir([object]),返回一个字符串列表。如果不带参数调用,则返回当前作用域中的名字。如果给定参数,则返回构成给定对象的属性的名字的按字母排序的列表(字符串列表),以及从它可获得的属性(attributes reachable from it)(比如类型对象的递归基类的属性,类实例对象的递归基类的属性)

        用python2.7举个栗子:

#-*-encoding:utf-8-*-
class person:
    def SetBaseData(self):
        self.basedata='base'

class rich(person):
    def SetDerivedData(self):
        self.deriveddata='derived'

if __name__ == "__main__":
    print('基类类型对象person.__dict__:') 
    for k, v in person.__dict__.items(): #基类类型对象.__dict__
        print("%s : %s" % (k,v))
    print('dir(基类类型对象person):')
    print(dir(person)) #dir(基类类型对象)
     
    print('--------------------')
     
    print('派生类类型对象rich.__dict__:') 
    for k, v in rich.__dict__.items(): #派生类类型对象.__dict__
        print("%s : %s" % (k,v))
    print('dir(派生类类型对象rich):') 
    print(dir(rich)) #dir(派生类类型对象)


        输出:

haypin@ubt:~/Files$ python2.7 m0726.py
基类类型对象person.__dict__:
__module__ : __main__
SetBaseData : <function SetBaseData at 0x7f9c3ad761d0>
__doc__ : None
dir(基类类型对象person):
['SetBaseData', '__doc__', '__module__']
--------------------
派生类类型对象rich.__dict__:
__module__ : __main__
SetDerivedData : <function SetDerivedData at 0x7f9c3ad76250>
__doc__ : None
dir(派生类类型对象rich):
['SetBaseData', 'SetDerivedData', '__doc__', '__module__']
haypin@ubt:~/Files$

        dir(派生类rich)除了包含自己定义的属性SetDeriveData外还包含了继承自基类的属性SetBaseData,而派生类类型对象rich.__dict__与基类类型对象person.__dict__都只显示各自的属性,python2.7中自定义类的类型对象的__dict__属性字典额外包含了"__module__"与"__doc__"属性,后面会看到python3.8会使没有继承的用户自定义类"强行"继承built-ins的object元基类。

4、当自定义类不继承任何类时python3让类默认继承object类,Python2没这招

        参见python定义类()中写object和不写的区别

5、通过object.__init__的属性名-属性值字典可以直接访问、设置、修改或删除object的属性

        参见骏马金龙

        

 

猜你喜欢

转载自blog.csdn.net/HayPinF/article/details/107591387
今日推荐