dir()
和 __ dict __
都可以用来查询对象或类的属性(方法等)。
dict
(1)__dict__
返回的是一个字典,对应的是实例的属性及其值
实例的__dict__
仅存储与该实例相关的实例属性,正是因为实例的__dict__属性,每个实例的实例属性才会互不影响。
注意不包含对象属性
class A:
a = "a"
def __init__(self, name):
self.name = name
if __name__ == "__main__":
obj_a = A("aaa")
print(obj_a.__dict__)
# {'name': 'aaa'}
(2)动态修改实例属性时,会修改实例的__dict__
属性
示例:
class A:
a = "a"
def __init__(self, name):
self.name = name
def func1(self):
self.c = "c"
if __name__ == "__main__":
obj_a = A("aaa")
print(obj_a.__dict__)
obj_a.age = 10
print(obj_a.__dict__)
obj_a.func1()
print(obj_a.__dict__)
# {'name': 'aaa'}
# {'name': 'aaa', 'age': 10}
# {'name': 'aaa', 'age': 10, 'c': 'c'}
(3)@property
修饰的方法,虽然可以使用属性方式访问,但是不在__dict__
里
class A:
a = "a"
def __init__(self, name):
self.name = name
def func1(self):
self.c = "c"
@property
def birthday(self):
return "birthday"
if __name__ == "__main__":
obj_a = A("aaa")
print(obj_a.__dict__) # {'name': 'aaa'}
(4)一些内置的数据类型是没有__dict__
属性的
如:int, list, dict等这些常用的数据类型是没有__dict__
属性的。
(5)类的__dict__
里包含了静态函数、类函数、普通函数、全局变量以及一些内置的属性。
class A:
a = "a"
def __init__(self, name):
self.name = name
def func1(self):
pass
@classmethod
def func2(cls):
pass
@staticmethod
def func3(cls):
pass
if __name__ == "__main__":
print(A.__dict__)
打印如下:
{
'__module__': '__main__', 'a': 'a', '__init__': <function A.__init__ at 0x7fade80a38b0>, 'func1': <function A.func1 at 0x7fade80a3e50>, 'func2': <classmethod object at 0x7fadf8036c40>, 'func3': <staticmethod object at 0x7fadf8036c10>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
(6)无论是实例还是类,都没有父类的属性
class A:
a = "a"
def __init__(self, name):
self.name = name
class B(A):
b = "b"
def __init__(self, name, age):
super().__init__(name)
self.age = age
if __name__ == "__main__":
obj = B("bbb", 30)
打印如下:
{
'__module__': '__main__', 'b': 'b', '__init__': <function B.__init__ at 0x7fc4b01abe50>, '__doc__': None}
(7)私有属性和方法,在 __dict__
会变成_类名__属性名
;单下划线的不影响
class A:
a = "a"
def __init__(self, name):
self.name = name
class B(A):
b = "b"
def __init__(self, name, age):
super().__init__(name)
self.age = age
self._school = "haha"
self.__d = 1
if __name__ == "__main__":
obj = B("bbb", 30)
print(obj.__dict__)
# {'name': 'bbb', 'age': 30, '_school': 'haha', '_B__d': 1}
(8)利用__dict__
可以给运行中的对象添加新的属性
class A:
a = "a"
def __init__(self, name):
self.name = name
class B(A):
b = "b"
def __init__(self, name, age):
super().__init__(name)
self.age = age
self.__d = 1
if __name__ == "__main__":
obj = B("bbb", 30)
obj.__dict__["e"] = "e"
print(obj.__dict__) # {'name': 'bbb', 'age': 30, '_B__d': 1, 'e': 'e'}
dir()
dir()
用来寻找一个对象的所属性,包括__dict__
中没有的属性,__dict__
是dir()
的子集;
dir()
函数会自动寻找一个对象的所有属性(包括从父类中继承的属性)。
class A:
a = "a"
def __init__(self, name):
self.name = name
class B(A):
b = "b"
def __init__(self, name, age):
super().__init__(name)
self.age = age
self.__d = 1
if __name__ == "__main__":
obj = B("bbb", 30)
print(dir(obj))
print(dir(B))
结果打印如下:
dir(obj):
['_B__d', '__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__', 'a', 'age', 'b', 'name']
dir(B):
['__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__', 'a', 'b']
做为查属性的两个方法,他们最重要的两个区别:
__ dict __
是一个字典,存储对相应的属性和值;dir()
是一个列表,只存储对应的属性名而已;__ dict __
无法获取父类的属性;dir()
可以获取父类的属性或方法;