如何在Python中创建类(即静态)变量或方法?
当前回答
您还可以使用元类强制类为静态类。
class StaticClassError(Exception):
pass
class StaticClass:
__metaclass__ = abc.ABCMeta
def __new__(cls, *args, **kw):
raise StaticClassError("%s is a static class and cannot be initiated."
% cls)
class MyClass(StaticClass):
a = 1
b = 3
@staticmethod
def add(x, y):
return x+y
然后,每当您意外尝试初始化MyClass时,都会收到StaticClassError。
其他回答
使用Object数据类型是可能的。但是对于bool、int、float或str等原始类型,bahaviour与其他OOP语言不同。因为在继承类中不存在静态属性。若继承类中不存在该属性,Python将开始在父类中查找该属性。如果在父类中找到,将返回其值。当您决定更改继承类中的值时,将在运行时创建静态属性。在下一次读取继承的静态属性时,将返回其值,因为它已经定义。对象(列表、字典)用作引用,因此可以安全地将它们用作静态属性并继承它们。对象地址在更改其属性值时不会更改。
整数数据类型示例:
class A:
static = 1
class B(A):
pass
print(f"int {A.static}") # get 1 correctly
print(f"int {B.static}") # get 1 correctly
A.static = 5
print(f"int {A.static}") # get 5 correctly
print(f"int {B.static}") # get 5 correctly
B.static = 6
print(f"int {A.static}") # expected 6, but get 5 incorrectly
print(f"int {B.static}") # get 6 correctly
A.static = 7
print(f"int {A.static}") # get 7 correctly
print(f"int {B.static}") # get unchanged 6
基于refdatatypes库的解决方案:
from refdatatypes.refint import RefInt
class AAA:
static = RefInt(1)
class BBB(AAA):
pass
print(f"refint {AAA.static.value}") # get 1 correctly
print(f"refint {BBB.static.value}") # get 1 correctly
AAA.static.value = 5
print(f"refint {AAA.static.value}") # get 5 correctly
print(f"refint {BBB.static.value}") # get 5 correctly
BBB.static.value = 6
print(f"refint {AAA.static.value}") # get 6 correctly
print(f"refint {BBB.static.value}") # get 6 correctly
AAA.static.value = 7
print(f"refint {AAA.static.value}") # get 7 correctly
print(f"refint {BBB.static.value}") # get 7 correctly
用这种方式,静态变量是在用户定义的类出现时创建的,
class Student:
the correct way of static declaration
i = 10
incorrect
self.i = 10
您还可以向类动态添加类变量
>>> class X:
... pass
...
>>> X.bar = 0
>>> x = X()
>>> x.bar
0
>>> x.foo
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: X instance has no attribute 'foo'
>>> X.foo = 1
>>> x.foo
1
类实例可以更改类变量
class X:
l = []
def __init__(self):
self.l.append(1)
print X().l
print X().l
>python test.py
[1]
[1, 1]
在类定义中声明但不在方法中声明的变量是类或静态变量:
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
正如@millerdev所指出的,这会创建一个类级别i变量,但这与任何实例级别i变量都不同,因此您可以
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
这与C++和Java不同,但与C#没有太大区别,在C#中,不能使用对实例的引用来访问静态成员。
看看Python教程对类和类对象的主题有什么看法。
@Steve Johnson已经回答了静态方法的问题,也在Python库参考中的“内置函数”中进行了说明。
class C:
@staticmethod
def f(arg1, arg2, ...): ...
@beidy推荐classmethods而不是staticmethod,因为该方法随后会接收类类型作为第一个参数。
我发现最好的方法是使用另一个类。您可以创建一个对象,然后将其用于其他对象。
class staticFlag:
def __init__(self):
self.__success = False
def isSuccess(self):
return self.__success
def succeed(self):
self.__success = True
class tryIt:
def __init__(self, staticFlag):
self.isSuccess = staticFlag.isSuccess
self.succeed = staticFlag.succeed
tryArr = []
flag = staticFlag()
for i in range(10):
tryArr.append(tryIt(flag))
if i == 5:
tryArr[i].succeed()
print tryArr[i].isSuccess()
通过上面的示例,我创建了一个名为staticFlag的类。
此类应显示静态变量__success(私有静态变量)。
tryIt类表示我们需要使用的常规类。
现在我为一个标志(staticFlag)创建了一个对象。此标志将作为对所有常规对象的引用发送。
所有这些对象都被添加到列表tryArr中。
此脚本结果:
False
False
False
False
False
True
True
True
True
True