Python中的静态类变量和方法。
- 如何在Python中创建静态类变量或方法?
- 在Python中静态类变量是可能的吗?
实验。如果我们在Python文档中搜索*"静态类变量",我们将找不到任何接近于这些所谓的变量种类。如果我们尝试在文档的词汇表部分只搜索"static "这个词,我们会看到一些与"静态方法 "*有关的匹配,但没有与变量有关的匹配。
这是因为Python几乎不使用*"静态 "*这个词,而其他语言如C++ 或Java则更常用这个词。
无论如何,由于不同的编程语言之间存在一些平行关系,我们将看到通常被理解为静态类变量和静态方法的东西在Python中是如何实现和工作的。这并不意味着详尽无遗,当然,掌握一些关于类和实例的基本概念是很方便的。
静态类变量
如果你已经有了一些想法,并且想简单地看看它是如何工作的,以及如何实现的,我建议你看下图,那里实际上都是总结出来的。
接下来,我们将用4个简单的步骤来探索这个图形中的代码。
第1步:Python中的类属性
如果我们试着总结一下*"静态类变量 "*在其他编程语言中的含义,我们可以这么说。
定义。静态类变量是由一个类的所有实例共享的变量,这个变量只有一个副本,而不是在该类的每个实例中都有一个副本。
在 Python 中,通常把这个概念称为*"类属性",但也称为"属性类变量"、* "类变量",甚至,尽管不太常见,也称为*"静态变量 "或"静态类变量"。在这里,为了使术语简单化,我们采用"类属性*"这一名称。
让我们看看如何在 Python 中创建和使用*"类属性"*。
在下面的例子中,我们将用一个叫做Employees
的类来模拟一家名为"A"
的公司的雇员。
class Employees:
company = "A" # class attribute
languages = []
我们指出这个类的每个实例(每个具体的雇员)都属于公司"A"
,其类属性company
,其值为"A"
。
然后,我们创建另一个名为language
的*"类属性"*,作为一个空列表,以便以后存储每个雇员的母语。
你可能在想这应该是一个实例属性。但它在这里是为了帮助你看到,作为类属性的可变类型可以带来令人惊讶的结果。我们将在后面看到这一点。
步骤 2: Python 中的实例属性
正如你所看到的,它可以在类定义里面创建,就像你在 Python 中创建任何变量一样,但是在以def
开始的方法之外。
现在我们要用 [__init__()](https://blog.finxter.com/python-init/)
属性 "n
"(来自名称),类Employees
的每个对象(实例)都必须被初始化。
这些属性被称为*"数据属性 "或"实例属性",对应于 C++ 中的数据成员*。
class Employees:
company = "A" # class atribute
languages = []
def __init__(self, name):
self.n = name # data or instance attribute
第三步:在 Python 中创建实例和打印类属性
好了,现在我们要添加代码来创建两个实例并打印它们的类属性。
class Employees:
company = "A" # class atribute
languages = []
def __init__(self, name):
self.n = name # data or instance atribute
e1 = Employees("Peter White")
e2 = Employees("Paul Green")
print(e1.company) # Result: A
print(e2.company) # Result: A
第4步:修改一个类属性
在Python中,我们可以在代码中改变一个*"类属性 "* 的值,并且这些改变将反映在所有的实例中,正如我们在下面的代码中所显示的。
# This code shows only what is added to the previous code and the results you will see
Employees.company = "B" # Changing the value of the class attribute
print(e1.company) # Result: B
print(e2.company) # Result: B
第5步:修改一个类属性成为一个实例属性
而在 Python 中,我们可以将*"类属性 "*改为实例。这可能很罕见,但也是可能的,正如我们在下一个例子中展示的名为 "e1
" 的实例。
# This code shows only what is added to the previous code and the results you will see
e1.company = "C" # Changing the class attribute of the instance e1
print(e1.company) # Result: C
print(e2.company) # Result: B
第6步:理解可变的类属性
最后,我们不应该使用像列表或字典这样的可变数据类型作为 "类属性",因为如果我们像下面的例子那样使用它们,它们可能会有令人惊讶的行为。
在这里,我们试图把每个雇员的母语作为一个类属性,并且以一个空列表开始。
很明显,这是一个 "实例属性",但是让我们对这个例子稍作调整,看看会发生什么。
# This code shows only what is added to the previous code and the results you will see
e1.language.append("english")
e2.language.append("spanish")
print(e1.language) # Result: ['english', 'spanish']
print(e2.language) # Result: ['english', 'spanish']
可以看出,没有得到预期的结果。
- 一方面,这有助于理解母语是每个雇员的属性,也就是每个实例的属性,并且应该像"
[self.n](https://blog.finxter.com/self-in-python/)
"是在[__init__()](https://blog.finxter.com/python-init/)
方法内。 - 另一方面,正如文档中第9.3.5点所述,这有助于看到将可变数据类型实现为 "类属性 "可能会产生令人惊讶的效果。
最后,我建议你看一下本节开头的图,我们试图在这里总结所有这些考虑。
静态方法
正如文档中所说,Python 中的静态方法与 Java 或 C++ 中的静态方法相似。
静态方法是一种可以在没有类的任何实例的情况下运行的方法。它不需要对一个特定的对象进行调用。
如果你想快速了解如何创建和使用静态方法,我建议你看下图,其中总结了最重要的内容。
最现代的Python实现,也就是我们在这里展示的那个,需要在 [@staticmethod](https://blog.finxter.com/python-staticmethod/)
装饰器在启动方法的def
之前。
这告诉 Python 这是一个 "静态方法",而不是其他方法。
由于 "静态方法 "不修改或不需要类的实例来执行,所以它不需要像 "self
"这样的参数,后者代表了调用方法时的实例本身。
注意:我们澄清一下,使用术语"
[self](https://blog.finxter.com/self-in-python/)
"是一个惯例,可以使用另一个词,但这可能使代码的可读性降低,因为每个人都理解并期望在任何实例方法中看到一个"self
"作为第一个参数。
让我们看一个例子,在这个例子中,我们重新学习了上一节中建立的Employees
类。为了展示一些简单的东西,我们将发明一个静态方法,当它被调用时返回程序的版本。
正如我们所看到的,没有必要创建一个实例来调用它。
class Employees:
company = "A"
def __init__(self,name):
self.n = name
@staticmethod
def version():
print("""Welcome to Company A's employee system.
This is the version 1.0
Type "Employees.help(1)" to see how to enter an object.""")
# To call this static method:
Employees.version() # Result: Welcome to Company…
在前面的例子中,"静态方法 "没有参数。
让我们看看另一个,正如第一个 "静态方法 "信息所说,需要一个1来显示第一个帮助信息来创建一个对象或类的实例。
# This code shows only what is added to the previous code and the results you will see
@staticmethod
def help(key):
if key == 1:
print("To create an object you can follow the next example by putting the employee's complete name in parentheses: e1 = Employees('John Black')")
# To call this static method:
Employees.help(1) # Show: To create an object…
结论
我们已经看到了如何实现 "静态类变量",在 Python 中更多地被称为 "类属性"。
它们像任何变量一样简单地被创建,但在类的定义中,在创建方法的 "def
" 之外。
我们也看到了类属性在 Python 中的一些特殊性。
另一方面,我们已经看到了如何实现 "静态方法",它不需要使用任何实例,使用 "@staticmethod
" 装饰器在 "def
" 之前,我们用它来开始定义方法本身。
我们还看到,它不需要 "self
" 作为第一个参数。