Python中类的介绍及使用

文章目录

  • 前言
  • 一、面向对象与面向过程
  • 二、类的创建和使用
  • 三、使用类和实例
  • 1.给属性指定默认值
  • 2.修改属性的值
  • 四、继承
  • 1.子类的方法__init__()
  • 2.给子类定义属性和方法
  • 3.重写父类的方法
  • 4.将实例用作属性
  • 五、类的导入
  • 六、Python标准库
  • 总结

  • 前言

    本文的主要内容是Python中类的介绍及使用,具体包括面向对象与面向过程的介绍、类的创建和使用、使用类和实例、继承、类的导入和Python标准库的使用,文中附有代码以及相应的运行结果辅助理解。


    一、面向对象与面向过程

    面向过程(procedure-oriented):注重过程,在解决一个问题的时候,面向过程会把事情拆分成 一个个函数和数据,然后按照一定的顺序,依次执行这些方法,等方法执行完了,问题就解决了。
    面向对象(object-oriented):注重对象,在解决一个问题的时候,面向对象会把事物抽象成若干个对象,然后再给对象赋一些属性和方法,让每个对象去执行自己的方法,问题得到解决。
    举一个例子:洗衣机洗衣服。
    面向过程:
    1.把衣服放进洗衣机;
    2.往洗衣机中注水;
    3.加入洗衣液;
    4.启动洗衣机;
    5.洗衣机清洗;
    6.洗衣机烘干。
    面向过程洗衣服就是按照顺序按部就班的执行一个个的“函数”。
    面向对象:
    先抽象出两个对象:“人”和“洗衣机”。
    对“人”加一些属性和方法:“把衣服放进洗衣机”、“往洗衣机中注水”、“加入洗衣液”、“启动洗衣机”。
    对“洗衣机”加一些属性和方法:“洗衣机清洗”、“洗衣机烘干”。
    执行:人——“把衣服放进洗衣机”;人——“往洗衣机中注水”;人——“加入洗衣液”;人——“启动洗衣机”;洗衣机——洗衣机清洗;洗衣机——洗衣机烘干。
    面向对象洗衣服就是先抽象出类,然后各个类再分别调用“方法”。


    二、类的创建和使用

    面向对象编程是最有效的软件编写方法之一,在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。编写类时,你定义一大类对象都有的通用行为,基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。根据类来创建对象被称为实例化,这让你能够使用类的实例。
    根据约定,在Python中,首字母大写的名称指的是类,类中的函数称为方法,通过实例访问的变量称为属性。
    方法__init__()是一个特殊的方法,每当你给类创建新的实例时,Python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。在这个方法的定义中,形参self是必不可少的,还必须位于其他形参的前面,因为Python调用__init__()方法来创建实例时,将自动传入实参self,因此我们不需要传递它,只需要给self后面的参数传递实参即可。每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
    下面是一个类的创建和使用的例子。

    class User():
        """定义用户的类"""
        def __init__(self, first_name, last_name, gender, age):
            """初始化属性"""
            self.name = first_name.title() + ' ' + last_name.title()
            #获取存储在形参first_name和last_name中的值,并将其存储到变量name中
            self.gender = gender
            self.age = age
            #这里的name,gender和age都是属性
    
        def describe_user(self):
            """描述用户的方法"""
            if self.gender == 'male':
                print("This user's name is " + self.name + ", and his age is " + str(self.age) + ".")
            elif self.gender == 'female':
                print("This user's name is " + self.name + ", and her age is " + str(self.age) + ".")
    
        def greet_user(self):
            """问候用户的方法"""
            print("Hello, " + self.name + "!")
        #这里的describe_user()和greet_user()都是方法
    
    user_1 = User('lebron', 'james', 'male', 37) #根据类创建实例,Python遇到这行代码会调用方法__init__()来提供属性
    
    print('name : ' + user_1.name) #用句点表示法访问实例的属性
    print('gender : ' + user_1.gender)
    print('age : ' + str(user_1.age))
    
    user_1.describe_user() #用句点表示法调用方法
    user_1.greet_user()
    
    print()
    
    user_2 = User('rachel', 'green', 'female', 24) #创建多个实例
    
    print('name : ' + user_2.name) #用句点表示法访问实例的属性
    print('gender : ' + user_2.gender)
    print('age : ' + str(user_2.age))
    
    user_2.describe_user()
    user_2.greet_user()
    

    运行结果如下图所示。

    由运行结果可知,对于类中的属性可以用句点表示法访问实例的属性,也可以直接调用类中的方法。


    三、使用类和实例

    可以使用类来模拟现实世界中的很多情景,类编写好以后,大部分时间都将花在使用根据类创建的实例上,还要执行的一个重要任务是修改实例的属性,可以直接修改实例的属性,也可以编写方法以特定的方式进行修改。

    1.给属性指定默认值

    类中的每个属性都必须有初始值,即使这个值是0或空字符串。在有些情况下,如设置默认值时,如果在方法__init__()内指定了初始值,那么在后面的括号中就无需包含其形参。
    下面是给属性指定默认值的例子。

    class User():
        """定义用户的类"""
        def __init__(self, first_name, last_name, gender, age): #不用给login_attempts传递形参
            """初始化属性"""
            self.name = first_name.title() + ' ' + last_name.title()
            #获取存储在形参first_name和last_name中的值,并将其存储到变量name中
            self.gender = gender
            self.age = age
            self.login_attempts = 0  #给属性指定默认值后不用再传递形参
    
        def print_login_attempts(self):
            """打印属性login_attempts"""
            print('login_attempts in function: ' + str(self.login_attempts))
    
    user = User('lebron', 'james', 'male', 37) #不用给login_attempts传递实参
    
    print('name : ' + user.name) #用句点表示法访问实例的属性
    print('gender : ' + user.gender)
    print('age : ' + str(user.age))
    print('login_attempts : ' + str(user.login_attempts)) #直接访问实例属性
    
    user.print_login_attempts() #调用方法打印属性login_attempts
    

    运行结果如下图所示。

    由运行结果可知,我们给属性指定默认值之后,可以直接访问实例的该默认属性,也可以通过方法来访问,其结果都是一样的。

    2.修改属性的值

    修改属性的值可以用三种不同的方式:直接通过实例进行修改;通过方法进行修改;通过方法进行递增。
    下面是修改属性值的例子,里面包含了上面提到的三种方法。

    class User():
        """定义用户的类"""
        def __init__(self, first_name, last_name, gender, age): #不用给login_attempts传递形参
            """初始化属性"""
            self.name = first_name.title() + ' ' + last_name.title()
            #获取存储在形参first_name和last_name中的值,并将其存储到变量name中
            self.gender = gender
            self.age = age
            self.login_attempts = 0  #给属性指定默认值后不用再传递形参
    
        def print_login_attempts(self):
            """打印属性login_attempts"""
            print('print_login_attempts login_attempts : ' + str(self.login_attempts))
    
        def update_login_attempts(self, value):
            """修改属性login_attempts的值"""
            self.login_attempts = value
            print('update_login_attempts login_attempts : ' + str(self.login_attempts))
    
        def increment_login_attempts(self, value):
            """修改属性login_attempts的值"""
            self.login_attempts += value
            print('increment_login_attempts login_attempts : ' + str(self.login_attempts))
    
    user = User('lebron', 'james', 'male', 37) #不用给login_attempts传递实参
    
    print('name : ' + user.name) #用句点表示法访问实例的属性
    print('gender : ' + user.gender)
    print('age : ' + str(user.age))
    print('original login_attempts : ' + str(user.login_attempts)) #直接访问实例属性
    
    user.login_attempts = 10  #直接通过实例进行修改默认属性值
    user.print_login_attempts() #调用方法打印属性login_attempts
    
    user.update_login_attempts(20) #调用方法修改默认属性的值
    
    user.increment_login_attempts(10) #调用方法对默认属性值递增
    

    运行结果如下图所示。

    由上面运行结果可知,原始的login_attempts值为0;直接通过实例进行修改其值后为10;通过方法修改其值时会覆盖掉原来的10,修改为20;再调用方法对属性值递增,递增时不会覆盖掉已有的login_attempts值20,而是在其基础上递增10,结果即为30。


    四、继承

    并非所有类的编写总是从空白开始,如果你要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法,原有的类称为父类(超类),而新类称为子类,子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
    创建子类时,父类必须包含在当前文件中,且位于子类前面。
    定义子类时,必须在括号内指定父类的名称。

    1.子类的方法__init__()

    创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值,而子类的方法__init__()需要父类施以援手。
    super()是一个特殊函数,帮助Python将父类和子类关联起来。
    下面是子类的方法__init__()编写的例子。

    class User():
        """定义用户的类"""
        def __init__(self, first_name, last_name, gender, age):
            """初始化属性"""
            self.name = first_name.title() + ' ' + last_name.title()
            self.gender = gender
            self.age = age
    
        def describe_user(self):
            """描述用户的方法"""
            if self.gender == 'male':
                print("This user's name is " + self.name + ", and his age is " + str(self.age) + ".")
            elif self.gender == 'female':
                print("This user's name is " + self.name + ", and her age is " + str(self.age) + ".")
    
        def greet_user(self):
            """问候用户的方法"""
            print("Hello, " + self.name + "!")
    
    
    class Administrator(User):
        """定义子类Administrator继承父类User"""
        def __init__(self, first_name, last_name, gender, age):
            """初始化父类的属性"""
            super().__init__(first_name, last_name, gender, age)
    
    
    admin = Administrator('lebron', 'james', 'male', 37)
    admin.greet_user()
    

    运行结果如下图所示。

    通过上面的例子可以看到,子类Administrator继承了父类User的属性和方法,在子类的__init__()方法中需要用到super()来初始化父类的属性。子类继承父类后,就可以用父类中的属性和方法了。

    2.给子类定义属性和方法

    让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。
    下面是给子类定义属性和方法的例子。

    class User():
        """定义用户的类"""
        def __init__(self, first_name, last_name, gender, age):
            """初始化属性"""
            self.name = first_name.title() + ' ' + last_name.title()
            self.gender = gender
            self.age = age
    
        def describe_user(self):
            """描述用户的方法"""
            if self.gender == 'male':
                print("This user's name is " + self.name + ", and his age is " + str(self.age) + ".")
            elif self.gender == 'female':
                print("This user's name is " + self.name + ", and her age is " + str(self.age) + ".")
    
        def greet_user(self):
            """问候用户的方法"""
            print("Hello, " + self.name + "!")
    
    
    class Administrator(User):
        """定义子类Administrator继承父类User"""
        def __init__(self, first_name, last_name, gender, age):
            """初始化父类的属性"""
            super().__init__(first_name, last_name, gender, age)
            self.identity = 'administrator'  # 添加子类的特有属性
    
        def greet_admin(self):   # 添加子类的特有方法
            """问候管理员的方法"""
            print("Dear " + self.identity + ":")
            print("Welcome to login, " + self.name + "!")
    
    
    admin = Administrator('lebron', 'james', 'male', 37)
    admin.greet_user() #调用子类继承父类的方法
    admin.greet_admin() # 调用子类特有的方法
    

    运行结果如下图所示。

    可以看到,子类除了有父类的属性和方法,还可以添加新的属性和方法。

    3.重写父类的方法

    对于父类的方法,只要它不符合子类的要求,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。
    下面是重写父类方法的例子。

    class User():
        """定义用户的类"""
        def __init__(self, first_name, last_name, gender, age):
            """初始化属性"""
            self.name = first_name.title() + ' ' + last_name.title()
            self.gender = gender
            self.age = age
    
        def describe_user(self):
            """描述用户的方法"""
            if self.gender == 'male':
                print("This user's name is " + self.name + ", and his age is " + str(self.age) + ".")
            elif self.gender == 'female':
                print("This user's name is " + self.name + ", and her age is " + str(self.age) + ".")
    
        def greet_user(self):
            """问候用户的方法"""
            print("Hello, " + self.name + "!")
    
    
    class Administrator(User):
        """定义子类Administrator继承父类User"""
        def __init__(self, first_name, last_name, gender, age):
            """初始化父类的属性"""
            super().__init__(first_name, last_name, gender, age)
            self.identity = 'administrator'  # 添加子类的特有属性
    
        def greet_admin(self):   # 添加子类的特有方法
            """问候管理员的方法"""
            print("Dear " + self.identity + ":")
            print("Welcome to login, " + self.name + "!")
    
        def describe_user(self):
            """重写父类的方法describe_user()"""
            if self.gender == 'male':
                print("This admin's name is " + self.name + ", and his age is " + str(self.age) + ".")
            elif self.gender == 'female':
                print("This admin's name is " + self.name + ", and her age is " + str(self.age) + ".")
    
    user = User('lebron', 'james', 'male', 37)
    user.describe_user()  # 调用父类方法
    
    admin = Administrator('emma', 'green', 'female', 24)
    admin.describe_user()  # 调用子类重写的父类方法
    

    运行结果如下图所示。

    通过上面运行结果的对比就可以知道,子类成功重写了父类的方法。

    4.将实例用作属性

    使用代码模拟实物时,你可能会发现给类添加的细节越来越多,属性和方法清单以及文件都越来越长,在这种情况下,可能需要将类的一部分作为一个独立的类提取出来,将大型类拆分成多个协同工作的小类。
    下面是将实例用作属性的例子。

    class User():
        """定义用户的类"""
        def __init__(self, first_name, last_name):
            """初始化属性"""
            self.name = first_name.title() + ' ' + last_name.title()
    
        def print_name(self):
            """打印姓名"""
            print("name : " + self.name)
    
    
    class Attribute():
        """定义一个属性类"""
        def __init__(self, gender, age):
            """初始化属性"""
            self.gender = gender
            self.age = age
    
        def describe_attribute(self):
            """描述属性的方法"""
            print("gender : " + self.gender)
            print("age : " + str(self.age))
    
    
    class Administrator(User):
        """定义子类Administrator继承父类User"""
        def __init__(self, first_name, last_name):
            """初始化父类的属性"""
            super().__init__(first_name, last_name)
            self.attribute = Attribute('female', 24)  # 将类用作属性
    
    
    admin = Administrator('emma', 'green')
    admin.print_name()
    admin.attribute.describe_attribute()  # 调用属性中的方法
    

    运行结果如下图所示。

    通过上面的例子可知,一个类可以作为另一个类的属性,这样一来,我们在完成一个复杂的问题时就可以将其拆解为多个小问题,每个小问题对应着一个小类,最后将它们合在一个大类中,大的问题就比较容易的解决了。


    五、类的导入

    如果不断地给类添加新的功能,文件可能变得很长,即便妥善地使用了继承也是如此,因此,可以将类存储在模块中,然后在主程序中导入所需的模块。
    可以在一个模块里只存储一个类,比如在模块user.py中存储着名为User的这一个类,在主程序代码模块中导入该类时使用如下代码。

    from user import User
    

    也可以在一个模块中存储多个类,比如在模块user.py中存储着名为User、Admin等多个类,在主程序代码模块中要导入其中的几个类时使用如下代码。

    from user import User, Admin
    

    还可以使用如下代码导入user.py整个模块,再使用句点表示法访问需要的类。

    import user
    

    导入user.py模块中的所有类使用如下代码。

    from user import *
    

    下面是导入类的例子。
    模块user.py中的代码如下。

    class User():
        """定义用户的类"""
        def __init__(self, first_name, last_name):
            """初始化属性"""
            self.name = first_name.title() + ' ' + last_name.title()
    
        def print_name(self):
            """打印姓名"""
            print("name : " + self.name)
    
    
    class Attribute():
        """定义一个属性类"""
        def __init__(self, gender, age):
            """初始化属性"""
            self.gender = gender
            self.age = age
    
        def describe_attribute(self):
            """描述属性的方法"""
            print("gender : " + self.gender)
            print("age : " + str(self.age))
    
    
    class Administrator(User):
        """定义子类Administrator继承父类User"""
        def __init__(self, first_name, last_name):
            """初始化父类的属性"""
            super().__init__(first_name, last_name)
            self.attribute = Attribute('female', 24)  # 将类用作属性
    

    主程序中的代码如下。
    1.导入user.py整个模块。

    import user
    
    admin = user.Administrator('emma', 'green')
    admin.print_name()
    admin.attribute.describe_attribute()  # 调用属性中的方法
    

    2.从模块user.py中导入类。

    from user import Administrator
    # from user import *
    # from user import User, Attribute, Administrator
    # 对于本例,以上三条导入语法的运行结果一致
    
    admin = Administrator('emma', 'green')
    admin.print_name()
    admin.attribute.describe_attribute()
    

    对于本例而言,上面主程序中的代码不管是导入user.py整个模块还是从模块user.py中导入类,其运行结果都一样,如下图所示。

    合理的导入类对于代码的可读性和维护性都有很大的好处。


    六、Python标准库

    Python标准库是一组模块,安装的Python都包含它,这是其他程序员编写好的模块,有时候我们需要用到它们,在程序开头包含一条import语句即可导入这些模块。
    下面是Python标准库应用的例子。

    from random import randint
    
    
    class Dice():
        """掷骰子"""
        def __init__(self):
            self.sides = 6  #默认是6面的骰子
    
        def roll_dice(self):
            """打印骰子点数"""
            print(randint(1, self.sides))
    
        def change_side(self,side):
            """改变骰子面数"""
            self.sides = side
    
    
    dice = Dice()
    dice.roll_dice()  # 点数在1-6之间
    
    dice.change_side(10)
    dice.roll_dice()  # 点数在1-10之间
    
    dice.change_side(20)
    dice.roll_dice()  # 点数在1-20之间
    

    运行结果如下图所示。

    本例用到的是random模块中的randint函数,这是Python自带的库,不用我们自己写,使用起来非常方便,使用Python标准库可以极大的方便我们编程。


    总结

    以上就是Python中类的介绍及使用的所有内容了,类的创建和使用是最基础也是最重要的;在继承中,子类既保留了父类的属性方法,还可以自己创建独有的属性和方法,将实例用作属性也是非常高效的编程手段;类的导入和Python标准库都是为了方便我们更好的编程,应当熟练运用。
    本文参考书目:Python 编程 :从入门到实践 / (美) 埃里克•马瑟斯(Eric Matthes)著;袁国忠译
    参考博文:
    面向对象与面向过程的本质的区别
    https://zhuanlan.zhihu.com/p/75265007

    来源:西岸贤

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python中类的介绍及使用

    发表回复