Python静态变量

在 Python 中,静态变量通常是通过类属性来实现的。静态变量是指与类相关联而不是与类的实例相关联的变量。这意味着无论创建多少个类的实例,静态变量都只有一份副本,共享给所有实例。通常,静态变量用于存储与整个类相关的数据,而不是与特定实例相关的数据。

什么是类?

类可以被定义为模板或蓝图(以创建对象),从而允许有效地存储和处理数据。它也可以被假定为用户定义的数据类型,具有自己的一组属性和条件。属性和方法是用于描述属性的术语。

什么是对象(实例)?

对象是一个类实例,包含模板(类)中定义的所有属性和函数(包括它们的值)。(假设它是为数据类型创建的变量。)

一个类可以包含多个实例,每个实例都保存不同的属性值,就像数据类型可以有许多变量,每个变量都包含不同的值一样。

什么是静态变量?

实例变量对于每个实例可以是唯一的,但有时需要整个类共有的属性。静态变量是对整个类保持公共的变量,即不是为每个实例创建一个副本,而是由所有实例共享相同的内存空间静态变量也称为在类内部但在方法外部定义的变量

由于静态变量仅限于类,因此也称为类变量。对象不能影响类变量,静态变量也不能改变对象的条件。

Python 中静态变量的特点

1. 静态变量被称为类变量,因为它只属于定义它的类。

2. 类的所有对象共享静态变量的相同副本。

示例:玩具厂

假设要制造一批宽度和高度相同但长度和颜色不同的乐高积木。

Python静态变量

可以将类假设为包含乐高积木的公共属性的蓝图每个乐高积木都将成为此类的对象,因为它是蓝图的副本,但带有值。宽度和高度是类的静态变量,因为它们对于批次的所有乐高积木保持不变(并且通用)。

现在,让我们学习如何使用玩具工厂在 Python 中创建和访问静态变量。

如何在Python中创建静态变量?

在 Python 中创建静态变量的方法有很多种。

方法一:在类中声明变量

如果您熟悉其他编程语言,您就会知道使用“static”关键字来声明静态变量。Python 没有“static”关键字来声明静态变量。 

在Python中,您 只需在类中声明一个变量,注意它不应该在任何方法中,并且该变量将被称为静态变量或类变量。很容易,对吧?

尝试为我们假设的玩具工厂创建代码:

# 创建乐高积木的蓝图(类)
# 假设长度单位为厘米
class Lego:
    # 声明静态变量
    width = 5   # 静态变量
    height = 5  # 静态变量
    
    # 声明构造函数,接受长度和颜色作为参数
    # 请记住 'self'(对象)会传递给每个方法
    def __init__(self, length, colour):
        self.length = length  # 实例变量
        self.colour = colour
        print('制造了一块颜色为' + colour + '的积木。')

# 创建乐高积木的对象(块)
block1 = Lego(10, '红色')
block2 = Lego(5, '蓝色')

输出:

制造了一块颜色为红色的积木。
制造了一块颜色为蓝色的积木。

上述方法是创建静态变量最简单的方法。

方法2:使用hasattr()方法

Python 还提供了 hasattr() 方法,这是一种内置方法,用于检查对象(传递的参数)是否具有给定的属性。 如果对象具有给定的属性(property),则返回True ,否则返回 False。有两种方法可以使用 hasattr() 方法 –

在构造函数中使用 hasattr() 方法

我们可以通过在构造函数中使用 hasattr() 方法来创建静态变量,以检查是否创建了类变量(静态变量)。您应该知道,我们可以使用“className.staticVariable”格式访问静态变量

 让我们看一下下面的代码,了解如何在构造函数中使用 hasattr() 方法声明静态变量:

# 创建乐高积木的蓝图(类)
# 假设长度单位为厘米
class Lego:
    
    # 声明构造函数,接受长度和颜色作为参数
    # 请记住 'self'(对象)会传递给每个方法
    def __init__(self, length, colour):
        # 检查类 Lego 是否具有属性 width
        if not hasattr(Lego, 'width'):
            print('创建了静态变量')
            Lego.width = 5  # 类/静态变量
        if not hasattr(Lego, 'height'):
            print('创建了静态变量')
            Lego.height = 5  # 类/静态变量
            
        self.length = length
        self.colour = colour
        print('制造了一块颜色为' + colour + '的积木。')

# 创建乐高积木的对象(块)
block1 = Lego(10, '红色')
block2 = Lego(5, '蓝色')

我们使用了“ not hasattr() ”,因为传递的参数(即我们的乐高类)没有属性“宽度”和“高度”。因此,当我们创建第一个实例时,该方法返回 false。为了更好地观察,我在两个 if 块中添加了一条打印语句。输出如下:

创建了静态变量
创建了静态变量
制造了一块颜色为蓝色的积木。
制造了一块颜色为蓝色的积木。

您会想知道为什么在创建第一个对象(block1)后不重复“静态变量创建”行?这是因为一旦为 Lego 类创建了变量“width”和“height”,那么当再次调用 hasattr() 方法时,它会返回 False,即 Lego 类已经具有上述属性。

b. 在方法内部使用 hasattr() 方法

当您必须仅在调用某个方法时创建静态变量时,此方法很有用。假设要添加一个名为“blocks”的静态变量到我们的类中。我们可以创建一个方法,向我们引入“blocks”变量。查看下面的代码以获得更好的参考 – 

# 创建乐高积木的蓝图(类)
# 假设长度单位为厘米
class Lego:
    
    # 声明构造函数,接受长度和颜色作为参数
    # 请记住 'self'(对象)会传递给每个方法
    def __init__(self, length, colour):
        self.length = length
        self.colour = colour
        print('制造了一块颜色为' + colour + '的积木。')
    
    # 使用方法来创建一个静态变量
    def staticMethod(self):
        if not hasattr(Lego, 'blocks'):  # 使用 hasattr() 函数
            Lego.blocks = 12  # 创建类变量
            print('创建了乐高积木的静态变量')

# 创建乐高积木的对象(块)
block1 = Lego(10, '红色')
block2 = Lego(5, '蓝色')
# print(block1.blocks)
block1.staticMethod()
print(block1.blocks)  # 使用对象访问静态变量 blocks
print(block2.blocks)  # 使用对象访问静态变量 blocks

您会注意到,如果在调用创建的 staticMethod() 之前运行注释 #print(block1.blocks) ,它会给我们一个错误,因为静态变量“blocks”在您调用之前不会被创建方法。

输出:

制造了一块颜色为红色的积木。
制造了一块颜色为蓝色的积木。
创建了乐高积木的静态变量
12
12

您是否注意到我们没有通过第二个对象调用 staticMethod(),但它却能够访问“blocks”变量?因此,证明我们的静态变量已创建。

如何在Python中访问静态变量?

到目前为止,我们已经学习了如何创建静态变量;现在让我们看看如何访问这些静态变量以便我们可以使用它们。

方法一:使用类名

我们可以直接使用类名来调用静态变量(类变量)。相同的情况可以有两个用例 –

(i) 访问类中的静态变量

(ii) 在main方法中调用静态变量

这两种方法都显示如下:

# 创建乐高积木的蓝图(类)
# 假设长度单位为厘米

class Lego:
    # 声明静态变量
    width = 5   # 静态变量
    height = 5  # 静态变量
    
    # 声明构造函数,接受长度和颜色作为参数
    def __init__(self, length, colour):
        self.length = length  # 实例变量
        self.colour = colour
        print('制造了一块颜色为' + colour + '的积木。')
    
    # 创建一个方法来访问类内的静态变量
    def printStatic(self):
        print('静态变量的值为:宽度 = ', Lego.width, ' 和 高度 = ', Lego.height)

# 创建乐高积木的对象(块)
block1 = Lego(10, '红色')
block2 = Lego(5, '蓝色')
# 在主方法中使用类名调用静态变量
print(Lego.width)
# 调用方法以显示访问静态变量的方式
block1.printStatic()

输出:

制造了一块颜色为红色的积木。
制造了一块颜色为蓝色的积木。
5
静态变量的值为:宽度 = 5 和高度= 5

方法 2:使用对象名称

也可以使用对象的名称来调用类变量。看看下面的代码: 

# 创建一个乐高积木蓝图(类)
# 假定尺寸单位为厘米

class Lego:
    # 声明静态变量
    width = 5   # 静态变量
    height = 5  # 静态变量
    
    # 声明构造函数,接受长度和颜色作为参数
    def __init__(self, length, colour):
        self.length = length  # 实例变量
        self.colour = colour
        print('制造了一块颜色为' + colour + '的积木。')

# 创建一个 Lego 类的对象(积木块)
block1 = Lego(10, '红色')
block2 = Lego(5, '蓝色')

# 使用对象调用静态变量
print(block1.width)
print(block2.height)

输出:

制造了一块颜色为红色的积木。
制造了一块颜色为蓝色的积木。
5
5

请记住,在 Python 中,只能通过对象访问静态变量。您不能使用类的实例来更改静态变量。例如 – 

# 创建一个乐高积木蓝图(类)
# 假定尺寸单位为厘米

class Lego:
    # 声明静态变量
    width = 5   # 静态变量
    height = 5  # 静态变量
    
    # 声明构造函数,接受长度和颜色作为参数
    def __init__(self, length, colour):
        self.length = length  # 实例变量
        self.colour = colour
        print('制造了一块颜色为' + colour + '的积木。')

# 创建一个 Lego 类的对象(积木块)
block1 = Lego(10, '红色')
block2 = Lego(5, '蓝色')

# 使用对象调用静态变量
print('积木块1的宽度: ', block1.width)
print('积木块2的宽度: ', block2.height)

# 通过对象访问静态变量以更改其值
block1.width = 10
print('积木块1的宽度: ', block1.width)
print('积木块2的宽度: ', block2.width)
print('积木块的宽度: ', Lego.width)

在上面的代码中,我们尝试使用对象“block1”更改静态变量“width”的值。

输出:

制造了一块颜色为红色的积木。
制造了一块颜色为蓝色的积木。
积木块1的宽度: 5
积木块2的宽度: 5
积木块1的宽度: 10
积木块2的宽度: 5
积木块的宽度: 5

请记住,您不能使用对象更改静态变量。它只会为该对象创建该变量的新实例。

方法3:使用__class__方法

访问静态变量的另一种方法是使用 __class__ 方法。您可以通过在对象的帮助下调用静态变量来访问静态变量。
基本语法:
objectName.__class__.staticVariableName
可以称为使用类名间接访问静态变量。下面我们看看它的实现: 

# 创建一个乐高积木蓝图(类)
# 假定尺寸单位为厘米

class Lego:
    # 声明静态变量
    width = 5   # 静态变量
    height = 5  # 静态变量
    
    # 声明构造函数,接受长度和颜色作为参数
    def __init__(self, length, colour):
        self.length = length  # 实例变量
        self.colour = colour
        print('制造了一块颜色为' + colour + '的积木。')

# 创建一个 Lego 类的对象(积木块)
block1 = Lego(10, '红色')
block2 = Lego(5, '蓝色')

# 使用 __class__ 方法调用静态变量
print('积木块的宽度: ', block1.__class__.width)
# 注意点操作符的重要性。

 .__class__. 调用实例(block1)的类,因此返回“width”变量的值,以类(Lego)为参考。 

输出:

制造了一块颜色为红色的积木。
制造了一块颜色为蓝色的积木。
积木块的宽度: 5

方法 4:使用 type() 方法

该方法可以看作是通过Class对静态变量的间接调用。type() 方法返回我们作为参数传递给它的变量的数据类型。当一个对象作为参数传递给 type() 方法时,它将返回 Class。让我们看看下面的语法 –

# 创建一个乐高积木蓝图(类)
# 假定尺寸单位为厘米

class Lego:
    # 声明静态变量
    width = 5   # 静态变量
    height = 5  # 静态变量
    
    # 声明构造函数,接受长度和颜色作为参数
    def __init__(self, length, colour):
        self.length = length  # 实例变量
        self.colour = colour
        print('制造了一块颜色为' + colour + '的积木。')

# 创建一个 Lego 类的对象(积木块)
block1 = Lego(10, '红色')
print('积木块1的高度: ', block1.height )
print("积木块的高度: ", type(block1).height)

输出:

制造了一块颜色为红色的积木。
积木块1的高度: 5
积木块的高度: 5

静态变量的优点:

  • 内存效率:由于静态变量在类的所有实例之间共享,因此它们可以通过避免创建相同数据的多个副本来节省内存。
  • 共享状态:静态变量可以提供一种在类的所有实例之间维护共享状态的方法,允许所有实例访问和修改相同的数据。
  • 易于访问:可以使用类名本身来访问静态变量,而不需要类的实例。这可以更方便地访问和修改存储在静态变量中的数据。
  • 初始化:静态变量可以在类定义时进行初始化,这样很容易确保变量有一个有效的起始值。
  • 可读性:静态变量可以提高代码的可读性,因为它们清楚地表明存储在变量中的数据在类的所有实例之间共享。

静态变量的缺点:

  • 不灵活:静态变量可能不灵活,因为它们的值在类的所有实例之间共享,因此很难为不同的实例提供不同的值。
  • 隐藏依赖:静态变量可以在代码的不同部分之间创建隐藏依赖,从而使代码难以理解和修改。
  • 线程安全:静态变量在多线程环境中可能会出现问题,因为如果同步不正确,它们可能会引入竞争条件和同步问题。
  • 命名空间污染:静态变量可以添加到类的命名空间中,可能导致名称冲突并使代码更难维护。
  • 测试:静态变量会使编写有效的单元测试变得更加困难,因为静态变量的状态可能会影响类及其方法的行为。

总体而言,静态变量可以成为 Python 编程中的有用工具,但应谨慎使用它们并注意潜在的缺点,例如不灵活性、隐藏依赖项和线程安全问题。

原创文章,作者:jkhxw,如若转载,请注明出处:https://www.jkhxw.com/python-static-variable/

(0)
上一篇 2023年9月26日
下一篇 2023年9月27日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注