我尝试创建一个静态变量,通过不同的类访问,为其赋值,并在需要时获取此值。我确实使用this way来实现这一目标,这导致我将以下属性包括在内:
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
答案 0 :(得分:1)
正如我在评论中所解释的那样,当您通过以下方式将{5}分配给i
时会出现问题:
GetPartition.i = 5
使用这行代码,您覆盖属性,&#34;绕过&#34; 属性设置器。我的意思是:当您从类中调用其属性名称时,属性设置器不会被称为;只有在从类实例调用其属性名称时才会调用它。
由于它已被覆盖,因此该属性不再存在,并且对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
的实例,而不适用于类本身。他们可以通过为您的类创建一个元类(类是类)来强制使用类本身;这被认为是&#34;深黑魔法&#34;许多人,如果你能避免,我不建议你去那条路。
我相信以下示例可能是实现您想要的行为的最简单方法。这种方法放弃了使用属性,而有利于直接覆盖属性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("\n\nBEGIN TESTING\n\n")
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("\n\nTESTING COMPLETE\n\n")
如果您不熟悉__getattribute__
和__setattr__
,我应该告诉您,覆盖它们通常非常危险并且可能会导致很大问题(尤其是__getattribute__
)。你会发现很多人只是说“不要这样做”;重新考虑你的问题,找到另一种解决方案&#34;。正确执行覆盖需要深入了解各种python主题。
我没有声称有这种深刻的理解(虽然我认为我有一个很好的理解),所以我不能100%确定我上面给出的覆盖不会导致你的其他问题。我相信它们是合理的,但请注意,python的这些特殊角落可能非常棘手。