Python从入门到入土-面向对象

发布于:2022-12-23 ⋅ 阅读:(470) ⋅ 点赞:(0)

类与对象

创建学生类, 创建一个学生列表,加入3个学生,循环打印学生信息

# 创建学生类, 创建一个学生列表,加入3个学生,循环打印学生信息
# 方式一
class Student:
    # 初始化成员
    def __init__(self, no, name, age):
        self.no = no
        self.name = name
        self.age = age

    # 打印信息
    def dump(self):
        infos = [
            f"* no:{self.no}",
            f"* name:{self.name}",
            f"* age:{self.age}"
        ]
        for info in infos:
            print(info)

# 方式二
# class Student:
#     def __init__(self, no, name, age):
#         self.no = no
#         self.name = name
#         self.age = age
#
#     def dump(self):
#         print(f"* no:{self.no}")
#         print(f"* name:{self.name}")
#         print(f"* age:{self.age}")

# 方式三
# class Student:
#     def __init__(self, no, name, age):
#         self.fields = {
#             'no': no,
#             'name': name,
#             'age': age
#         }
#
#     def dump(self):
#         for field_name in self.fields:
#             field_value = self.fields[field_name]
#             print(f'* {field_name}:{field_value}')

if __name__ == '__main__':
    students = []
    for i in range(0, 3):
        s = Student(i, f'somebody_{i}', 20+i)
        students.append(s)

    for s in students:
        print('')
        s.dump()

类成员

类成员变量可以直接访问,直接调用学生类的成员变量,打印学生信息

# 普通初始化函数添加成员
class Student:
    # 实现含有no/name/age 三个成员属性的学生类
    # 实现方式一
    def __init__(self, no, name, age):
        self.no = no
        self.name = name
        self.age = age
# 实现方式二
# 使用 @dataclass 可以简化实现
# from dataclasses import dataclass
#
# @dataclass
# class Student:
#     no: int
#     name: str
#     age: int

# 实现方式三
# # 使用 @dataclass + slot 可以简化实现并且优化内存占用
# from dataclasses import dataclass
#
# @dataclass
# class Student:
#     __slots__ = ['no', 'name', 'age']
#     no: int
#     name: str
#     age: int

def test():
    students = []
    for i in range(0, 3):
        s = Student(i, f'somebody_{i}', 20+i)
        students.append(s)

    for s in students:
        print('')
        print(f"* no:{s.no}")
        print(f"* name:{s.name}")
        print(f"* age:{s.age}")

if __name__ == '__main__':
    test()

面向对象特性

封装

使用类的方法获取相关信息,可以将内部的实现细节封装起来。

# 封装写法1
# class Student:
#     def __init__(self, no, name, age):
#         self._no = no
#         self._name = name
#         self._age = age
#
#     def no(self):
#         return self._no
#
#     def name(self):
#         return self._name
#
#     def age(self):
#         return self._age

# 封装写法2
# class Student:
#     def __init__(self, no, name, age):
#         self.info =[no, name, age]
#
#     def no(self):
#         return self.info[0]
#
#     def name(self):
#         return self.info[1]
#
#     def age(self):
#         return self.info[2]

# 封装写法3
class Student:
    def __init__(self, no, name, age):
        self.info = {
            'no': no,
            'name': name,
            'age': age
        }

    def no(self):
        return self.info['no']

    def name(self):
        return self.info['name']

    def age(self):
        return self.info['age']

if __name__ == '__main__':
    s = Student(0, f'somebody', 20)
    print(f'* {s.no()}')
    print(f'* {s.name()}')
    print(f'* {s.age()}')

继承

下面是People、Student和Teacher三个类:

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

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

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

if __name__ == '__main__':
    s = Student(0, f'somebody', 20)
    t = Teacher('jladfja', 'linus', 0)

    print('# 教师')
    print(f"* name:{t.name}")
    print(f"* age:{t.age}")
    print('')
    print('# 学生')
    print(f"* no:{s.no}")
    print(f"* name:{s.name}")
    print(f"* age:{s.age}")

实际上Student 和 Teacher 可以从 People 类继承,复用实现:

class Student(People):
    def __init__(self, no, name, age):
        super().__init__(name, age)
        self.no = no

class Teacher(People):
    def __init__(self, access_key, name, age):
        super().__init__(name, age)
        self.access_key = access_key

多态

Student 和 Teacher 类都继承 People 类。Student 和 Teacher 类可以动态改变 People 类的 infos 方法,添加子类新增信息。程序入口可以对它们统一处理,打印他们的基本信息。

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

    def infos(self):
        return [
            f"name:{self.name}",
            f"age:{self.age}",
            f"role:{self.role}"
        ]

class Student(People):
    def __init__(self, no, name, age):
        super().__init__("student", name, age)
        self.no = no

    def infos(self):
        info_list = super().infos()
        info_list.append(f'no:{self.no}')
        return info_list


class Teacher(People):
    def __init__(self, access_key, name, age):
        super().__init__("teacher", name, age)
        self.access_key = access_key

    def infos(self):
        info_list = super().infos()
        info_list.append(f'access_key:{self.access_key}')
        return info_list


if __name__ == '__main__':
    peoples = [
        Teacher("ajladfjkadf", "Linus", 0)
    ]

    for i in range(0, 3):
        s = Student(i, f'somebody_{i}', 20+i)
        peoples.append(s)

    for p in peoples:
        print()
        for info in p.infos():
            print(info)
            

Python类创建

创建点对象,有多种方式创建一个类的实例,我们称一个点的x、y、z都一样的点为对角点。
方式一:

# 添加类静态方法,批量创建对角点
class Point:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

    @staticmethod
    def create_diag_points(count):
        points = []
        for i in range(count):
            points.append(Point(i,i,i))
        return points

if __name__ == '__main__':
    points = Point.create_diag_points(1000)

方式二:

# 通过 @classmethod 装饰器,增加一个类级别的创建方法,批量创建
class Point:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

    @classmethod
    def create_diag_points(cls, count):
        # 在@classmethod修饰的方法中,其中 cls 表示 Point
        points = []
        for i in range(count):
            points.append(cls(i,i,i))
        return points

if __name__ == '__main__':
    points = Point.create_diag_points(1000)

方式三:

class Point:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

if __name__ == '__main__':
    points = []
    for i in range(1000):
        points.append(Point(i,i,i))

抽象类

使用 abc 库,创建抽象 BasePoint 类,创建 Point 子类,实现 dot 抽象方法,计算内积

# 使用 abc 库,创建抽象 BasePoint 类,创建 Point 子类,实现 dot 抽象方法,计算内积

import abc

# 抽象类 BasePoint
class BasePoint:
    def __init__(self, x, y, z) -> None:
        self.x = x
        self.y = y
        self.z = z

    @abc.abstractmethod
    def dot(self, right):
        pass

class Point(BasePoint):
    def __init__(self, x, y, z) -> None:
        super().__init__(x, y, z)

    def dot(self, right):
        return self.x*right.x+self.y*right.y+self.z*right.z

if __name__ == '__main__':
    p1 = Point(0, 1, 2)
    p2 = Point(2, 4, 6)
    assert p1.dot(p2) == 16
    p1 = BasePoint(0, 1, 2)
    p2 = BasePoint(2, 4, 6)
    assert p1.dot(p2) is None

访问控制

分别编写类内部的私有方法,模块级别的私有方法

# 分别编写类内部的私有方法,模块级别的私有方法
class Test:
    def test(self):
        self.__test()

    def __test(self):
        '''类内部的私有方法'''
        print("test")

def _func():
    '''模块级别的私有方法'''
    print("file private")

if __name__ == '__main__':
    t = Test()
    t.test()

获取对象信息

过滤列表里所有含有 ‘z’ 属性的对象,打印他们的 ‘x’+‘y’+‘z’ 的值。

class Point2D:
    def __init__(self, x, y) -> None:
        self.x = x
        self.y = y

class Point3D:
    def __init__(self, x, y, z) -> None:
        self.x = x
        self.y = y
        self.z = z

class Vector2D:
    def __init__(self, x, y) -> None:
        self.x = x
        self.y = y

class Vector3D:
    def __init__(self, x, y, z) -> None:
        self.x = x
        self.y = y
        self.z = z

def test():
    points = [
        Point2D(0, 1),
        Point2D(0, 1),
        Point3D(0, 1, 2),
        Point3D(0, 1, 3),
        Vector2D(0, 1),
        Vector3D(0, 1, 4),
    ]

    z_objects = []
    # 过滤出含有'z'属性的对象,在过滤中打印出对应对象的'z'属性
    for p in points:
        if hasattr(p, 'z'):
            z = getattr(p, 'z')
            print('get z attr:', z)
            z_objects.append(p)

    for p in z_objects:
        print('x+y+z:', p.x+p.y+p.z)

if __name__ == '__main__':
    test()

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位大佬指出。
主页共饮一杯无的博客汇总👨‍💻

保持热爱,奔赴下一场山海。🏃🏃🏃

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到