PythonOOP快速入门

简介: PythonOOP快速入门

本文整理自下面这个视频,推荐观看:

Object Oriented Programming (OOP) In Python - Beginner Crash Course

author:Python Engineer (Youtube)

前言

谈到OOP,就不得不谈继承、多态和封装。

继承实现了代码重用,并且是多态的基础;

多态提高了代码的灵活性、扩展性;

封装隐藏内部细节,更好地保护数据。

抽象是OOP的基础,有好的抽象能力才能设计出好的基类,好的函数层级…

(by 一只大鸽子)

1. Class & Instance

WHY?

为什么我们需要Class?

如果你的需求很简单,基本数据类型就可以满足,那么不需要Class。

但是随着需求变得复杂,你会发现有非常多的数据和函数需要管理。这个时候就需要用Class了。

举例:

你要写一个管理雇员信息的程序,现在正在写管理“软件工程师”人员的代码。

一个软件工程师有这些信息:职位、姓名、年龄、等级、工资。

你可以用列表来存储,或者用namedtuple来存储信息。没问题,代码可以跑通。但是后面进行操作的时候,就会比较混乱。

因此,我们用类实现“软件工程师”:

__init__中初始化他的信息(属性)。


class SoftwareEngineer:

    def __init__(self, name, age, level, salary):
        self.name = name
        self.age = age
        self.level = level
        self.salary = salary

if __name__ == '__main__':
    se1 = SoftwareEngineer('DD',20,'Senior', 7000)
    

class attributes & instance attributes

刚刚在__init__中的属性是instance attributes

和每一个具体的软件工程师相关(如名字,每个软件工程师都有自己的名字),而class attributes是和类相关,不依赖具体的人(如他们的中文名称都是“软件工程师”)。一般在class 中定义(而不在__init__函数内)。

class SoftwareEngineer:
    # class attributes
    alias = "Keyboard Magician"  # 别名
    cn_name = "软件工程师"

    # instance attributes
    def __init__(self, name, age, level, salary):
        self.name = name
        self.age = age
        self.level = level
        self.salary = salary


if __name__ == '__main__':
    se1 = SoftwareEngineer('DD', 20, 'Senior', 7000)
    print(se1.cn_name)
    print(SoftwareEngineer.cn_name)

2. Functions in Classes

现在我们要让软件工程师写代码了。

我们定义一个函数code(),让某个工程师写代码:

    def code(self):
        print(f"{self.name} is writing code...")

如果想让他用某个语言写代码,可以给函数加一个language参数:

    def code_in_language(self,language):
        print(f"{self.name} is writing code...in {language}")

dunder method

带有双下划线的方法,是Python中的一种特殊方法,也称为魔法方法,会被隐式地自动调用。

例如__init__方法,我们不用手动调用,而是创建对象时自动调用。se1 = SoftwareEngineer('DD', 20, 'Senior', 7000)

类中常用的一个dunder method 是__str__,用来返回实例信息。

    # dunder method
    def __str__(self):
        information = f"name = {self.name}, age={self.age}, level={self.level}"
        return information

__str__方法返回一个包含实例信息的字符串,在print(实例)时会自动调用。

print(se1)

__eq__(self, other) :比较两个对象相等时自动调用,该函数应该返回一个布尔类型值

类中的静态方法

使用@staticmethod修饰。属于类但不属于某个具体的实例(没有self参数)。

    @staticmethod
    def entry_salary(age):
        if age > 25 :
            return 7000
        else:
            return 5000

3. Inheritance 继承

继承(inherits)、扩展(extend)、重写(override)

继承(inherits)

ChildClass(BaseClass)

继承一个类,意味着继承类的属性和方法。

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

    def work(self):
        print(f"f{self.name} is working...")

class SoftwareEngineer(Employee):
    pass

class Desiner(Employee):
    pass

if __name__ == '__main__':
    se = SoftwareEngineer("DD",25,5000, "Junior")
    print(se.name)

扩展(extend)

新增方法。例如可以在SoftwareEngineer中新增debug方法。

class SoftwareEngineer(Employee):
    #override
    def __init__(self,name, age, salary, level):
        super().__init__(name,age,salary)
        self.level = level
    # extend
    def debug(self):
        print(f"{self.name} is debugging...")


重写(override)

和父类方法 同名时会覆盖掉父类方法,

注意:初始化方法__init__重写时必须调用父类的初始化方法super().__init__

否则会出现意想不到的错误(找不到属性等问题)。


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

    def work(self):
        print(f"{self.name} is working...")

class SoftwareEngineer(Employee):
    #override
    def __init__(self,name, age, salary, level):
        super().__init__(name,age,salary)
        self.level = level
    # extend
    def debug(self):
        print(f"{self.name} is debugging...")
    # override
    def work(self):
        print(f"{self.name} is coding...")

class Desiner(Employee):
    # override
    def work(self):
        print(f"{self.name} is designing...")

多态(Polymorphism)

调用同一方法,根据具体的类表现出不同的行为。

    se = SoftwareEngineer("DD",25,5000, "Junior")
    de = Desiner("xd",25,5000)

    employes = [se,de]
    for employe in employes:
        employe.work()


4. Encapsulation(封装)

_salary 以单下划线开头的变量或函数(习惯上地、并非语法规定地)约定为私有变量,不该在外部直接访问或修改。

而应该通过getter和setter方法进行访问和修改。

__xx以双下划线开头的变量会被重命名为_ClassName__xx,避免意外访问。

虽然有这些约定,但是实际上Python没有实现真的私有变量。外部还是可以访问所有变量。

5. Properties(属性)

@property

修饰getter方法, 并且可以通过该函数名x获取属性x。函数名和属性名是一样的。

@x.setter

修饰setter方法,并且修改属性x时会自动调用该方法。

@x.deleter

修饰del 方法, 删除属性x时会自动调用,用的很少。

class SoftwareEngineer():
    #override
    def __init__(self,name, age, salary,level):
        self.name = name
        self.age = age
        self._salary = salary
        self.level = level
    @property
    def salary(self):
        return self._salary
    @salary.setter
    def salary(self, value):
        self._salary = value
    @salary.deleter
    def salary(self):
        del self._salary



if __name__ == '__main__':
    se1 = SoftwareEngineer('DD',25,5000,'Junior')
    print(se1.salary)
    se1.salary = 7000
    print(se1.salary)

相关文章
|
算法 C语言 C++
快速入门C++
快速入门C++
86 0
|
Kubernetes 监控 调度
K8S快速入门
K8S快速入门
131 0
|
Kubernetes Linux API
[没接触过kubevirt?]15分钟快速入门kubevirt
什么是kubevirt? kubevirt是一个容器方式运行虚拟机的项目。`kubevirt`是附加`kubernetes`集群上的,它是通过 `CustomResourceDefinition(CRD)`部署到`Kubernetes API`变成资源对象。使用方式类似创建`deploy、pod`......这些资源清单。
4433 0
[没接触过kubevirt?]15分钟快速入门kubevirt
|
7月前
|
算法 数据可视化 Java
Gephi快速入门
Gephi快速入门
|
7月前
|
存储 编译器 Linux
C++:快速入门篇
C++:快速入门篇
77 0
|
Linux Windows
QMQTT快速入门
环境搭建 • 准备一台linux设备和一台windows设备虚拟机也是可以的; • 安装mosquitto ; • 准备QMQTT环境 - windows下;
174 0
|
SQL 负载均衡 NoSQL
DawnSql快速入门
DawnSql开源分布式数据库,快速入门
DawnSql快速入门
|
SQL 分布式计算 关系型数据库
MLSQL(Byzer)的快速入门
MLSQL(Byzer)的快速入门
MLSQL(Byzer)的快速入门
|
安全 编译器 C语言
【C++】—— 快速入门(2)
【C++】—— 快速入门(2)
106 0
【C++】—— 快速入门(2)
|
自然语言处理 编译器 Linux
【C++】—— 快速入门(1)
【C++】—— 快速入门(1)
266 0
【C++】—— 快速入门(1)