python 类的命名空间
一、类对象提供的默认行为
要想了解类的命名空间,首先我们得了解类对象提供的默认行为。 当我们执行class语句定义类的时候,就会得到类的对象,python类对象的默认行为如下:
1、class语句创建类对象并且将其赋值给一个名称。 就像函数def语句一样,Python的class语句也是可执行语句。当其执行时就会产生新的类对象,并被赋值给class头部的名称。此外,就像def一样,class语句一般是在其所在的文件被导入时执行的。
2、class语句内的赋值语句会创建该类的属性。 就像模块文件一样,class语句内顶层的赋值语句(不是嵌套在def之内)会产生类对象中的属性。从技术上来看,class语句定义了一个局部作用域,该作用域会变成类对象的属性的命名空间,就像模块的命名空间一样。我们同样可以使用__dict__来访问类的命名空间,所有命名空间内的变量都可以只用属性访问符'.' 来进行访问
怎么理解这句话呢:class语句内的赋值语句会创建该类的属性。 简单来说,就是class语句块之内,def语句块之外的赋值语句,还包括def函数定义语句本身,这些赋值语句被称为顶层语句,赋值语句指定的名称都会成为类的属性。举个例子
class Car(object):
a = 1
_defaults = {'b': 2, 'c':3}
print(Car.a)
print(Car._defaults)
1
{'b': 2, 'c': 3}
这里我们只是定义了一个类Car,并没有定义任何的def方法,我们的顶层赋值语句 a=1 和_defaults = {'b': 2, 'c': 3} ,就为Car这个类创建了两个属性,这两个属性是属于Car这个类的,而不是Car类的实例对象。
我们没有对Car创建实例对象,而是直接访问Car这个类,和Car这个类的a属性和_defaults属性。
3、类属性提供了对象的状态和行为 类对象的属性记录了可由这个类所创建的所有实例共享的状态信息行为。类的内部函数def语句会生成方法,方法可用于处理实例。
二、类的属性和命名空间 vs 实例的属性和命名空间
实例对象是具体的元素
- 像函数那样调用类对象会创建新的实例对象
- 每个实例对象都继承了类的属性并获得了自己的命名空间
- 在方法内对self属性做赋值运算会产生每个实例自己的属性
1、类的属性和命名空间 就像上面所讲的一样,class语句块之内,def语句块之外的赋值语句会创建该类的属性。我们使用__dict__来查看一下Car这个类的命名空间中有那些属性。
class Car(object):
a = 1
_defaults = {'b': 2, 'c':3}
def __init__(self): pass
print(Car.__dict__)
mappingproxy({'__module__': '__main__',
'a': 1,
'_defaults': {'b': 2, 'c': 3},
'__init__': <function __main__.Car.__init__(self)>,
'__dict__': <attribute '__dict__' of 'Car' objects>,
'__weakref__': <attribute '__weakref__' of 'Car' objects>,
'__doc__': None})
可见Car这个类的命名空间中有我们上面所说的属性Car.a 和属性Car._defaults
2、实例的属性和命名空间 类的实例是要通过self.attr 来指定属性的,大多数时候我都都可以将需要给实例对象设置的属性放置在__init__方法中。
class Car(object):
a = 1
_defaults = {'b': 2, 'c':3}
def __init__(self):
self.d = 4
mycar = Car()
print(mycar.__dict__)
print(mycar.d)
print(Car.__dict__)
{'d': 4}
4
mappingproxy({'__module__': '__main__',
'a': 1,
'_defaults': {'b': 2, 'c': 3},
'__init__': <function __main__.Car.__init__(self)>,
'__dict__': <attribute '__dict__' of 'Car' objects>,
'__weakref__': <attribute '__weakref__' of 'Car' objects>,
'__doc__': None})
这里我们给实例对象设置了.d 这个属性,但是这个属性只属于实例对象而不属于类
3、将类属性更新到实例属性中的例子 我们为了让Car类的实例也能有_defaults中的属性,我们可以这样做
class Car(object):
a = 1
_defaults = {'b': 2, 'c':3}
def __init__(self):
for key, value in self._defaults.items():
setattr(self, key, value)
mycar = Car()
print(mycar.__dict__)
{'b': 2, 'c': 3}
|