问题:Python中可以使用静态类变量吗?
Python中是否可以有静态类变量或方法?为此需要什么语法?
回答 0
在类定义中声明但在方法内部声明的变量是类或静态变量:
>>> 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 Library Reference中的“内置函数”下。
class C:
@staticmethod
def f(arg1, arg2, ...): ...
@beidy建议使用classmethod而不是staticmethod,因为该方法随后将类类型作为第一个参数,但是对于这种方法相对于staticmethod的优势,我还是有些模糊。如果您也是,那可能没关系。
回答 1
@Blair Conrad说,在类定义中声明但在方法内部声明的静态变量是类或“静态”变量:
>>> class Test(object):
... i = 3
...
>>> Test.i
3
这里有一些陷阱。从上面的示例继续进行:
>>> t = Test()
>>> t.i # "static" variable accessed via instance
3
>>> t.i = 5 # but if we assign to the instance ...
>>> Test.i # we have not changed the "static" variable
3
>>> t.i # we have overwritten Test.i on t by creating a new attribute t.i
5
>>> Test.i = 6 # to change the "static" variable we do it by assigning to the class
>>> t.i
5
>>> Test.i
6
>>> u = Test()
>>> u.i
6 # changes to t do not affect new instances of Test
# Namespaces are one honking great idea -- let's do more of those!
>>> Test.__dict__
{'i': 6, ...}
>>> t.__dict__
{'i': 5}
>>> u.__dict__
{}
请注意,直接t.i
将属性i
设置为时,实例变量如何与“静态”类变量不同步t
。这是因为i
已在t
命名空间中重新绑定,这与Test
命名空间不同。如果要更改“静态”变量的值,则必须在其最初定义的范围(或对象)内进行更改。我将“ static”用引号引起来,因为Python实际上没有C ++和Java所具有的静态变量。
尽管它没有对静态变量或方法进行任何具体说明,但是Python教程提供了有关类和类对象的一些相关信息。
@Steve Johnson还回答了有关静态方法的问题,该方法也记录在Python库参考的“内置函数”下。
class Test(object):
@staticmethod
def f(arg1, arg2, ...):
...
@beid还提到了classmethod,它与staticmethod相似。类方法的第一个参数是类对象。例:
class Test(object):
i = 3 # class (or static) variable
@classmethod
def g(cls, arg):
# here we can use 'cls' instead of the class name (Test)
if arg > cls.i:
cls.i = arg # would be the same as Test.i = arg1
回答 2
静态和类方法
正如其他答案所指出的,使用内置装饰器可以轻松实现静态和类方法:
class Test(object):
# regular instance method:
def MyMethod(self):
pass
# class method:
@classmethod
def MyClassMethod(klass):
pass
# static method:
@staticmethod
def MyStaticMethod():
pass
通常,第一个参数to MyMethod()
绑定到类实例对象。与此相反,第一个参数MyClassMethod()
被绑定到类对象本身(例如,在这种情况下,Test
)。对于MyStaticMethod()
,没有参数绑定,并且完全没有参数是可选的。
“静态变量”
然而,实现“静态变量”(无论如何,可变静态变量,如果这不是一个矛盾的话……)并不是那么简单。正如millerdev 在回答中指出的那样,问题在于Python的类属性并不是真正的“静态变量”。考虑:
class Test(object):
i = 3 # This is a class attribute
x = Test()
x.i = 12 # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i # ERROR
assert Test.i == 3 # Test.i was not affected
assert x.i == 12 # x.i is a different object than Test.i
这是因为该行x.i = 12
向其中添加了新的实例属性i
,x
而不是更改Test
class i
属性的值。
可以通过将class属性变成属性来实现部分预期的静态变量行为,即,多个实例之间的属性同步(但不与类本身同步;请参见下面的“陷阱”):
class Test(object):
_i = 3
@property
def i(self):
return type(self)._i
@i.setter
def i(self,val):
type(self)._i = val
## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##
class Test(object):
_i = 3
def get_i(self):
return type(self)._i
def set_i(self,val):
type(self)._i = val
i = property(get_i, set_i)
现在您可以执行以下操作:
x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i # no error
assert x2.i == 50 # the property is synced
现在,静态变量将在所有类实例之间保持同步。
(注意:也就是说,除非类实例决定定义其自己的版本_i
!但是,如果有人决定执行该操作,那么他们应得的是什么,不是吗???)
请注意,从技术上讲,i
它仍然根本不是“静态变量”。它是property
,这是一种特殊类型的描述符。但是,该property
行为现在等同于跨所有类实例同步的(可变)静态变量。
不变的“静态变量”
对于不可变的静态变量行为,只需省略property
setter:
class Test(object):
_i = 3
@property
def i(self):
return type(self)._i
## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting i) ##
class Test(object):
_i = 3
def get_i(self):
return type(self)._i
i = property(get_i)
现在尝试设置实例i
属性将返回AttributeError
:
x = Test()
assert x.i == 3 # success
x.i = 12 # ERROR
要意识到的一个陷阱
请注意,上述方法只能用工作实例类的-他们会不工作使用类本身时。因此,例如:
x = Test()
assert x.i == Test.i # ERROR
# x.i and Test.i are two different objects:
type(Test.i) # class 'property'
type(x.i) # class 'int'
行assert Test.i == x.i
产生一个错误,这是因为i
的属性Test
和x
是两个不同的对象。
许多人会发现这令人惊讶。但是,事实并非如此。如果我们返回并检查Test
类定义(第二个版本),请注意以下这一行:
i = property(get_i)
显然,部件i
的Test
必须是一个property
对象,该对象是对象的从返回的类型property
的功能。
如果您发现上述混淆,您很可能仍会从其他语言(例如Java或c ++)的角度考虑它。您应该研究property
对象,有关返回Python属性的顺序,描述符协议和方法解析顺序(MRO)。
我在下面提出了上述“陷阱”的解决方案;但是,我建议-努力-除非您完全理解为什么assert Test.i = x.i
会导致错误,否则不要尝试执行以下操作。
REAL,ACTUAL静态变量-Test.i == x.i
我仅在下面提供(Python 3)解决方案,仅供参考。我不赞成将其作为“好的解决方案”。我对是否真的有必要在Python中模拟其他语言的静态变量行为感到怀疑。但是,不管它是否真的有用,下面的内容应有助于进一步了解Python的工作方式。
更新:这种尝试确实非常糟糕;如果您坚持要做这样的事情(提示:请不要; Python是一种非常优雅的语言,并且不需要像其他语言那样勉强地表现出来),请改用Ethan Furman的答案中的代码。
使用元类模拟其他语言的静态变量行为
元类是类的类。Python中所有类的默认元类(即,我认为Python 2.3之后的“新样式”类)是type
。例如:
type(int) # class 'type'
type(str) # class 'type'
class Test(): pass
type(Test) # class 'type'
但是,您可以这样定义自己的元类:
class MyMeta(type): pass
并将其应用于您自己的类(仅适用于Python 3):
class MyClass(metaclass = MyMeta):
pass
type(MyClass) # class MyMeta
下面是我创建的元类,它试图模仿其他语言的“静态变量”行为。它基本上是通过将默认的getter,setter和deleter替换为版本来工作的,该版本检查以查看所请求的属性是否为“静态变量”。
“静态变量”的目录存储在StaticVarMeta.statics
属性中。最初尝试使用替代解决顺序解决所有属性请求。我将其称为“静态解决方案命令”或“ SRO”。这是通过在给定类(或其父类)的“静态变量”集中查找请求的属性来完成的。如果该属性未出现在“ SRO”中,则该类将回退到默认属性的“获取/设置/删除”行为(即“ MRO”)。
from functools import wraps
class StaticVarsMeta(type):
'''A metaclass for creating classes that emulate the "static variable" behavior
of other languages. I do not advise actually using this for anything!!!
Behavior is intended to be similar to classes that use __slots__. However, "normal"
attributes and __statics___ can coexist (unlike with __slots__).
Example usage:
class MyBaseClass(metaclass = StaticVarsMeta):
__statics__ = {'a','b','c'}
i = 0 # regular attribute
a = 1 # static var defined (optional)
class MyParentClass(MyBaseClass):
__statics__ = {'d','e','f'}
j = 2 # regular attribute
d, e, f = 3, 4, 5 # Static vars
a, b, c = 6, 7, 8 # Static vars (inherited from MyBaseClass, defined/re-defined here)
class MyChildClass(MyParentClass):
__statics__ = {'a','b','c'}
j = 2 # regular attribute (redefines j from MyParentClass)
d, e, f = 9, 10, 11 # Static vars (inherited from MyParentClass, redefined here)
a, b, c = 12, 13, 14 # Static vars (overriding previous definition in MyParentClass here)'''
statics = {}
def __new__(mcls, name, bases, namespace):
# Get the class object
cls = super().__new__(mcls, name, bases, namespace)
# Establish the "statics resolution order"
cls.__sro__ = tuple(c for c in cls.__mro__ if isinstance(c,mcls))
# Replace class getter, setter, and deleter for instance attributes
cls.__getattribute__ = StaticVarsMeta.__inst_getattribute__(cls, cls.__getattribute__)
cls.__setattr__ = StaticVarsMeta.__inst_setattr__(cls, cls.__setattr__)
cls.__delattr__ = StaticVarsMeta.__inst_delattr__(cls, cls.__delattr__)
# Store the list of static variables for the class object
# This list is permanent and cannot be changed, similar to __slots__
try:
mcls.statics[cls] = getattr(cls,'__statics__')
except AttributeError:
mcls.statics[cls] = namespace['__statics__'] = set() # No static vars provided
# Check and make sure the statics var names are strings
if any(not isinstance(static,str) for static in mcls.statics[cls]):
typ = dict(zip((not isinstance(static,str) for static in mcls.statics[cls]), map(type,mcls.statics[cls])))[True].__name__
raise TypeError('__statics__ items must be strings, not {0}'.format(typ))
# Move any previously existing, not overridden statics to the static var parent class(es)
if len(cls.__sro__) > 1:
for attr,value in namespace.items():
if attr not in StaticVarsMeta.statics[cls] and attr != ['__statics__']:
for c in cls.__sro__[1:]:
if attr in StaticVarsMeta.statics[c]:
setattr(c,attr,value)
delattr(cls,attr)
return cls
def __inst_getattribute__(self, orig_getattribute):
'''Replaces the class __getattribute__'''
@wraps(orig_getattribute)
def wrapper(self, attr):
if StaticVarsMeta.is_static(type(self),attr):
return StaticVarsMeta.__getstatic__(type(self),attr)
else:
return orig_getattribute(self, attr)
return wrapper
def __inst_setattr__(self, orig_setattribute):
'''Replaces the class __setattr__'''
@wraps(orig_setattribute)
def wrapper(self, attr, value):
if StaticVarsMeta.is_static(type(self),attr):
StaticVarsMeta.__setstatic__(type(self),attr, value)
else:
orig_setattribute(self, attr, value)
return wrapper
def __inst_delattr__(self, orig_delattribute):
'''Replaces the class __delattr__'''
@wraps(orig_delattribute)
def wrapper(self, attr):
if StaticVarsMeta.is_static(type(self),attr):
StaticVarsMeta.__delstatic__(type(self),attr)
else:
orig_delattribute(self, attr)
return wrapper
def __getstatic__(cls,attr):
'''Static variable getter'''
for c in cls.__sro__:
if attr in StaticVarsMeta.statics[c]:
try:
return getattr(c,attr)
except AttributeError:
pass
raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
def __setstatic__(cls,attr,value):
'''Static variable setter'''
for c in cls.__sro__:
if attr in StaticVarsMeta.statics[c]:
setattr(c,attr,value)
break
def __delstatic__(cls,attr):
'''Static variable deleter'''
for c in cls.__sro__:
if attr in StaticVarsMeta.statics[c]:
try:
delattr(c,attr)
break
except AttributeError:
pass
raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
def __delattr__(cls,attr):
'''Prevent __sro__ attribute from deletion'''
if attr == '__sro__':
raise AttributeError('readonly attribute')
super().__delattr__(attr)
def is_static(cls,attr):
'''Returns True if an attribute is a static variable of any class in the __sro__'''
if any(attr in StaticVarsMeta.statics[c] for c in cls.__sro__):
return True
return False
回答 3
您还可以随时将类变量添加到类中
>>> 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]
回答 4
就个人而言,每当我需要静态方法时,我都会使用类方法。主要是因为我将类作为参数。
class myObj(object):
def myMethod(cls)
...
myMethod = classmethod(myMethod)
或使用装饰器
class myObj(object):
@classmethod
def myMethod(cls)
对于静态属性..它时候您查找一些python定义..变量可以随时更改。有两种类型,它们是可变的和不可变的。此外,还有类属性和实例属性。从Java和C ++的意义上说,没有什么比静态属性更像
如果与类没有任何关系,为什么要使用pythonic意义上的静态方法!如果您是我,则可以使用classmethod或独立于类定义方法。
回答 5
关于静态属性和实例属性的一件事要特别注意,如下面的示例所示:
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类中声明的每个属性在内存中始终具有一个静态插槽。
回答 6
python中的静态方法称为classmethod。看下面的代码
class MyClass:
def myInstanceMethod(self):
print 'output from an instance method'
@classmethod
def myStaticMethod(cls):
print 'output from a static method'
>>> MyClass.myInstanceMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method myInstanceMethod() must be called [...]
>>> MyClass.myStaticMethod()
output from a static method
注意,当我们调用方法myInstanceMethod时,我们得到一个错误。这是因为它要求在此类的实例上调用该方法。使用装饰器@classmethod将方法myStaticMethod设置为类方法。
只是为了一笑而过,我们可以通过传入类的实例来在类上调用myInstanceMethod,如下所示:
>>> MyClass.myInstanceMethod(MyClass())
output from an instance method
回答 7
当在任何成员方法之外定义某个成员变量时,该变量可以是静态的也可以是非静态的,具体取决于变量的表示方式。
- CLASSNAME.var是静态变量
- INSTANCENAME.var不是静态变量。
- 类中的self.var不是静态变量。
- 类成员函数内部的var未定义。
例如:
#!/usr/bin/python
class A:
var=1
def printvar(self):
print "self.var is %d" % self.var
print "A.var is %d" % A.var
a = A()
a.var = 2
a.printvar()
A.var = 3
a.printvar()
结果是
self.var is 2
A.var is 1
self.var is 2
A.var is 3
回答 8
可能有static
类变量,但可能不值得。
这是用Python 3编写的概念验证-如果任何确切的细节有误,则可以对代码进行调整以使其与您所表达的含义完全匹配static variable
:
class Static:
def __init__(self, value, doc=None):
self.deleted = False
self.value = value
self.__doc__ = doc
def __get__(self, inst, cls=None):
if self.deleted:
raise AttributeError('Attribute not set')
return self.value
def __set__(self, inst, value):
self.deleted = False
self.value = value
def __delete__(self, inst):
self.deleted = True
class StaticType(type):
def __delattr__(cls, name):
obj = cls.__dict__.get(name)
if isinstance(obj, Static):
obj.__delete__(name)
else:
super(StaticType, cls).__delattr__(name)
def __getattribute__(cls, *args):
obj = super(StaticType, cls).__getattribute__(*args)
if isinstance(obj, Static):
obj = obj.__get__(cls, cls.__class__)
return obj
def __setattr__(cls, name, val):
# check if object already exists
obj = cls.__dict__.get(name)
if isinstance(obj, Static):
obj.__set__(name, val)
else:
super(StaticType, cls).__setattr__(name, val)
并在使用中:
class MyStatic(metaclass=StaticType):
"""
Testing static vars
"""
a = Static(9)
b = Static(12)
c = 3
class YourStatic(MyStatic):
d = Static('woo hoo')
e = Static('doo wop')
和一些测试:
ms1 = MyStatic()
ms2 = MyStatic()
ms3 = MyStatic()
assert ms1.a == ms2.a == ms3.a == MyStatic.a
assert ms1.b == ms2.b == ms3.b == MyStatic.b
assert ms1.c == ms2.c == ms3.c == MyStatic.c
ms1.a = 77
assert ms1.a == ms2.a == ms3.a == MyStatic.a
ms2.b = 99
assert ms1.b == ms2.b == ms3.b == MyStatic.b
MyStatic.a = 101
assert ms1.a == ms2.a == ms3.a == MyStatic.a
MyStatic.b = 139
assert ms1.b == ms2.b == ms3.b == MyStatic.b
del MyStatic.b
for inst in (ms1, ms2, ms3):
try:
getattr(inst, 'b')
except AttributeError:
pass
else:
print('AttributeError not raised on %r' % attr)
ms1.c = 13
ms2.c = 17
ms3.c = 19
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19
MyStatic.c = 43
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19
ys1 = YourStatic()
ys2 = YourStatic()
ys3 = YourStatic()
MyStatic.b = 'burgler'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
assert ys1.d == ys2.d == ys3.d == YourStatic.d
assert ys1.e == ys2.e == ys3.e == YourStatic.e
ys1.a = 'blah'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
ys2.b = 'kelp'
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
ys1.d = 'fee'
assert ys1.d == ys2.d == ys3.d == YourStatic.d
ys2.e = 'fie'
assert ys1.e == ys2.e == ys3.e == YourStatic.e
MyStatic.a = 'aargh'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
回答 9
您还可以使用元类将类强制为静态。
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。
回答 10
关于Python属性查找的一个非常有趣的观点是,它可以用于创建“ 虚拟变量”:
class A(object):
label="Amazing"
def __init__(self,d):
self.data=d
def say(self):
print("%s %s!"%(self.label,self.data))
class B(A):
label="Bold" # overrides A.label
A(5).say() # Amazing 5!
B(3).say() # Bold 3!
通常,在创建它们之后,没有任何分配。请注意,使用查找是self
因为,尽管label
在不与特定实例关联的意义上说它是静态的,但该值仍取决于实例的(类)。
回答 11
关于此答案,对于常量静态变量,可以使用描述符。这是一个例子:
class ConstantAttribute(object):
'''You can initialize my value but not change it.'''
def __init__(self, value):
self.value = value
def __get__(self, obj, type=None):
return self.value
def __set__(self, obj, val):
pass
class Demo(object):
x = ConstantAttribute(10)
class SubDemo(Demo):
x = 10
demo = Demo()
subdemo = SubDemo()
# should not change
demo.x = 100
# should change
subdemo.x = 100
print "small demo", demo.x
print "small subdemo", subdemo.x
print "big demo", Demo.x
print "big subdemo", SubDemo.x
导致 …
small demo 10
small subdemo 100
big demo 10
big subdemo 10
如果您pass
不想静默地忽略设置值(以上),则总是可以引发异常。如果要查找C ++ Java样式静态类变量:
class StaticAttribute(object):
def __init__(self, value):
self.value = value
def __get__(self, obj, type=None):
return self.value
def __set__(self, obj, val):
self.value = val
回答 12
绝对可以,Python本身没有明确的静态数据成员,但是我们可以这样做
class A:
counter =0
def callme (self):
A.counter +=1
def getcount (self):
return self.counter
>>> x=A()
>>> y=A()
>>> print(x.getcount())
>>> print(y.getcount())
>>> x.callme()
>>> print(x.getcount())
>>> print(y.getcount())
输出
0
0
1
1
说明
here object (x) alone increment the counter variable
from 0 to 1 by not object y. But result it as "static counter"
回答 13
是的,绝对可以在python中编写静态变量和方法。
静态变量: 在类级别声明的变量称为静态变量,可以使用类名称直接访问。
>>> class A:
...my_var = "shagun"
>>> print(A.my_var)
shagun
实例变量:与某个类的实例相关并访问的变量是实例变量。
>>> a = A()
>>> a.my_var = "pruthi"
>>> print(A.my_var,a.my_var)
shagun pruthi
静态方法:与变量类似,可以使用Name类直接访问静态方法。无需创建实例。
但请记住,静态方法无法在python中调用非静态方法。
>>> class A:
... @staticmethod
... def my_static_method():
... print("Yippey!!")
...
>>> A.my_static_method()
Yippey!!
回答 14
为了避免任何潜在的混乱,我想对比静态变量和不可变对象。
一些原始对象类型(例如整数,浮点数,字符串和touples)在Python中是不可变的。这意味着给定名称引用的对象如果属于上述对象类型之一,则无法更改。可以将名称重新分配给其他对象,但是对象本身不能更改。
使变量为静态使此步骤更进一步,它不允许变量名指向除当前指向的对象之外的任何对象。(注意:这是一个通用的软件概念,并不特定于Python;有关在Python中实现静态功能的信息,请参见其他人的帖子)。
回答 15
我发现最好的方法是使用另一个类。您可以创建一个对象,然后在其他对象上使用它。
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
。
此类应显示静态var __success
(私有静态Var)。
tryIt
类代表我们需要使用的常规类。
现在,我为一个标志(staticFlag
)创建了一个对象。该标志将作为对所有常规对象的引用发送。
所有这些对象都将添加到列表中tryArr
。
该脚本结果:
False
False
False
False
False
True
True
True
True
True
回答 16
类工厂python3.6中的静态变量
对于使用带有python3.6及更高版本的类工厂的任何人,请使用nonlocal
关键字将其添加到正在创建的类的作用域/上下文中,如下所示:
>>> def SomeFactory(some_var=None):
... class SomeClass(object):
... nonlocal some_var
... def print():
... print(some_var)
... return SomeClass
...
>>> SomeFactory(some_var="hello world").print()
hello world
回答 17
所以这可能是一个hack,但是我一直在使用 eval(str)
python 3获取静态对象,这有点矛盾。
有一个Records.py文件,除了class
用静态方法定义的对象和保存一些参数的构造函数外,什么都没有。然后从另一个.py文件中,import Records
但我需要动态选择每个对象,然后根据要读取的数据类型按需实例化它。
因此object_name = 'RecordOne'
,我在哪里调用了类名,cur_type = eval(object_name)
然后对其进行了实例化。cur_inst = cur_type(args)
但是,在实例化之前,您可以从cur_type.getName()
例如静态类中调用静态方法,例如抽象基类的实现或目标是什么。但是在后端,它可能是在python中实例化的,并且不是真正的静态对象,因为eval返回的是一个对象……必须已被实例化……会产生类似静态的行为。
回答 18
您可以使用列表或字典来获得实例之间的“静态行为”。
class Fud:
class_vars = {'origin_open':False}
def __init__(self, origin = True):
self.origin = origin
self.opened = True
if origin:
self.class_vars['origin_open'] = True
def make_another_fud(self):
''' Generating another Fud() from the origin instance '''
return Fud(False)
def close(self):
self.opened = False
if self.origin:
self.class_vars['origin_open'] = False
fud1 = Fud()
fud2 = fud1.make_another_fud()
print (f"is this the original fud: {fud2.origin}")
print (f"is the original fud open: {fud2.class_vars['origin_open']}")
# is this the original fud: False
# is the original fud open: True
fud1.close()
print (f"is the original fud open: {fud2.class_vars['origin_open']}")
# is the original fud open: False
回答 19
例如,如果您尝试共享静态变量,以便在其他实例之间增加静态变量,则类似此脚本的代码可以正常工作:
# -*- coding: utf-8 -*-
class Worker:
id = 1
def __init__(self):
self.name = ''
self.document = ''
self.id = Worker.id
Worker.id += 1
def __str__(self):
return u"{}.- {} {}".format(self.id, self.name, self.document).encode('utf8')
class Workers:
def __init__(self):
self.list = []
def add(self, name, doc):
worker = Worker()
worker.name = name
worker.document = doc
self.list.append(worker)
if __name__ == "__main__":
workers = Workers()
for item in (('Fiona', '0009898'), ('Maria', '66328191'), ("Sandra", '2342184'), ('Elvira', '425872')):
workers.add(item[0], item[1])
for worker in workers.list:
print(worker)
print("next id: %i" % Worker.id)