获取静态变量值

我试图创建一个静态变量,通过不同的类访问,赋值给它,并在需要时获取这个值。 为了实现这一目的,我确实使用了这种方式,这导致我包含一个属性如下:

class GetPartition(Partition):
    _i = 100
    def __init__(self):
        super(Partition,self).__init__("get")
    def get_i(self):
        return type(self)._i
    def set_i(self,val):
        type(self)._i = val
    i = property(get_i, set_i)

这是类Partition如果需要:

class Partition(BaseCommand):
    def __init__(self,type):
        super(Partition,self).__init__("databaseTest")
        self.type = type

因此,值分配给当i从另一个类,我喜欢直接分配给它:

GetPartition.i = 5

并且在打印GetPartition.i时,在这个类中它给了我5 ,但是当试图从另一个类获得这个值时:

partitionNum = GetPartition()
print(partitionNum.i) # 100
print(partitionNum.get_i()) # 100
print(GetPartition.i) # <property object at 0x12A938D0>
print(GetPartition._i) # 100

正如我在我的评论中解释的那样,当您通过以下方式将5分配给i时,问题就出现了:

GetPartition.i = 5

用这行代码,你覆盖了属性 ,并“绕过”属性设置器。 我的意思是:当您从类中调用属性名称时,属性设置器不会被调用; 它只在你从一个类实例中调用它的属性名称时被调用。

由于它已被覆盖,该属性不再存在,并且所有对i属性的引用(无论是来自类实例还是来自类本身)都是不同的。 他们将不再检索相同的对象,而是检索不同的对象。

您可以通过执行此操作来确认此问题:

gp = GetPartition()
print(GetPartition.i) # the property is returned
GetPartition.i = 5 # here the property is overwritten
print(GetPartition.i) # 5 ; the property is gone
print(gp.i) # 5 because gp instance doesn't have its own i
gp.i = 2 # now gp does have its own i
print(gp.i) # 2
print(GetPartition.i) # 5 ; i is not synced

正如我上面所说的, property getter和setter(以及一般的描述符)只能用于GetPartition实例,而不是类本身。 他们可能会被迫通过创建一个类类metaclass(这是一个类的类)为你的类工作; 这被许多人认为是“深黑魔法”,如果你能避免这种情况,我不建议你走这条路。

我相信下面的例子可能是实现你想要的行为的最简单的方法。 这种方法放弃使用属性,而是直接重写属性getter和setter方法:

class Example():
    i = 1 # this is a "static variable"
    j = 3 # this is a regular class attribute
    #designate which of the class attributes are "static"
    statics = {'i'}
    def __getattribute__(self, attr):
        '''Overrides default attribute retrieval behavior.'''
        if attr in Example.statics:
            #use class version if attr is a static var
            return getattr(Example, attr)
        else:
            #default behavior if attr is not static var
            return super().__getattribute__(attr)
    def __setattr__(self, attr, value):
        '''Overrides default attribute setting behavior.'''
        if attr in Example.statics:
            #use class version if attr is a static var
            setattr(Example, attr, value)
        else:
            #default behavior if attr is not static var
            super().__setattr__(attr, value)

#testing
if __name__ == '__main__':
    print("nnBEGIN TESTINGnn")

    e = Example()
    #confirm instance and class versions of i are the same
    test = "assert e.i is Example.i"
    exec(test)
    print(test)

    e.i = 5
    #confirm they remain the same after instance change
    test = "assert e.i is Example.i"
    exec(test)
    print(test)

    Example.i = 100
    #confirm they remain the same after class change
    test = "assert e.i is Example.i"
    exec(test)
    print(test)

    e.j = 12
    #confirm both versions of j are distinct
    test = "assert e.j is not Example.j"
    exec(test)
    print(test)

    print("nnTESTING COMPLETEnn")

如果你对__getattribute____setattr__不熟悉,我应该让你知道,覆盖它们通常是非常危险的,并且会导致很大的问题(尤其是__getattribute__ )。 你会发现许多人只是说:“不要这样做;重新思考你的问题,找到另一种解决方案”。 正确覆盖需要深入理解各种python主题。

我没有声称有这个深刻的理解(虽然我认为我有一个很好的理解),所以我不能100%确定我的覆盖如上所述不会导致你的其他问题。 我相信它们很健全,但要注意Python的这些特殊角落可能会非常棘手。

链接地址: http://www.djcxy.com/p/13811.html

上一篇: Get static variable value

下一篇: How is heap and stack memories managed, implemented, allocated?