如何在Python中创建类(即静态)变量或方法?
当前回答
类变量并允许子类化
假设你不是在寻找一个真正的静态变量,而是一个类似于蟒蛇的东西,它可以为同意的成年人做同样的工作,那么就使用一个类变量。这将为您提供一个所有实例都可以访问(和更新)的变量
注意:其他许多使用类变量的答案都会破坏子类化。应避免直接按名称引用类。
from contextlib import contextmanager
class Sheldon(object):
foo = 73
def __init__(self, n):
self.n = n
def times(self):
cls = self.__class__
return cls.foo * self.n
#self.foo * self.n would give the same result here but is less readable
# it will also create a local variable which will make it easier to break your code
def updatefoo(self):
cls = self.__class__
cls.foo *= self.n
#self.foo *= self.n will not work here
# assignment will try to create a instance variable foo
@classmethod
@contextmanager
def reset_after_test(cls):
originalfoo = cls.foo
yield
cls.foo = originalfoo
#if you don't do this then running a full test suite will fail
#updates to foo in one test will be kept for later tests
将为您提供与使用Sheldon.foo处理变量相同的功能,并将通过以下测试:
def test_times():
with Sheldon.reset_after_test():
s = Sheldon(2)
assert s.times() == 146
def test_update():
with Sheldon.reset_after_test():
s = Sheldon(2)
s.updatefoo()
assert Sheldon.foo == 146
def test_two_instances():
with Sheldon.reset_after_test():
s = Sheldon(2)
s3 = Sheldon(3)
assert s.times() == 146
assert s3.times() == 219
s3.updatefoo()
assert s.times() == 438
它还允许其他人简单地:
class Douglas(Sheldon):
foo = 42
这也将起作用:
def test_subclassing():
with Sheldon.reset_after_test(), Douglas.reset_after_test():
s = Sheldon(2)
d = Douglas(2)
assert d.times() == 84
assert s.times() == 146
d.updatefoo()
assert d.times() == 168 #Douglas.Foo was updated
assert s.times() == 146 #Seldon.Foo is still 73
def test_subclassing_reset():
with Sheldon.reset_after_test(), Douglas.reset_after_test():
s = Sheldon(2)
d = Douglas(2)
assert d.times() == 84 #Douglas.foo was reset after the last test
assert s.times() == 146 #and so was Sheldon.foo
有关创建课程时要注意的事项的最佳建议,请查看Raymond Hettinger的视频https://www.youtube.com/watch?v=HTLu2DFOdTg
其他回答
在类定义中声明但不在方法中声明的变量是类或静态变量:
>>> 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 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。
关于静态财产和实例财产,需要注意一件特殊的事情,如下例所示:
class my_cls:
my_prop = 0
#static property
print my_cls.my_prop #--> 0
#assign value to static property
my_cls.my_prop = 1
print my_cls.my_prop #--> 1
#access static property thru' instance
my_inst = my_cls()
print my_inst.my_prop #--> 1
#instance property is different from static property
#after being assigned a value
my_inst.my_prop = 2
print my_cls.my_prop #--> 1
print my_inst.my_prop #--> 2
这意味着在将值分配给实例属性之前,如果我们试图通过“实例”访问属性,则使用静态值。python类中声明的每个属性在内存中总是有一个静态槽。
为了避免任何潜在的混淆,我想对比静态变量和不可变对象。
一些基本对象类型,如整数、浮点数、字符串和元组,在Python中是不可变的。这意味着由给定名称引用的对象如果属于上述对象类型之一,则不能更改。可以将名称重新分配给不同的对象,但不能更改对象本身。
通过禁止变量名指向除当前指向的对象之外的任何对象,使变量成为静态变量更进一步。(注意:这是一个通用的软件概念,并不特定于Python;请参阅其他人的帖子,了解有关在Python中实现静态的信息)。
所以这可能是一个黑客,但我一直在使用eval(str)来获取一个静态对象,这有点矛盾,在python 3中。
有一个Records.py文件,除了用保存一些参数的静态方法和构造函数定义的类对象外,它什么都没有。然后从另一个.py文件导入Records,但我需要动态选择每个对象,然后根据读入的数据类型按需实例化它。
因此,在object_name=“RecordOne”或类名的情况下,我调用cur_type=eval(object_name),然后要实例化它,请执行cur_inst=cur_type(args)然而,在实例化之前,您可以从cur_type.getName()调用静态方法,例如,类似于抽象基类实现或任何目标。然而,在后端,它可能是在python中实例化的,并不是真正静态的,因为eval返回一个对象。。。。必须已实例化。。。。这会产生类似静态的行为。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录