python学习笔记 day23 类和对象命名空间
1. 对象属性,和类属性的调用
类属性,也就是静态属性,可以使用类名来调用静态属性,或者使用对象名也可以调用静态属性
对象属性:就是初始化方法中创建的属性,可以使用对象名来调用静态属性;但是不可以使用类名去调用一个对象属性;
class Course(): # 类名 language='Chinese' # 类属性,静态属性 def __init__(self,name,teacher,period): # 初始化方法 self.name=name # 对象属性 self.teacher=teacher self.period=period c1=Course('python','xuanxuan','6 months') # 实例化一个类,创建一个类对象 print(c1.language) # 可以使用对象名调用一个动态属性 print(Course.language) # 可以使用类名调用类属性(动态属性) print(c1.name) # 可以使用对象名查看对象的属性
运行结果:
但是当我试图想要使用类名去调用对象属性时,是会报错的~
print(Course.name) # 不能使用类名去调用一个对象的属性~
运行结果:
其实理解起来也很简单,比如对于这个Course类,我们可以实例化出很多不同的对象:
c1=Course('python','xuanxuan','6 months') c2=Course('Linux','璇璇','3 weeks')
这样就可以实例化出两个对象,但是当我们Course.name时你就不知道要调用哪一个属性了吧 ,其实对象属性是专属于对象的,类名是不能去调用的。
其实内部实质是这样的:
就是当我定义一个类时,他会给Course类创建一个命名空间,存放的是,类属性(静态属性),初始化方法名,其他的方法名(比如Course类中还有其他的一些方法func()-,所以当我们使用类名去调用类属性(静态方法时是完全没问题的,因为类属性就在这个类的命名空间中)你看类Course的命名空间里是没有对象的一些属性的;
当我们对类实例化成一个对象时,比如pyhton=Course(''),我们就会给这个对象创建一个新的命名空间python ,由于在调用Course这个类时,创建了一个python对象,python对象开辟了一个新的命名空间,里面放的就是该对象的一些属性,但是python这个对象肯定知道是由谁实例化的,对象肯定能找到它所调用的那个类,这就有了类对象指针(由对象指向它所调用的类),所以当我们使用对象名去调用类属性(存在于类的命名空间中)时,首先会在自己的命名空间中找,找不到就去类对象指针指向的那个类的命名空间中去查找,找到了就返回值,所以这就是使用对象名也可以调用类属性的原因。
但是类对象指针只能是由对象指向它所调用的类,不能反过来,因为可能会有很多对象是由一个类实例化出来的,所以只能是单线,这就是为什么类名不能调用属性名~
2.通过对象名修改类属性 VS 通过类名修改类属性
当我们通过类名去修改类属性时,实例化这个类的所有对象在使用对象名调用这个类属性时都会发生变化,因为这些对象都是通过各自的类对象指针指向它们所实例化的这个类,当类的这个命名空间中的类属性修改之后,当对象名调用这个类属性时,通过类对象指针找到这个类属性也变了~
class Course(): # 类名 language='Chinese' # 类属性,动态属性 def __init__(self,name,teacher,period): # 初始化方法 self.name=name # 对象属性 self.teacher=teacher self.period=period c1=Course('python','xuanxuan','6 months') # 类实例化创建对象c1 c2=Course('Linux','璇璇','3 weeks') print('类属性修改之前:',Course.language) print(Course.__dict__) Course.language='中文' print('类属性修改之后:',Course.language) print(Course.__dict__) # 其实打印的是类的一些属性和方法 print(c1.language) # 可以使用对象名调用类属性 print(c1.__dict__) # 但是这个对象的命名空间里是没有language这个类属性的,它能取到值是通过类对象指针找到类命名空间中的这个类属性的~ print(c2.language) # 发现由类名修改类属性之后,对象名调用这个类属性时,结果都是会发生变化的~ print(c2.__dict__)
运行结果:
我们知道对象名可以调用类属性,也知道使用类名也可以调用类属性,并且使用类名修改类属性时 面对类实例化得到的对象调用类属性时都会发生变化~
但是当我们企图使用对象名修改类属性时会发生什么呢:
class Course(): # 类名 language='Chinese' # 类属性,动态属性 def __init__(self,name,teacher,period): # 初始化方法 self.name=name # 对象属性 self.teacher=teacher self.period=period c1=Course('python','xuanxuan','6 months') # 类实例化创建对象c1 c2=Course('Linux','璇璇','3 weeks') print('对象名调用类属性修改之前:',c1.__dict__) c1.language='中文' print('对象名调用类属性修改之后:',c1.__dict__) print(c1.language) print("c1对象调用类属性修改之后,c2对象调用类属性 和 类名调用类属性的情况:") print(Course.language) print('Course:',Course.__dict__) print(c2.language) print('c2:',c2.__dict__)
运行结果:
发现,c1对象调用类属性时,“修改前后”的变化是:之前c1命名空间中是没有类属性的,“修改之后”命名空间中却有了! 其实是因为c1.language=‘中文’,是在赋值!!就是会在c1对象的命名空间中创建了这个属性,所以当c1这个对象去查找这个类属性时,就会现在本地明明空间查找,查找到了,就不会通过类对象指针再去类的命名空间找了,所以会看到c1调用类属性时结果会变化
然而类中的这个类属性还是原来的那个啊,所以类调用类属性时会直接在类的命名空间中找,而且c2类对象指针还是会指向实例化的类,c2调用类属性时在本地找不到,就去类命名空间中找;