Python - 名称空间

一、类的实例化

调用类 ====>产生类的对象,该对象也可以成为类的一个实例,调用类的过程也称为类的实例化

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('%s is learning' % self)
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')

最后一行代码就是类的实例化,那么这行代码做了哪些事,我们再来回顾下

二、名称空间

我们可以使用类名加.dict方法,查看类的名称空间,那么对象的名称空间能不能查看呢?

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name  # 把name这个属性放进对象的名称空间中
        self.age = age
        self.gender = gender
    def learn(self):
        print('%s is learning' % self)
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
print(stu1.__dict__)

在定义类的阶段产生类的名称空间,那么什么时候产生对象的名称空间呢?你要先告诉我什么时候产生对象,只有在调用类的时候才会产生对象,这个时候就会产生出对象的名称空间,有了名称空间就是把对象存好了,但是存不是目的,我们目的是取

print(stu1.__dict__['name'])

毫无疑问,这样肯定是可以的,但是我们还有更好的方法

print(stu1.name)

现在我们定义的类做一下修改

class DeepshareStudent:
    school = 'deepshare'
    name = 'aaaaaaaaaa'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('%s is learning' % self)
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')

现在有两个name,我再执行以下代码,打印的结果是什么呢

print(stu1.name)

很明显我用对象找他的独有的name属性 就应该从init中找name

但是,如果init函数中没有呢?

print(stu1.school)

这个对象stu1会先从他自己对象的名称空间中找school这个属性,但是他发现没有这个属性,那就后退一级,往类的名称空间中找,注意对象的名称空间和类的名称空间不是一个概念,接下来我们会说明这个问题

如果类的名称空间中没有,他还会往上找吗?

school = 'deepshare'
class DeepshareStudent:
    name = 'aaaaaaaaaa'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('%s is learning' % self)
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
print(stu1.school)

肯定是不能的,写代码的时候Pycharm就会有错误的提示了,现在school是定义在全局,与对象stu1没有任何关系

我们再来看一下代码

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('%s is learning' % self)
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
stu2 = DeepshareStudent('王三小',18,'male')
print(DeepshareStudent.__dict__)
print(id(DeepshareStudent.__dict__))
print(stu1.__dict__)
print(id(stu1.__dict__))
print(id(stu2.__dict__))

我现在造了两个对象stu1和stu2,打印结果可以说明,他们分别有自己的内存空间,类也有自己的内存空间,那么这之间有什么关系呢?

他们三部分是完全独立的,没有包含与被包含的关系,只不过用对象点属性做属性查找的时候先从对象的名称空间中查找,如果能够找到,就是使用对象的名称空间存的,如果找不到就取类的名称空间中找,再找不到就要报错了,错误提示:对象没有这个属性

三、绑定方法

前面我们研究是对象的特征(用变量表示的,接下来我们来研究对象的技能(用函数来表示的),不管是特征还是技能这些都是对象的属性,这是我们前面已经证明过的,那么接下来我们就来调用对象的属性

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('%s is learning' % self)
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
stu2 = DeepshareStudent('王三小',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的学生,都有一个相似的技能叫做学习,但是你学习能学到小明身上了,你学习并不能代表小明学习,虽然你们都具有学习的功能。这就叫绑定方法,大家用的是同一个功能,但是绑定给谁,就是谁在执行

那么这在程序中怎么体现呢?

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('is learning')
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
stu2 = DeepshareStudent('王三小',18,'male')
DeepshareStudent.learn('albert')
stu1.learn()

执行代码,我们会发现,类调用learn方法必须要传一个参数,而stu1调用learn方法不需要传参数,但是learn确实是需要一个参数的,那就说明他是自动传了一个参数,我们怎么验证呢?

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('is learning',self)  # 打印一下self就知道了
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
stu2 = DeepshareStudent('王三小',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)

绑定方法的特殊之处在于谁来调用,就会把谁当作第一个参数自动传入

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('is learning',self)
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
stu2 = DeepshareStudent('王三小',18,'male')
stu1.learn()
stu2.learn()

接下来我们单独用stu1来说明

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    
    # self=stu1
    def learn(self):
        print('%s is learning' % self.name)  # self就是stu1,stu1有name方法
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
stu2 = DeepshareStudent('王三小',18,'male')
stu1.learn()
stu2.learn()

综上所述

类内部的变量是给所有对象共享,所有对象指向的都是同一个内存地址; 类内部定义的函数其实是为了给对象用的,而且是绑定给对象用的,绑定给不同的对象,就是不同的绑定方法

类内部定义的函数必须要有self这个参数,但也可以有别的参数

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('%s is learning' % self.name)
    def choose(self,course):  # 在添加一个函数
        print('%s is choosing %s' %(self.name, course))  # 传一个course参数
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
stu2 = DeepshareStudent('王三小',18,'male')
stu1.choose('Python')  # 传一个实参
stu2.choose('AI')

四、一切皆对象

在Python中有一个一切皆对象的说法,面向对象讲到这里我们就可以解释了

class DeepshareStudent:
    school = 'deepshare'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def learn(self):
        print('%s is learning' % self.name)
    def choose(self,course):
        print('%s is choosing %s' %(self.name, course))
    def eat(self):
        print('is eating')
    def sleep(self):
        print('is sleeping')
stu1 = DeepshareStudent('王二小',18,'male')
stu2 = DeepshareStudent('王三小',18,'male')
print(stu1)
print(type(stu1))
print(id(stu1))
展开阅读全文

页面更新:2024-03-12

标签:名称   空间   绑定   函数   属性   定义   对象   参数   代码   方法

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top