python类与对象

【类】是【对象】的模板。

注意,以上说的【对象】,都是指【实例对象】。我们可以以【类】为模板,多次复制,生成多个【实例对象】。

什么叫实例对象呢?大家可以想象一下,【类】就像工厂的模具,以它为模板,造出来的成千上万的产品,才是被我们消费、购买、使用,真正融入我们生活的东西。这些产品,在Python中就叫【实例对象】。
往深了说,Python中,万事万物都可以是对象,【类】这种模板层级的本身也是【对象】,但并不是【实例对象】。
从模具变成产品,也就是从【类】变成【实例对象】的过程,就叫做【实例化】。

class 成绩单():
    def 录入成绩单(self):
        self.学生姓名 = input('请输入学生姓名:')
        self.语文_成绩 = int(input('请输入语文成绩:'))
        self.数学_成绩 = int(input('请输入数学成绩:'))

    def 打印成绩单(self):
        print(self.学生姓名 + '的成绩单如下:')
        print('语文成绩:'+ str(self.语文_成绩))
        print('数学成绩:'+ str(self.数学_成绩))


成绩单1 = 成绩单() # 实例化,得到实例对象“成绩单1”
成绩单2 = 成绩单() # 实例化,得到实例对象“成绩单2”
成绩单3 = 成绩单() # 实例化,得到实例对象“成绩单2”

​在上面的代码中,我们成功地录入和保存了3份成绩单。这个过程的专业描述是:把成绩单()类实例化为成绩单1、成绩单2、成绩单3三个【实例对象】。(15-17行代码是关键)
用这种思路,要录入和打印更多份成绩单也是可以做到的。
通过这个例子,我们对“类的实例化”可以有一个比较直观的体会

类的实例化

让我们先明确一下实例化的基本格式。要注意,当类需要被实例化后再使用时,和直接使用类的格式是不同的。

通过对比可以看到,实例化后再使用的格式,①是空着的,意思是这里不再需要@classmethod的声明,并且在第②处,把cls替换成了self。
同时,实例化后再使用的格式,需要先赋值然后再调用(第③处):

在第④步骤,我们需要用实例名 = 类()的方式(实例名其实就是任取一个变量名),为类创建一个实例,然后再使用实例名.函数()的方式调用对应的方法。

# 直接使用类
class 成绩单():
    @classmethod
    def 录入成绩单(cls):
        cls.学生姓名 = input('请输入学生姓名:')
        cls.语文_成绩 = int(input('请输入语文成绩:'))
        cls.数学_成绩 = int(input('请输入数学成绩:'))

    @classmethod
    def 打印成绩单(cls):
        print(cls.学生姓名 + '的成绩单如下:')
        print('语文成绩:'+ str(cls.语文_成绩))
        print('数学成绩:'+ str(cls.数学_成绩))

成绩单.录入成绩单()
成绩单.打印成绩单()

# 实例化之后
class 成绩单():   # ①不用再写@classmethod
    def 录入成绩单(self):  # ②cls变成self
        self.学生姓名 = input('请输入学生姓名:')  # ③cls.变成self.
        self.语文_成绩 = int(input('请输入语文成绩:'))
        self.数学_成绩 = int(input('请输入数学成绩:'))

    def 打印成绩单(self):
        print(self.学生姓名 + '的成绩单如下:')
        print('语文成绩:'+ str(self.语文_成绩))
        print('数学成绩:'+ str(self.数学_成绩))


成绩单1 = 成绩单() # ④创建实例对象:成绩单1

成绩单1.录入成绩单() # ⑤实例化后使用
成绩单1.打印成绩单()

另外提一下,cls代表“类”的意思,self代表“实例”的意思,这样写是编码规范(程序员们的共识),但不是强制要求。理论上只要写个变量名占位,写什么都行,比如把self写成bbb:

class 智能机器人():
    胸围 = 33
    腰围 = 44
    臀围 = 55
    
    def 自报三围(bbb):
        print('主人,我的三围是:')
        print('胸围:' + str(bbb.胸围))
        print('腰围:' + str(bbb.腰围))
        print('臀围:' + str(bbb.臀围))
        print('哈哈哈哈哈,下面粗上面细,我长得像个圆锥。')


a = 智能机器人() # 实例化
a.自报三围() # 实例化后再使用实例

不过为了不做“非主流”,我们还是乖乖地用self就好了。也就是说,当类支持实例化的时候,self是所有类方法位于首位、默认的特殊参数。
换而言之,实例化后,只要你在类中用了def语句,那么就必须在其后的括号里把第一个位置留给self。
另外,当类支持实例化的时候,就不能再直接使用类方法了,如果运行以下代码将会报错:(报错后请点击跳过按钮)

实例属性和类属性

类和实例的关系,就像母体和复制品的关系一样。当一个类实例化为多个实例后,实例将原封不动的获得类属性,也就是实例属性和类属性完全相等。

我们可以修改类属性,这会导致所有实例属性变化(因为类是模板)。

class 类():
    变量 = 100

实例1 = 类() # 实例化
实例2 = 类() # 实例化
print(实例1.变量)
print(实例2.变量)

类.变量 = 'abc'   # 修改类属性
print(实例1.变量)   # 实例属性同步变化
print(实例2.变量)   # 实例属性同步变化

我们也可以修改实例属性,但这不会影响到其他实例,也不会影响到类。因为每个实例都是独立的个体。

class 类():
    变量 = 100

实例1 = 类() # 实例化
实例2 = 类() # 实例化

print('原先的类属性:')
print(类.变量)
print('原先的实例1属性:')
print(实例1.变量)
print('原先的实例2属性:')
print(实例2.变量)

实例1.变量 = 'abc'
print('--------修改实例1的属性后----------') 

新增也是一样的道理,在类中新增属性会影响到实例,但在实例中新增属性只影响这个实例自己。

class 类():
    变量1 = 100

实例 = 类() # 实例化
类.变量2 = 'abc' # 新增类属性
​print(实例.变量1)
print(实例.变量2)

体验一下新增实例属性:(将会报错,因为增加实例属性不会影响到类。报错后请点击跳过按钮)

class 类():
    变量1 = 100

实例 = 类() # 实例化

实例.变量2 = 'abc' # 新增实例属性

print(类.变量2)

class 类:
    变量 = 100 #类属性

实例1 = 类() # 实例化
实例2 = 类() # 实例化

实例1.变量 = 10
类.变量 = 1

print(实例1.变量)
print(实例2.变量)

在这里,每个实例都是独立的个体。其中实例1.变量 = 10相当于修改了实例属性,所以类.变量 = 1不能影响到它,只能影响到实例2.变量。最终实例1.变量的值是10,实例2.变量的值是1。
弄清楚了“实例属性和类属性”,接下来我们继续看“实例方法和类方法”。

实例方法和类方法

和类属性一样,我们可以重写类方法,这会导致所有实例方法自动被重写。

# 请直接运行并体验代码

class 类():
    def 原始函数(self):
        print('我是原始函数!')

def 新函数(self):
    print('我是重写后的新函数!')

a = 类()  # 实例化
a.原始函数()


# 用新函数代替原始函数,也就是【重写类方法】
类.原始函数 = 新函数
# 现在原始函数已经被替换了
a.原始函数()

# 请直接运行并体验代码
class 幸运():
    def 好运翻倍(self):
        print('好的,我把它存了起来,然后翻了888倍还给你:' + str(self.幸运数*888))

def 新好运翻倍(self):
    print('我是重写后的新函数!')
    print('好的,我把它存了起来,然后翻了666倍还给你:' + str(self.幸运数*666))

幸运.幸运数 = int(input('你的幸运数是多少?请输入一个整数。'))
幸运.好运翻倍 = 新好运翻倍
实例 = 幸运()  # 实例化
实例.好运翻倍()

我们可以通过重写类方法,让实例方法发生变化,但我们不能重写实例方法,模板给的技能不是说换就能换的。

初始化函数

class 类():
    def __init__(self):
        print('实例化成功!')

实例 = 类()

初始化函数的意思是,当你创建一个实例的时候,这个函数就会被调用。上面的代码在执行实例 = 类()的语句时,就自动调用了__init__(self)函数。
初始化函数的写法是固定的格式:中间是“init”,这个单词的中文意思是“初始化”,然后前后都要有【两个下划线】,然后__init__()的括号中,第一个参数一定要写上self,不然会报错。
同时,这个初始化函数照样可以传递参数,我们来看个例子。

class 成绩单():
    def __init__(self,学生姓名,语文_成绩,数学_成绩):
        self.学生姓名 = 学生姓名
        self.语文_成绩 = 语文_成绩
        self.数学_成绩 = 数学_成绩

    def 打印成绩单(self):
        print(self.学生姓名 + '的成绩单如下:')
        print('语文成绩:'+ str(self.语文_成绩))
        print('数学成绩:'+ str(self.数学_成绩))


成绩单1 = 成绩单('张三',99,88)
成绩单2 = 成绩单('李四',64,73)
成绩单3 = 成绩单('王五',33,22)

成绩单1.打印成绩单()
成绩单2.打印成绩单()
成绩单3.打印成绩单()

继承

类的继承很大程度也是为了避免重复性劳动。比如说当我们要写一个新的类,如果新的类有许多代码都和旧类相同,又有一部分不同的时候,就可以用“继承”的方式避免重复写代码。

class 父类():
    def __init__(self,参数):
        self.变量 = 参数

    def 打印属性(self):
        print('变量的值是:')
        print(self.变量)

class 子类(父类):
    pass  # pass语句代表“什么都不做”

子类实例 = 子类(2)
子类实例.打印属性()

这里的格式很简单,只需使用class 子类(父类),就能让子类继承父类的所有类方

子类除了可以定制新的类方法,还能直接覆盖父类的方法(可类比富二代男主推翻了老爹管理公司的做派),只要使用相同的类方法名称就能做到这一点。

class 基础机器人():
    def __init__(self,参数):
        self.姓名 = 参数

    def 自报姓名(self):
        print('我是' + self.姓名 + '!')     

    def 卖萌(self):
        print('主人,求抱抱!')

class 高级机器人(基础机器人):
    def 卖萌(self):  # 这里使用了相同的类方法名称“卖萌”,这样可以让子类方法覆盖父类方法
        print('主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!')

鲁宾 =  基础机器人('鲁宾')
鲁宾.自报姓名()

class 基础机器人():
    def __init__(self,参数):
        self.姓名 = 参数

    def 自报姓名(self):
        print('我是' + self.姓名 + '!')     

    def 卖萌(self):
        print('主人,求抱抱!')

class 高级机器人(基础机器人):
    def __init__(……):
        ……
    
    def 自报姓名(self):
        print(……)       

    def 卖萌(self):
        print('主人,每次想到怎么欺负你的时候,就感觉自己全身biubiubiu散发着智慧的光芒!')

安迪 = 高级机器人('安迪',150)
安迪.自报姓名()
安迪.卖萌()

这样,子类从【一个父类】继承类方法,我们叫做“单继承”。还有一种更复杂的继承情况,叫“多重继承”。

顾名思义,“多重继承”就是一个子类从【多个父类】中继承类方法。格式是class 子类(父类1,父类2,……)。

通过本关的学习,我们知道了类就像是一个模版,通过这个模版可以制造出许多个实例对象,这个制造过程,我们称之为实例化。
在我们实例化的过程,可以通过初始化函数__init__给类传递不同的参数,这样的方式可以让我们得到属性不同的实例。
我们也学习了继承,有了继承之后,我们可以很方便的改装类,得到子类,这个过程就像在改装模版,我们既可以直接复制模版,又可以给模版增加一些功能,亦或是替换、强化原来模板的某些功能。

你可能感兴趣的:(python,python,开发语言)