类--python基础

1. 类

1.1 面向对象

面向过程的关注点:怎么做
面向对象的关注点:谁来做
面向对象编程(00P)是一种解决软件复用的设计和编程方法。这种方法把软件系统中相近相似的操作逻辑和操作应用数据、状态,以类的形式的描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。
类:类是具有一组相同或相似特征(属性)和行为的一系列对象的组合;是模板,模板中可以包含多个函数,函数里实现一些功能;类是负责创建对象的
对象:则是根据模板创建的实例,通过实例对象可以执行类中的函数。

类相当于制造汽车的图纸,用这个图纸制造的汽车相当于对象。
1) 使用面向过程编程:

# 问题情景;每位同学报告,并做自我介绍

stu_a = {
    'name': 'zhangsan',
    'age': 18,
    'gender': 'F',
    'hometown': 'henan'
}

stu_b = {
    'name': 'lisi',
    'age': 19,
    'gender': 'M',
    'hometown': 'hubei'
}

stu_c = {
    'name': 'wangwu',
    'age': 16,
    'gender': 'M',
    'hometown': 'qinghai'
}


def stu_info(stu):
    '''
每位学生自我介绍:
    '''
    for key, value in stu.items():
        print('我的', key, '是', value)


stu_info(stu_a)
stu_info(stu_b)
stu_info(stu_c)

'''
上述情景花费大量时间在学生信息定义上,自我介绍使用函数进行了封装简化, 
'''

2)使用面向对象编程

class Student:
    def __init__(self,name,age,birthplace):
        self.name = name
        self.age = age
        self.birthplace = birthplace
        print('我叫{},今年{}岁,家在{}'.format(self.name,self.age,self.birthplace))
stuA = Student('张三',20,'河南')
stuB = Student('李四',24,'湖北')

在这里插入图片描述
使用类能够实现代码的重复利用,提高开发效率

1.2 类的组成

类由3部分构成:
类的名称:类名
类的属性:一组数据,反应特征
类的方法:行为

在这里插入图片描述

2. 类

2.1 类名:

  1. 采用“大驼峰”命名方法:
    (1)每个单词首字母大写;
    (2)单词与单词之间没有下划线

2.2 创建简单类

通过class关键字,创建类

# 创建类
class Animal:
    pass


print(id(Animal))
print(type(Animal))

在这里插入图片描述
可以看到,虽然类内部我们还没定义具体的内容,但计算机已经给类开辟了内存空间。

接下来,我们在类的内部定义一个简单的实例方法

class Animal:
    def eat(self):
        print('吃东西才能活着')

先不要管self参数,后面会讲到,当你输入()的时候pychrm会自动补充self参数。

2.3 类的实例化—实例(对象)

2.3.1 创建类的对象

根据类创建类的对象,使用:

变量名 = 类名()
class Animal:
    def eat(self):
        print('吃东西才能活着')


am = Animal()
print(am)
nl = Animal()
print(nl)

在这里插入图片描述
这里创建了Animal的两个对象,可以看到,当我们输出创建的对象,python将会返回对象所属的类信息,以及在内存中的地址(十六进制表示),每个对象python都会分配单独的内存空间。

2.2.3 调用对象方法

调用对象的方法,只需要使用

对象名.方法名()
class Animal:
    def eat(self):
        print('吃东西才能活着')


am = Animal()
# print(am)
nl = Animal()
# print(nl)
am.eat()
nl.eat()

在这里插入图片描述
上面不同对象am、nl调用eat方法时,输出的是相同的内容,如果我们想要输出与对象am、nl相关的信息,就需要使用self参数。

2.2.4 self 参数

python中根据同一个类创建的对象都能够调用类中定义的方法,哪个对象调用方法,方法中的self参数就和那个对象名指向相同的内存地址。下面通过对代码打断点来看一下

在这里插入图片描述

可以看到,在第六行代码运行之后,产生了am对象,具体执行过程如下:
1)python会首先寻找内存中等号=右边的类Animal是否已经分配内存空间;
2)若类的内存空间存在,则利用类向内存中申请创建一块与类一样的空间;
3)回到类中查看是否定义了魔术方法__init__,
4)若没有定义魔术方法__init__,则直接将开辟的内存空间给变量名am;若有魔术方法__init__,则先进入魔术方法__init__内部执行里面的代码,然后再将开辟的内存空间给对象名变量。
接下类看对象am调用eat()方法的过程:
在这里插入图片描述

可以看到self指向的内存地址与am对象名指向的内存地址相同。

在这里插入图片描述

接下来,再看对象nl
在这里插入图片描述
在这里插入图片描述

每次运行代码,Animal类都会重新开辟新的内存空间给对象。同样可以看到,当创建对象nl后,nl调用eat方法时,其中的self指向的内存地址与nl相同
也就是说,哪个对象调用方法,方法中的self参数就和那个对象名指向同一个内存空间。
了解了self参数,跟调用方法的对象有关,那么想要不同的对象输出不同的内容,只需要self后面跟上不同的名字表示对象名,以及其他属性。要想在类中使用self.属性需要先定义self.属性。对不同的对象输出不同的属性,就需要在创建类时传入不同的实参,那也就需要在类中定义相应的形参。

2.2.5 自动调用初始化方法:init

前面说到在创建对象时,python会先找类中有没有__init__方法,再将开辟的内存赋给对象名变量。__init__方法时创建实例时自动执行的方法,我们可以在里面定义一些参数,用于指定对象相关属性

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print('吃东西才能活着')

由于__init__方法会创建实例时自动执行,因此创建实例时,我们也需要传入对象相应的实参

am = Animal('艾玛', 6)
am.eat()

nl = Animal('纽乐', 4)
nl.eat()

在这里插入图片描述

代码中的self.后面的属性名不一定要与形参的一致,习惯保持一致。
接下来,验证__init__中 的内容是不是不需要主动调用,在创建对象时就自动执行
在这里插入图片描述

可以看到__init__中的内容,确实创建完实例,不需要调用就会自动执行。

当创建对象时从外界传入了name、age参数,在定义实例方法时,就可以使用。

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print('%s说: 吃东西才能活着'% self.name)


am = Animal('艾玛', 6)
am.eat()

nl = Animal('纽乐', 4)
nl.eat()

在这里插入图片描述
同样的也可以在方法中,定义其他形参,例如:

在这里插入图片描述

**总结:**
1) 创建出来的对象叫做类的实例
2)创建对象的动作叫做实例化
3)对象的属性叫做实例属性
4)对象调用的方法叫做实例方法
5)__init__方法是python的内置方法,在创建实例时会自动执行,可以在函数里面接收参数,定义实例属性,
   实现不同对象不同属性。
6)通过对象名.属性名可以调用对象属性;同样的通过对象名.方法名可以调用对象方法
7)默认情况下print(对象名),将输出对象创建的类与十六进制的对象内存地址

上面总结7)说到:默认情况下print(对象名),将输出对象创建的类与十六进制的对象内存地址,但是我们还可以改变print(对象名)时的输出内容,通过__str__函数实现。

2.4 自定义输出信息:str

若在开发中,希望在使用print输出时不是看到对象所属的类与内存地址,可以使用__str__方法自定义输出内容,但是需要注意:__str__方法必须返回一个字符串(return函数)
先来看默认情况下,print(对象名)的输出结果:

'''
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))


am = Animal('艾玛', 6)
am.eat('苹果')

nl = Animal('纽乐', 4)
nl.eat('火龙果')

#默认情况下,print(对象名)的输出结果
print(am)
print(nl)

在这里插入图片描述
下面使用__str__函数修改默认输出内容:

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return '这是Animal的实例对象: [%s]' % (self.name)

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))


am = Animal('艾玛', 6)
am.eat('苹果')

nl = Animal('纽乐', 4)
nl.eat('火龙果')

#默认情况下,print(对象名)的输出结果
# print(am)
# print(nl)

# 使用__str__函数自定义后,print(对象名)的输出结果
print(am)
print(nl)

在这里插入图片描述

总结:
1) 每一个对象都有自己独立的内存空间,保存各自不同的属性:每个实例属性保存在每个对象的内存空间;
2)同一个类创建的多个对象的方法,在内存中只有一份,在调用方法时,把对象的引用传递到方法内部:即
实例方法保存在类的内存空间;
3)程序运行时,类在内存中只有一份,使用一个类可以创建出多个对象;
4)使用__str__方法可以自定义print(对象名)时的展示内容,且__str__方法必须使用
return函数返回一个字符串。

除了封装的实例属性和方法,类对象还可以拥有自己的属性和方法

2.5 类的属性和方法

2.5.1 类的属性

1)记录与类相关的特征
2)定义在类中,且在函数体外
3)类属性可以在所有实例化的对象中公用
4)使用赋值语句 属性名 = 属性值 定义类属性

class Animal:
    # 定义类属性
    legs = 4
    eyes = '眼神犀利'
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return '这是Animal的实例对象: [%s]' % (self.name)

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))


am = Animal('艾玛', 6)
am.eat('苹果')

nl = Animal('纽乐', 4)
nl.eat('火龙果')

#默认情况下,print(对象名)的输出结果
# print(am)
# print(nl)

# 使用__str__函数自定义后,print(对象名)的输出结果
print(am)
print(nl)

访问类属性,通过类名.属性名的方式

在这里插入图片描述
虽然也可以通过 实例名.属性名 的方式访问类属性。因为,我们前面提到,每个对象取值不同的实例属性是存放在对象内存中的,而类属性是存放在类内存中的。在python中属性的获取存在:向上查找机制

通过实例名.属性名: 属性的获取首先在对象内部查找,如能找到,则直接返回属性值,若对象内部没有找到,
则向上到类中查找属性,找到就返回结果,找不到就报错。

在这里插入图片描述
但建议类属性使用类名.属性名的方式访问

2.5.2 类方法

定义类方法
1)需要使用修饰器:@classmethod,告诉解释器这是一个类方法
2)类方法的第一个参数应为cls,类似于实例方法的第一个参数为self

class Animal:
    # 定义类属性
    legs = 4
    eyes = '眼神犀利'
    num = 0

    @classmethod
    def sub_count(cls):
        print('Animal类创建了%d个对象' % Animal.num)

    def __init__(self, name, age):   # 该方法没此创建对象就会自动执行,因此可以在此计算
        self.name = name
        self.age = age
        Animal.num += 1

    def __str__(self):
        return '这是Animal的实例对象: [%s]' % self.name

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))


am = Animal('艾玛', 6)
nl = Animal('纽乐', 4)

print(Animal.num)

在这里插入图片描述

2.6 静态方法

在开发时,如果类中封装的方法:
1)既不需要访问实例属性或者调用实例方法
2)也不需要访问类属性或者类方法
这时该方法中的内容不会随实例或者类的创建与不同发生改变,可封装为静态方法
静态方法需要:
1)使用修饰器:@staticmethod 标识,让解释器知道这是一个静态方法
2)可以通过 类名.方法名 调用静态方法

class Animal:
    # 定义类属性
    legs = 4
    eyes = '眼神犀利'
    num = 0

    @classmethod
    def sub_count(cls):
        print('Animal类创建了%d个对象' % Animal.num)

    def __init__(self, name, age):   # 该方法没此创建对象就会自动执行,因此可以在此计算
        self.name = name
        self.age = age
        Animal.num += 1

    @staticmethod
    def help_mes():
        print('类的具体学习请参考课本XXX页')

    def __str__(self):
        return '这是Animal的实例对象: [%s]' % self.name

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))


Animal.help_mes()

在这里插入图片描述

总结:
1) 方法内部需访问实例属性————实例方法
实例方法内部也可以通过类名访问类属性
2)方法内部只需要访问类属性————类方法
3)方法内部既不需要访问类属性也不需要访问实例属性————静态方法

2.7 私有属性和私有方法

在实际开发中,对象的某些属性和方法,只希望在类内部进行访问,而不希望在外部被访问到。这时,就可以采用私有属性和私有方法,以隐藏相关内容,避免他人修改。
1)私有属性:对象不希望公开的属性
2)私有方法:类不希望公开的方法
3)通过属性名或方法名前面加两个下划线__的方式定义
4)私有属性和私有方法仅能在类的内部访问和调用
5)私有的好处:
(1)隐藏属性,不被外界随意修改
(2)也可以通过函数setXXX 修改
(3)可以筛选赋值的内容(if语句)
(4)如果想要在外界获取属性,可以定义getXXX方法

首先,对于我们已经写好的下面这段代码:

class Animal:
    # 定义类属性
    legs = 4
    eyes = '眼神犀利'
    num = 0

    @classmethod
    def sub_count(cls):
        print('Animal类创建了%d个对象' % Animal.num)

    def __init__(self, name, age):   # 该方法没此创建对象就会自动执行,因此可以在此计算
        self.name = name
        self.age = age
        Animal.num += 1

    @staticmethod
    def help_mes():
        print('类的具体学习请参考课本XXX页')

    def __str__(self):
        return '这是Animal的实例对象: [%s]' % self.name

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))

    def drink(self, water):
        print('%s喜欢喝: %s' % (self.name, water))


am = Animal('艾玛', 6)
nl = Animal('纽乐', 4)

是可以通过实例名.属性名 = 属性值的方式新增或者修改属性

am = Animal('艾玛', 6)
# 修改属性值
print('修改前:', am.age)
am.age = 99
print('修改后:', am.age)
# 当属性不存在时,可以新增属性
am.school = 'cwdx'
print(am.school)

在这里插入图片描述

在实际开发项目时,如果不希望在外界可以修改属性值,就可以采用私有属性方式,比如不希望外界随便修改年纪值

class Animal:
    # 定义类属性
    legs = 4
    eyes = '眼神犀利'
    num = 0

    @classmethod
    def sub_count(cls):
        print('Animal类创建了%d个对象' % Animal.num)

    def __init__(self, name, age):   # 该方法没此创建对象就会自动执行,因此可以在此计算
        self.name = name
        self.__age = age
        Animal.num += 1

    @staticmethod
    def help_mes():
        print('类的具体学习请参考课本XXX页')

    def __str__(self):
        return '这是Animal的实例对象: [%s]' % self.name

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))

    def drink(self, water):
        print('%s喜欢喝: %s' % (self.name, water))


am = Animal('艾玛', 6)
# 访问私有属性值
print('私有后:', am.__age)

在这里插入图片描述
私有化后将会提示没有__age属性,不能在外界访问。
如果想实现外界访问可以采用

1) 实例名._类名__属性名

在这里插入图片描述
但是这种方式并不推荐使用。

2)通过在类内部定义实例方法,在类的内部方法是可以访问私有属性的。
class Animal:
    # 定义类属性
    legs = 4
    eyes = '眼神犀利'
    num = 0

    @classmethod
    def sub_count(cls):
        print('Animal类创建了%d个对象' % Animal.num)

    def __init__(self, name, age):   # 该方法没此创建对象就会自动执行,因此可以在此计算
        self.name = name
        self.__age = age
        Animal.num += 1

    @staticmethod
    def help_mes():
        print('类的具体学习请参考课本XXX页')

    def __str__(self):
        return '这是Animal的实例对象: [%s]' % self.name

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))

    def drink(self, water):
        print('%s喜欢喝: %s' % (self.name, water))

    def getage(self):
        print(self.__age)


am = Animal('艾玛', 6)
am.getage()

在这里插入图片描述

同时要想在外界修改年纪,也可以通过调用函数的形式:

class Animal:
    # 定义类属性
    legs = 4
    eyes = '眼神犀利'
    num = 0

    @classmethod
    def sub_count(cls):
        print('Animal类创建了%d个对象' % Animal.num)

    def __init__(self, name, age):   # 该方法没此创建对象就会自动执行,因此可以在此计算
        self.name = name
        self.__age = age
        Animal.num += 1

    @staticmethod
    def help_mes():
        print('类的具体学习请参考课本XXX页')

    def __str__(self):
        return '这是Animal的实例对象: [%s]' % self.name

    def eat(self, food):
        print('%s说:我爱吃 %s' % (self.name, food))

    def drink(self, water):
        print('%s喜欢喝: %s' % (self.name, water))

    def getage(self):
        print(self.__age)

    def setage(self, age):
        if 0 < age <= 120:
            self.__age = age
        else:
            print('年龄不符合要求')


am = Animal('艾玛', 6)
# 外界修改前:
am.getage()
# 外界修改后:
am.setage(100)
am.getage()

在这里插入图片描述

这样我们不仅能够实现外界修改,而且可以对外界修改输入的内容进行限制。

总结:
1)私有属性和私有方法可以阻止在外部随意修改属性
2)私有属性的定义方式是在属性名前加双下划线__
3)私有属性可以在类内部被访问,因此
(1)可以通过非私有方法访问私有属性,再在外界调用方法,从而输出私有属性,如:代码中的__age,可以通过getage方法获得,
也因此说python的私有属性和方法是伪私有。
(2)获取属性的方法就是正常定义的方法,只是为了见名知意,一采用:getXXX(XXX为要获取的私有属性名)
(3)与(2)同理,设置在外界修改私有属性的函数,使用setXXX(XXX为要获取的私有属性名),在函数内部还可以对
外界输入的属性进行限制与校验,这也是外界直接通过
                           实例名.属性名 = 属性值 
修改不具备的优势

3. 封装

封装是面向对象的核心思想,将对象的属性和行为封装起来,隐藏实现细节。

class Human:
    def __init__(self,name,weight):
        self.name=name
        self.weight=weight
    def __str__(self):
        return (self.name+'  原本  '+str(self.weight)+'kg  的体重变化情况:')
    def run(self,times):
        self.weight = self.weight-0.5*times
        print(times,'次跑步后的体重为:', self.weight)
    def eat(self,times):
        self.weight = self.weight+0.5*times
        print(times,'次吃饭后的体重为:', self.weight)
xm = Human('xiaoming',50)
print(xm)
xm.run(2)
xm.eat(1)
xm.run(1)

在这里插入图片描述

class Item:
    def __init__(self, name, area):
        self.name = name
        self.area = area

    def __str__(self):
        return (self.name + ', 占地面积是:  ' + str(self.area) + ' 平方米')


bed = Item('席梦思', 4)

chest = Item('衣柜', 2)

table = Item('餐桌', 150)


class House:
    def __init__(self,house_type,area):
        self.house_type = house_type
        self.area = area
        self.free_area = area
        self.item_list = []
    def __str__(self):
        # python能够自动将一对括号内部的代码连接在一起
        return ('户型:%s;  总面积:%.2f' %(self.house_type,self.area))
    def add_item(self,item):
        if item.area>self.free_area:
            print(' %s  太大了,放不下'%(item.name))
        else:
            self.item_list.append(item.name)
            self.free_area = self.free_area-item.area
            print('家里面有:%s,剩余面积为:%.2f 平方米' % (self.item_list,self.free_area))

my_home = House('两室一厅',70)
print(my_home)

my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)

在这里插入图片描述
在python中如果不知道给对象设置什么属性值,可以设置将属性值设置为None

4. 继承

继承是实现代码的重用,相同的代码不需要重复编写
子类拥有父类的所有属性和方法

# 继承
# 定义动物类:有吃、喝、跑、睡
class Animal:
    def eat(self):
        print('吃...')
    def drink(self):
        print('喝...')
    def run(self):
        print('跑...')
    def sleep(self):
        print('睡...')

# 再定义1个动物类中的狗类,除了拥有吃、喝、跑、睡、还有吠
class Dog:
    def eat(self):
        print('吃...')
    def drink(self):
        print('喝...')
    def run(self):
        print('跑...')
    def sleep(self):
        print('睡...')
    def bark(self):
        print('汪...')

使用继承就不需要在狗类中重新编写或赋值与动物类中相同的方法;且在父类方法中改变的属性和方法能够同步到子类中。

# 继承
# 定义动物类:有吃、喝、跑、睡
class Animal:
    def eat(self):
        print('吃...')
    def drink(self):
        print('喝...')
    def run(self):
        print('跑...')
    def sleep(self):
        print('睡...')

# 再定义1个动物类中的狗类,除了拥有吃、喝、跑、睡、还有吠
class Dog(Animal):
    def bark(self):
        print('汪...')
wangcai = Dog()
wangcai.drink()

在这里插入图片描述
修改动物类(Animal)中的方法drink,可以看到子类的Dog()对象,在调用drink方法时也同步发生了变化
在这里插入图片描述

4.1 继承的传递性

C类从B类继承,B类又从A类继承,那么C类就具有B类和A类的所有属性和方法

class Animal:
    def eat(self):
        print('吃...')
    def drink(self):
        print('喝喝喝喝喝')
    def run(self):
        print('跑...')
    def sleep(self):
        print('睡...')

# 再定义1个动物类中的狗类,除了拥有吃、喝、跑、睡、还有吠
class Dog(Animal):
    def bark(self):
        print('汪...')

class KeJi(Dog):
    def jump(self):
        print('蹦...')

wangcai = KeJi()
wangcai.drink()
wangcai.bark()
wangcai.jump()

在这里插入图片描述

4.2 重写父类方法

4.2.1 覆盖父类的方法

在开发中,父类的方法实现和子类的方法实现不同,可以使用覆盖的方式,在子类中重新编写父类的方法实现
具体实现方式:在子类中定义一个和父类同名的方法并且实现
重写之后,子类的对象只会调用子类中重写的方法,而不再调用同名的父类封装方法
如:柯基类的叫声与狗类不一样,可以通过柯基类中重新定义bark方法实现
在这里插入图片描述

4.2.2 对父类方法扩展

如果父类中封装的方法只是子类方法的一部分,可以使用扩展的方式在子类中重写父类的方法
实现方式:
使用super().父类方法,来调用父类方法
然后再编写子类特有的方法
比如:KeJi类中bark方法,除了会Dog类中的叫法,还会其他叫法,就可以使用super().父类方法实现父类方法的继承,同时再加上KeJi类的独特叫法
在这里插入图片描述

4.3 多继承

子类可以有多个父类,并且具有所有父类的属性和方法

class 子类名(父类名1,,父类名2,...pass
class A:
    def test(self):
        print('这是父类A')
class B:
    def demo(self):
        print('这是父类B')
class D(A,B):
    pass
d = D()
d.demo()
d.test()

在这里插入图片描述
如果不同的父类存在同名的方法或属性,应尽量避免使用多继承。
python中不同父类存在同名的方法或属性时,子类的继承顺序,可以通过类的内置属性__MRO__(method resolution order)方法查看
在这里插入图片描述
按照__MRO__输出结果从左至右的顺序查找,如果找到方法就直接执行,不再搜索;没找到,继续向后一个类中搜索,直至最后一个,仍没有则报错
在这里插入图片描述

5. 多态

多态是不同的子类独享调用相同的父类方法,会产生不同的执行结果
(1) 多态可以增加代码的灵活度
(2) 以继承和重写父类方法为前提
(3) 是调用方法的技巧,不会影响类的内部设计

class Dog:
    def __init__(self,name):
        self.name = name
    def game(self):
        print(self.name,'正在玩耍...')
class KeJi(Dog):
    def game(self):
        print(self.name,'花式玩耍中...')
class Human:
    def __init__(self,name):
        self.name = name
    def play_with(self,so):
        print(self.name,'正和',so.name,'玩耍')
        so.game()

wangcai1  = Dog('旺财')
xiaomei = Human('小美')
xiaomei.play_with(wangcai1)

wangcai2 = KeJi('短腿旺财')
xiaomei.play_with(wangcai2)

在这里插入图片描述
可以看到在play_with方法中,传入不同类的对象,导致不同的执行效果
(1)在python中每一个对象都有自己独立的内存空间,保存各自不同的属性
(2)多个对象的方法,在内存中只有1份,保存在类所在的内存空间,在调用方法时,需要把对象的引用传递到方法内部
(3) 类对象在内存中只有1份,使用一个类可以创建出多个对象

参考资料: 黑马程序员Python教程

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值