【Python入门】类和对象

文章一览

  • [一、面向过程编程 VS 面向对象编程](#一、面向过程编程 VS 面向对象编程)
    • [1.1 基本概念](#1.1 基本概念)
    • [1.2 结构和组织](#1.2 结构和组织)
    • [1.3 数据安全](#1.3 数据安全)
    • [1.4 代码重用](#1.4 代码重用)
    • [1.5 维护性和扩展性](#1.5 维护性和扩展性)
    • [1.6 编程范式](#1.6 编程范式)
  • [二 、类和对象](#二 、类和对象)
    • [2.1 创建类](#2.1 创建类)
    • [2.2 init 函数](#2.2 init 函数)
      • [init() 方法小结:](#init() 方法小结:)
    • [2.3 类继承](#2.3 类继承)
      • [2.3.1 继承概念](#2.3.1 继承概念)
      • [2.3.2 super() 方法的使用](#2.3.2 super() 方法的使用)
    • [2.4 object 类](#2.4 object 类)

一、面向过程编程 VS 面向对象编程

面向过程编程(Procedural Programming)和面向对象编程(Object-Oriented Programming, OOP)是两种不同的软件设计方法。各自有不同的特点和适用场景。

1.1 基本概念

  • 面向过程编程:这种编程方式强调的是过程和步骤,即程序是一系列操作的集合,这些操作按照一定的顺序执行来完成任务。它通常围绕函数和数据结构来组织代码
  • 面向对象编程:这种编程方式则是以对象为中心,对象是数据(属性)和操作数据的方法(行为)的封装体。OOP强调的是对象之间的交互来完成任务

1.2 结构和组织

  • 面向过程:程序被组织成一系列函数调用,每个函数负责完成特定的任务。数据和函数是分离的
  • 面向对象:程序由多个类组成,每个类可以包含数据成员和成员函数(方法)。类通过继承和组合的方式组织起来,形成一个层次结构

1.3 数据安全

  • 面向过程:由于数据和处理数据的函数是分开的,因此保护数据不被意外修改较为困难
  • 面向对象:提供了封装机制,可以限制对对象内部状态的访问,从而提高数据的安全性

1.4 代码重用

  • 面向过程:代码重用主要是通过函数的形式实现,但这种方式可能需要更多的参数传递,导致接口复杂
  • 面向对象:通过继承和多态等特性,可以很容易地扩展和重用现有代码,而不需要修改原来的代码

1.5 维护性和扩展性

  • 面向过程:随着程序规模的增长,维护难度会增加,因为过程之间的依赖关系可能会变得非常复杂
  • 面向对象:由于对象是独立的单元,因此更容易进行维护和扩展。面向对象的设计鼓励将复杂的系统分解为更小、更易于管理的部分

1.6 编程范式

  • 面向过程:更适合解决那些可以通过清晰定义的过程或算法来描述的问题
  • 面向对象:更适合于模拟现实世界中的实体及其交互,特别是在构建大型、复杂的应用程序时

面向过程是编年体,面向对象是纪传体。与"编年体"不同,"纪传体"侧重于描述人物生平或特定主题的历史,比如《史记》

面向对象编程关注的是对象之间的关系和交互,而不是单一的流程或步骤。通过对象之间的互动来构建应用程序的功能

每种编程范式都有其优势和局限性,选择哪种方式取决于具体的应用需求和个人偏好。在实际开发中,有时候也会结合使用这两种编程风格,以发挥各自的长处

二 、类和对象

Python 中,一切皆对象!

面向对象编程有 2 个非常重要的概念:类和对象

人以类聚,物以群分。类(Class)是具有相同属性(Attribute) 行为(Method)事物的统称。类是抽象

对象(Object) :是类(Class) 的具体实例

类就相当于制造飞机时的图纸,用它来进行创建的飞机就相当于对象

通过类定义数据类型的属性 (数据)和行为(方法),将行为和属性打包在一起

所谓方法 ,就是类里面的函数属性 就是类里的变量

从一个类创建对象时,每个对象会共享 这个类的行为(类中定义的方法)和属性,但对象也会有自己的属性值(不共享)。

在描述一个真实对象(物体)时包括两个方面

  • 行为:可以做什么
  • 属性(特征):是什么样的

结论:对象 = 属性(特征或数据)+ 方法(行为)

2.1 创建类

在python中,把具有相同属性和方法的对象归为一个(class),内容包括:

  • 类名:类似于函数名,创建类时需要一个类名
  • 属性(Attribute):类里面用于描述所有对象共同特征的变量数据
  • 方法(Method):类里面的函数 ,用来区别类外面的函数,也称为成员函数。 用来实现某些功能。比如打印出学生的名字和分数

要创建一个类需要使用关键词:class

类结构:

python 复制代码
class 类名:
    def __init__(self,parm1,parm2...)
        self.parm1 = parm1
        self.parm2 = parm2
        ......
    def 成员函数1(self,parm1,parm2...):
        ......
    def 成员函数2(self,parm1,parm2...):
        ......
    def 成员函数n(self,parm1,parm2...):        ......
python 复制代码
# 创建一个学生类
class Student:
# 定义学生属性,初始化方法
    def __init__(self, s_name, s_score):
        self.name = s_name
        self.score = s_score
    # 定义打印学生信息的方法
    def show(self):
        print(f'Name: {self.name} Score: {self.score}')

和普通函数相比,在类中定义的函数第一个参数 永远是变量 self!调用时,不用传递该参数,只需要传递后面的参数即可,所谓的 self,可以理解为自己,就是对象自身的意思。

为什么每个类实例方法都有一个参数self,它到底有什么作用呢?

​ 想要理解 self 有个最简单的方法,就是把 self 当做实例(对象)的身份证。换句话就是把属性的值绑定在实例对象上。

​ 每个人可以凭借身份证去上大学、坐高铁、住酒店...(方法),而Python中的实例(对象)也可以凭着 self 去调用类的方法

​ 如果前面没有 self ,python认为是给普通的变量赋值,不会把这个值看成是对象的属性值

类是抽象 的,不能直接使用。只有通过创建实例(对象)才能发挥它的功能,每个实例(对象)都是独一无二的,它可以调用类的方法、属性。

**例:**创建一个汽车类

python 复制代码
#创建汽车类
class Car:
    # 移动
    def move(self):
        print('车在奔跑')
    # 拐弯
    def left(self):
        print('车在左拐')
        
# 创建一个红旗车对象HQ
HQ = Car()
HQ.move()
HQ.left()
HQ.color = '黑色'
HQ.wheelNum = 4 #轮子数量
print(HQ.color)
print(HQ.wheelNum)

HQ = Car(),产生了一个Car的实例对象,此时也可以通过对象 HQ 来访问属性或者方法

第一次 使用 HQ.color = '黑色',表示给 HQ 这个对象添加属性 ,如果后面再次出现 HQ.color = xxx 表示对属性进行修改

有没有办法能够在创建对象的时候,就顺便把对象的属性给设置了呢?

​ 可以在创建实例的时候,把一些认为必须绑定的属性填写进去。

2.2 init 函数

python 复制代码
#创建汽车类
class Car:
    def __init__(self):
        self.wheelNum = 4
        self.color = '蓝色'
    # 移动
    def move(self):
        print('车在奔跑')
HQ = Car()
HQ.move()
print(HQ.color)
print(HQ.wheelNum)  

init (initialize)是类的构造(初始化)函数。用来完成一些默认的设定

注意 :"init"前后分别有两个下划线!!!

init () 这个方法会在创建对象时完成初始化初始化函数,创建 Car 对象后,在无调用 init() 的前提下,HQ 就默认拥有了 2 个属性 color 和 wheelNum,使用点号 . 来访问对象的属性。

既然在创建完对象后 init() 方法已经被默认的执行了,那么能否让对象在调用它的时候能传递一些参数呢?如果可以,那怎样传递呢?

python 复制代码
#创建汽车类
class Car:
    def __init__(self, WheelNum, Color):
        self.wheelNum = WheelNum
        self.color = Color
    # 移动
    def move(self):
        print('车在奔跑')
              
# 创建一个红旗车和宝马车对象,HQ和BWM
HQ = Car(4, 'black')
BMW = Car(4, 'white')
print('红旗车颜色:',HQ.color)
print('宝马车颜色:',BMW.color)

init() 方法小结:

  1. init()方法第一个参数永远是 self,表示创建的实例本身。默认有 1 个参数时,名字为 self,如果在创建对象时传递了 2 个实参,那么__init__(self)中除了 self 作为第一个形参外还需要 2 个形参

  2. init() 方法内部,就可以把各种属性绑定到 self,因为 self 就指向创建的实例本身

  3. 在创建一个对象时默认被调用,不需要手动调用

  4. 和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量 self,并且,调用时,不用传递该参数,python解释器会自动把当前的对象引用传递进去

python 复制代码
# 创建一个狗类
class Dog:
# 定义狗的属性,初始化方法
    def __init__(self, dog_name, dog_age, dog_color):
        self.name = dog_name
        self.age = dog_age
        self.color = dog_color
    def speak(self):
        print ('汪'*self.age)

dog1 = Dog('jone',2,'白色')
dog1.speak()  

创建一个矩形类

python 复制代码
class rectangle:
    def __init__(self,w,h):
        self.w,self.h = w,h
    def area(self):
        return self.w * self.h
    def perimeter(self):
        return 2*(self.w + self.h)
    
w = eval(input('输入长方形边宽:'))
h = eval(input('输入长方形边长:'))
rect = rectangle(w,h)
print ('面积:',rect.area())
print ('周长:',rect.perimeter())

类的作用:就是将数据 (属性)和操作数据的函数 (方法)捆绑在一起,当作一个整体使用

2.3 类继承

面向对象的编程带来的主要好处之一是代码的重用,为了避免每个类都从头编写的重复劳动,实现各种重用的方法之一是通过继承机制

2.3.1 继承概念

继承是类与类的一种关系,是一种子类与父类的关系

用代码表示继承,语句是:

class A (B): A ------子类名;B:父类名

A 类继承了 B 类全部的属性和方法

python 复制代码
class Person:        
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def eat(self):
        print('吃海鲜去')
# 定义子类
class Student(Person):  
    def __init__(self,ID = 202999):
        self.id = ID
        
    def study(self):
        print('Python语言')
        
s = Student()   # 实例化子类
s.study()       # 调用子类的方法
s.eat()         # 调用父类方法
  1. 虽然Student类没有定义eat函数,但它继承了Person类,所以默认有eat函数

  2. 如果 Student 类有自己定义的 eat 函数,就会调用自己的

  3. 父类 Person 里构造函数 init 中的属性 name、age,子类 Student 能使用吗?

    ​ 在创建子类实例的时候,会优先调用子类 的构造函数 init ,导致实例只有ID属性

​ 一个办法是在子类 init 里,把name、age等属性全部写上,但造成重复写代码!

​ 一个优雅的做法是:在子类下面,用 super 这个方法

2.3.2 super() 方法的使用

在面向对象编程中,super() 是一个非常有用的内置函数,它主要用于处理类的继承关系,特别是多重继承的情况

super() 主要用于调用父类的方法,这样可以避免显式地指定父类的名称,从而提高代码的可维护性和灵活性。

python 复制代码
class Base:
    def __init__(self):
        print("Base class constructor")
        
# 继承 Base 类
class Derived (Base): 
    def __init__(self):
        super().__init__()  # 调用父类的构造函数
        print("Derived class constructor")

# 创建 Derived 类的实例
d = Derived()	
python 复制代码
class Person:        
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def eat(self):
        print('吃海鲜去')
        
 # 定义子类       
class Student(Person):  
    def __init__(self,name,age,ID):
        super().__init__(name, age) #调用父类的构造函数
        self.id = ID
        print (f'{name}的年龄是{age},学号是{ID}')
        
    def study(self):
        print('Python语言')
        
s = Student('zhangsan',20,2024111)   # 实例化子类
s.study()       # 调用子类的方法
s.eat()         # 调用父类方法

super 的设计目的是用来解决多重继承时父类的查找问题,所以在单重继承中用不用都没关系,但是使用 super 是一个好的习惯。一般在子类中需要调用父类的方法时才会这么用

python 复制代码
class Animal:
    def __init__(self, name):
        self.name = name
    def greet(self):
        print ('Hello, it is %s.' % self.name)

        class Dog(Animal):
    def greet(self):
        super().greet()
        print ('WangWang...')
dog = Dog('dog')
dog.greet()

2.4 object 类

所有类都是 object 类的派生类,因而具有 object 类的各种属性和方法

python 复制代码
class A:
    def func(x):
        pass

print (dir(A))

例题:

定义一个学生类,要求:

属性包括学生姓名、学号,以及C语言、Python语言和离散数学三科的成绩

能够设置学生某科目的成绩

能够打印出该学生的所有科目成绩

python 复制代码
class Student:
    def __init__(self, name, student_id):
        self.name = name
        self.student_id = student_id
        self.grades = {'c语言': 0, 'Python语言': 0, '离散数学': 0}
       
    def set_grade(self, course, grade):
        for course in self.grades:
            self.grades[course] = grade

    def print_grades(self):
        print(f'学生: {self.name}    学号: {self.student_id} 的成绩为: ')
        for course in self.grades:
            print(f'{course}: {self.grades[course]} 分')

# 学生类实例化
zhang = Student ("小张","2024000111")
zhang.set_grade ("Python语言", 90)
zhang.set_grade ("离散数学", 85)
相关推荐
白瑕15 分钟前
[JavaScript] 我该怎么去写一个canvas游戏
前端·javascript
m0_7482489416 分钟前
前端篇-Content-Type 详解
前端
m0_7482550218 分钟前
新手参加2025年CTF大赛——Web题目的基本解题流程
前端·网络·安全
不如语冰21 分钟前
深度学习Python基础(2)
人工智能·python·深度学习·语言模型
正在努力中的小白♤22 分钟前
多个JAVA环境变量安装配置
java·开发语言·python
憨憨小江24 分钟前
Vue3 基础记录
前端
SANG嘻嘻嘻31 分钟前
ES6中的map和set
前端·javascript·es6
七夜星七夜月43 分钟前
时间序列预测论文阅读和相关代码库
论文阅读·python·深度学习
fantasy_arch44 分钟前
CPU性能优化--前端优化
前端·性能优化
19999er1 小时前
CDN信息收集(小迪网络安全笔记~
服务器·网络·笔记·安全·web安全