IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python系列(八):“一网打尽”类 -> 正文阅读

[Python知识库]Python系列(八):“一网打尽”类

一.类概述

作为一门面向对象(Object)的编程语言,Python的核心当然包含类(class)的设计。本文详细介绍了类的方法面面,具体介绍内容包括如下图所示:

python-class

二.变量

2.1 类变量

类变量会在所有类实例间共享,类实例还未创建时,类变量就已经存在。类变量在所有方法之外定义,通常是在类头的正下方以及构造函数和其它方法之前。

class People():
    class_name = "demo" # 类变量

    def __init__(self):
        pass


if __name__ == "__main__":
    print(People.class_name)
    # demo
    print(People().class_name)
    # demo

类变量可以通过类名直接引用,也可以通过类实例来引用。

2.2 类实例变量

类实例变量由类实例所拥有,每个类实例都由自己一套独立的类实例变量。

class People():
    class_name = "demo"  # 类变量

    def __init__(self, name="", age=1, sex="M") -> None:
        self.name = name  # 类实例变量
        self.age = age
        self.sex = sex


if __name__ == "__main__":
    p = People(name="Tom")
    p1 = People(name="Tony")
    print(p.name, p1.name)
    # Tom Tony

三.类中的方法

3.1 实例方法

实例方法(instance methods)对由实例变量提供的数据/值执行一系列的操作。实例方法的第一个参数须为self,它指的是当前对象,用于访问类中的变量和方法。实例方法不在类间共享。下面的示例代码中,__init__print_info都是类的实例方法。

class People():
    def __init__(self, name="", age=1, sex="M") -> None:
        self.name = name
        self.age = age
        self.sex = sex

    def print_info(self):
        print(f"Name: {self.name}, Age: {self.age}, Sex: {self.sex}")


if __name__ == "__main__":
    p = People("Tom", 22, "M")
    p.print_info()

3.1.1 类初始化方法

这里着重介绍一下类的初始化方法__init__(),该方法在类实例创建的时候该方法会被自动调用

在类的构造方法中,若存在继承关系,可以通过super()方法来调用父类的初始化方法完成父类属性的初始化。

super()方法可以返回超类的临时对象,然后可以通过它调用超类的方法。super()方法可以包含两个参数:

  • 子类(subclass);
  • 子类的一个实例对象。
class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * self.length + 2 * self.width

class Square(Rectangle):
    def __init__(self, length):
        super(Square, self).__init__(length, length)

Python3中super(Square, self)的调用等效于无参super()的调用。

3.1.2 __call__方法

Python允许class定义特殊的实例方法__call__,通过该方法可以让像调用函数一样调用对象

from collections import defaultdict


class CountMissing():
    def __init__(self):
        self.add = 0

    def __call__(self):
        self.add += 1
        return 0


if __name__ == "__main__":
    items = {'apple': 3, 'banana': 2}
    goods = [('orange', 6), ('watermelon', 1), ('strawberry', 9), ('apple', 8)]
    # 统计goods在items不存在的水果类别
    counter = CountMissing()
    items = defaultdict(counter, items)
    for fruit, num in goods:
        items[fruit] += num
    print(counter.add)
    # 3

3.2 类方法

同类变量一样,类方法(class methods)是所有类示例共享的方法。类方法只能访问类变量,而不能访问类实例变量(因为类实例还未创建)。类方法可以通过修改类变量来修改类的状态

3.2.1 通过@classmethod装饰器

在Python中,可以使用@classmethod装饰器来将方法声明为类方法。

class People():
    class_name = "demo"  # 类属性

    def __init__(self, name="", age=1, sex="M"):
        self.name = name  # 实例属性
        self.age = age
        self.sex = sex

    @classmethod
    def print_info(cls):
        print(f"class name: {cls.class_name}")


if __name__ == "__main__":
    People.print_info()
    # class name: demo
    People().print_info()
    # class name: demo

类方法的注意事项包括:

  • 第一个参数必须为cls
  • 类方法仅能访问类变量,例如class_name,但不能访问实例属性,例如self.name
  • 既可以通过类名.方法名来调用,也可以通过类实例对象.方法名来调用。

使用@classmethod的好处:在之后重构类时,不需要修改初始化函数,只需额外添加处理的函数,然后使用@classmethod即可。

3.2.2 通过classmethod()方法

Python中还可以通过内置的classmethod(function)方法来将正常的方法的方法转换为类方法,其中function便是要转换为类方法的函数名。

class People():
    class_name = "demo"  # 类属性

    def __init__(self, name="", age=1, sex="M"):
        self.name = name  # 实例属性
        self.age = age
        self.sex = sex

    def print_info(cls):
        print(f"class name: {cls.class_name}")


if __name__ == "__main__":
    People.print_info = classmethod(People.print_info)
    People().print_info()
    # class name: demo

3.3 静态方法

静态方法(static methods)与类方法有些相似,它也是绑定在类上,而不是类实例对象上。但静态方法没有像selfcls这样的隐式的第一个参数,这意味着它不能访问类变量和类实例变量。静态方法也能通过类名.静态方法名的方式来调用。

与类方法类似,静态方法通过可以通过@staticmethod装饰器或内置的staticmethod(function)方法来定义。

class People():
    class_name = "demo"  # 类属性

    def __init__(self, name="", age=1, sex="M"):
        self.name = name  # 实例属性
        self.age = age
        self.sex = sex

    @staticmethod
    def temp(x):
        print(x)

    def temp1(x, y):
        print(x + y)


if __name__ == "__main__":
    People.temp1 = staticmethod(People.temp1)
    People.temp(10) # 10
    People.temp1(10, 20) # 30

四.类装饰器

4.1 @property装饰器

Python提供了@property装饰器,它使得在类中使用gettersetter变得容易。一般情况下,只要不将类属性设置为私有属性就可以在类外自由的使用类属性。但是有时候,可能希望在设置属性时进行一些特殊的行为,例如检查设置的值是否大于0。这种情况下,@property装饰器便能排上用场了,例如:

class Circle():

    def __init__(self, radius):
        self.radius = radius

    @property
    def radius(self):
        return self.radius

    @radius.setter
    def radius(self, radius):
        if radius <= 0:
            raise ValueError(f"Circle's radius must be > 0, but get {radius}")
        self.radius = radius


c = Circle(-2)
# ValueError: Circle's radius must be > 0, but get -2

在该例子中,类初始化传入参数radius=-2,在类初始化函数中当执行self.radius = radius时会自动调用@radius.setter方法,其检查raduis的值小于等于0,引发异常。

五.访问权限控制

Python的类同样也有类似Java和C++的访问权限控制,它同样可以分为PublicProtectedPrivate

  • 公有:默认的方法和成员权限,通过对象的点运算符.访问即可直接访问;
  • 受保护:以单下划线开头_,只能通过类方法和子类本身进行访问。注意,这并非是强制要求,只是希望用户遵循这样的要求。
  • 私有:以双下划线__开头,只能通过类方法访问。
class People():
    def __init__(self, name, age, id):
        self.name = name  # public
        self._age = age  # protected
        self.__id = id  # private

    def _protected_mthd(self):
        print("Protected")

    def __private_mthd(self):
        print("Private")


if __name__ == "__main__":
    p = People("Tom", 22, "1001")
    print(p._age) # 虽然定义为包含类型,但还是可以直接访问,只是Python不建议这样做
    # 22
    p._protected_mthd()
    # Protected
    print(p.__id)
    # AttributeError: 'People' object has no attribute '__id'
    p.__private_mthd()
	# AttributeError: 'People' object has no attribute '__private_mthd'

5.1 私有类型的名称转写机制

实际上,Python中并没有禁止访问类中某一成员的保护机制。在外界看来无法访问私有属性的原因并不是因为保护机制,而是类方法使用了名称转写机制,即对于私有属性__X,其会被转写为_classname__X,其中classname为类名(私有方法也类似)。

print(p._People__id)
# 1001
p._People__private_mthd()
# Private

通过上述的名称转写机制,可以避免类继承过程中的命名冲突(子类定义与父类相同名称的属性)。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-06-21 21:25:35  更:2022-06-21 21:25:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:32:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码