一、类的实例化 调用类产生类的对象,该对象也可以成为类的一个实例,调用类的过程也称为类的实例化classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(sislearningself)defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male) 最后一行代码就是类的实例化,那么这行代码做了哪些事,我们再来回顾下先造一个空对象obj,和所有对象都一样连同这个对象和三个参数一块传递给init函数执行DeepshareStudent。init(obj,王二小,18,male)二、名称空间 我们可以使用类名加。dict方法,查看类的名称空间,那么对象的名称空间能不能查看呢?classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namename把name这个属性放进对象的名称空间中self。ageageself。gendergenderdeflearn(self):print(sislearningself)defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)print(stu1。dict) 在定义类的阶段产生类的名称空间,那么什么时候产生对象的名称空间呢?你要先告诉我什么时候产生对象,只有在调用类的时候才会产生对象,这个时候就会产生出对象的名称空间,有了名称空间就是把对象存好了,但是存不是目的,我们目的是取print(stu1。dict〔name〕) 毫无疑问,这样肯定是可以的,但是我们还有更好的方法print(stu1。name) 现在我们定义的类做一下修改classDeepshareStudent:schooldeepsharenameaaaaaaaaaadefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(sislearningself)defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male) 现在有两个name,我再执行以下代码,打印的结果是什么呢print(stu1。name) 很明显我用对象找他的独有的name属性就应该从init中找name 但是,如果init函数中没有呢?print(stu1。school) 这个对象stu1会先从他自己对象的名称空间中找school这个属性,但是他发现没有这个属性,那就后退一级,往类的名称空间中找,注意对象的名称空间和类的名称空间不是一个概念,接下来我们会说明这个问题 如果类的名称空间中没有,他还会往上找吗?schooldeepshareclassDeepshareStudent:nameaaaaaaaaaadefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(sislearningself)defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)print(stu1。school) 肯定是不能的,写代码的时候Pycharm就会有错误的提示了,现在school是定义在全局,与对象stu1没有任何关系 我们再来看一下代码classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(sislearningself)defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)stu2DeepshareStudent(王三小,18,male)print(DeepshareStudent。dict)print(id(DeepshareStudent。dict))print(stu1。dict)print(id(stu1。dict))print(id(stu2。dict)) 我现在造了两个对象stu1和stu2,打印结果可以说明,他们分别有自己的内存空间,类也有自己的内存空间,那么这之间有什么关系呢? 他们三部分是完全独立的,没有包含与被包含的关系,只不过用对象点属性做属性查找的时候先从对象的名称空间中查找,如果能够找到,就是使用对象的名称空间存的,如果找不到就取类的名称空间中找,再找不到就要报错了,错误提示:对象没有这个属性三、绑定方法 前面我们研究是对象的特征(用变量表示的,接下来我们来研究对象的技能(用函数来表示的),不管是特征还是技能这些都是对象的属性,这是我们前面已经证明过的,那么接下来我们就来调用对象的属性classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(sislearningself)defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)stu2DeepshareStudent(王三小,18,male)print(DeepshareStudent。learn)print(stu1。learn)print(stu2。learn)print(id(DeepshareStudent。school))print(id(stu1。school))print(id(stu2。school)) 我们再来理解一下,类是直接从自己的名称空间中拿到learn属性,而对象在自己的名称空间中找learn属性没有找到,就要到类的名称空间中去找,相当于是间接拿到了learn属性。类内部定义的函数自己能使用,但主要是给对象用的。再来看一下内存地址,上面三个函数属性的内存地址是完全不同的,而下面三个变量属性的内存地址是完全一样的。这是因为类内部的变量是直接给对象使用,而类内部的函数是绑定给对象使用,这怎么理解呢 你们大家都是Deepshare的学生,都有一个相似的技能叫做学习,但是你学习能学到小明身上了,你学习并不能代表小明学习,虽然你们都具有学习的功能。这就叫绑定方法,大家用的是同一个功能,但是绑定给谁,就是谁在执行 那么这在程序中怎么体现呢?classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(islearning)defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)stu2DeepshareStudent(王三小,18,male)DeepshareStudent。learn(albert)stu1。learn() 执行代码,我们会发现,类调用learn方法必须要传一个参数,而stu1调用learn方法不需要传参数,但是learn确实是需要一个参数的,那就说明他是自动传了一个参数,我们怎么验证呢?classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(islearning,self)打印一下self就知道了defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)stu2DeepshareStudent(王三小,18,male)DeepshareStudent。learn(albert)stu1。learn()print(stu1) 仔细看看是不是一样的 这就说明stu1调用learn方法本质原理就是把它自己传进来stu1。learn()DeepshareStudent。learn(stu1) 这就是绑定方法,类内部定义的函数,类可以使用,但是类来使用的时候就是一个普通函数,普通函数有几个参数就传几个参数print(DeepshareStudent。learn)DeepshareStudent。learn(albert) 但是类内部定义的函数其实是为了给对象用的,而且是绑定给对象用的,绑定给不同的对象,就是不同的绑定方法print(stu1。learn)print(stu2。learn) 绑定方法的特殊之处在于谁来调用,就会把谁当作第一个参数自动传入classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(islearning,self)defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)stu2DeepshareStudent(王三小,18,male)stu1。learn()stu2。learn() 接下来我们单独用stu1来说明classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderselfstu1deflearn(self):print(sislearningself。name)self就是stu1,stu1有name方法defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)stu2DeepshareStudent(王三小,18,male)stu1。learn()stu2。learn() 综上所述 类内部的变量是给所有对象共享,所有对象指向的都是同一个内存地址;类内部定义的函数其实是为了给对象用的,而且是绑定给对象用的,绑定给不同的对象,就是不同的绑定方法 类内部定义的函数必须要有self这个参数,但也可以有别的参数classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(sislearningself。name)defchoose(self,course):在添加一个函数print(sischoosings(self。name,course))传一个course参数defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)stu2DeepshareStudent(王三小,18,male)stu1。choose(Python)传一个实参stu2。choose(AI)四、一切皆对象 在Python中有一个一切皆对象的说法,面向对象讲到这里我们就可以解释了classDeepshareStudent:schooldeepsharedefinit(self,name,age,gender):self。namenameself。ageageself。gendergenderdeflearn(self):print(sislearningself。name)defchoose(self,course):print(sischoosings(self。name,course))defeat(self):print(iseating)defsleep(self):print(issleeping)stu1DeepshareStudent(王二小,18,male)stu2DeepshareStudent(王三小,18,male)print(stu1)print(type(stu1))print(id(stu1))