Answers:
在类定义中声明但在方法内部声明的变量是类或静态变量:
>>> 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的优势,我还是有些模糊。如果您也是,那可能没关系。
const.py
与PI = 3.14
你随处导入。from const import PI
i = 3
是不是一个静态变量,它是一个类属性,因为它是从一个实例级属性不同的i
它并没有表现得像其他语言的静态变量。请在下面查看millerdev的答案,Yann的答案以及我的答案。
i
即使我创建了数百个此类的实例,(静态变量)的一个副本也将在内存中?
@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
class Test(object):
,_i = 3
,@property
,def i(self)
,return type(self)._i
,@i.setter
,def i(self,val):
,type(self)._i = val
。现在你可以做x = Test()
,x.i = 12
,assert x.i == Test.i
。
正如其他答案所指出的,使用内置装饰器可以轻松实现静态和类方法:
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
会导致错误,否则不要尝试执行以下操作。
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
Test
(在使用它实例化实例之前)都视为在元编程领域中?例如,您通过执行更改类行为Test.i = 0
(在这里只是完全破坏了属性对象)。我猜想“属性机制”仅在类实例的属性访问中起作用(除非您可能使用元类作为中间层来更改基本行为)。顺便说一句,请完成此答案:-)
您还可以随时将类变量添加到类中
>>> 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 myObj(object):
def myMethod(cls)
...
myMethod = classmethod(myMethod)
或使用装饰器
class myObj(object):
@classmethod
def myMethod(cls)
对于静态属性..它时候您查找一些python定义..变量可以随时更改。有两种类型,它们是可变的和不可变的。此外,还有类属性和实例属性。从Java和C ++的意义上说,没有什么比静态属性更像
如果与类没有任何关系,为什么要使用pythonic意义上的静态方法!如果您是我,则可以使用classmethod或独立于类定义方法。
关于静态属性和实例属性的一件事要特别注意,如下面的示例所示:
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中的静态方法称为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
@staticmethod
; @classmethod
(显然)用于类方法(主要用于用作备用构造函数,但在某些情况下可以用作静态方法,恰好接收对其调用的类的引用)。
当在任何成员方法之外定义某个成员变量时,该变量可以是静态的也可以是非静态的,具体取决于变量的表示方式。
例如:
#!/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
可能有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
您还可以使用元类将类强制为静态。
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。
__new__
其父级的...
关于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
在不与特定实例关联的意义上说它是静态的,但该值仍取决于实例的(类)。
关于此答案,对于常量静态变量,可以使用描述符。这是一个例子:
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
@property
,与使用描述符相同,但是代码少得多。
绝对可以,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"
是的,绝对可以在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!!
我发现最好的方法是使用另一个类。您可以创建一个对象,然后在其他对象上使用它。
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
对于使用带有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
hasattr(SomeClass, 'x')
是False
。我怀疑这是否是任何人所说的静态变量。
some_var
不可变的,并且是静态定义的,不是吗?外部获取方法的访问与变量是否为静态有什么关系?我现在有很多问题。希望在有空的时候听到一些答案。
some_var
以上根本不是全班同学。在Python中,可以从类外部访问所有类成员。
nonlocal
keywoard“颠簸”的变量的作用域。类主体定义的范围独立于它在自身中发现的范围nonlocal some_var
,即您说的只是创建对另一个命名对象的非本地名称引用(在类定义范围内为NOT)。因此,它不属于类定义,因为它不在类主体范围内。
所以这可能是一个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返回的是一个对象……必须已被实例化……会产生类似静态的行为。
您可以使用列表或字典来获得实例之间的“静态行为”。
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
例如,如果您尝试共享静态变量,以便在其他实例之间增加静态变量,则类似此脚本的代码可以正常工作:
# -*- 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)
@classmethod
优于@staticmethod
AFAIK 的优点是,即使方法是子类,也总是获得调用该方法的类的名称。静态方法缺少此信息,因此,例如,它不能调用重写的方法。