我希望能够定义一个存在的类变量(以某种方式在基类中),但不能在子类或实例之间共享。我最初尝试的操作如下:
from __future__ import print_function # For lambda print()
class CallList(list):
def __call__(self, *args, **kwargs):
for f in self:
f(*args, **kwargs)
class State:
on_enter = CallList()
def enter(self):
self.on_enter()
class Opening(State): pass
class Closing(State): pass
Opening.on_enter.append(lambda: print('Opening state entered'))
Closing.on_enter.append(lambda: print('Closing state entered'))
但是子类和子类实例的行为是引用基类的类变量,这给了我以下内容:
opening = Opening()
closing = Closing()
opening.enter()
# Actual output: Opening state entered
# Closing state entered
# Desired output: Opening state entered
opening.on_enter.append(lambda: print('Additional instance callback'))
opening.enter()
# Actual output: Opening state entered
# Closing state entered
# Additional instance callback
# Desired output: Opening state entered
# Additional instance callback
closing.enter()
# Actual output: Opening state entered
# Closing state entered
# Additional instance callback
# Desired output: Closing state entered
我知道为什么会这样(我原本期望与其他语言不同的是其他语言,但这很好)。
可以修改基类(而不是子类)以使每个子类具有各自的类变量副本,并且可以为子类的实例获取其类变量的副本,然后可以对其进行独立修改也没有分享?
最佳答案
首先,从对象继承开始使用new-style classes:
class State(object):
on_enter = CallList()
def enter(self):
self.on_enter()
旧式的课程太旧了,我在这里提出的建议是行不通的。
您的特定问题可以使用descriptors解决。正如您在文档中所看到的,描述符使我们能够覆盖特定属性(即它们所应用的属性)的属性访问。从类中读取属性时,这甚至是可能的。
import weakref
class CallListDescriptor(object):
def __init__(self):
self._class_level_values = weakref.WeakKeyDictionary()
def __get__(self, instance, type):
if instance is None:
# class-level access
try:
return self._class_level_values[type]
except KeyError:
default = CallList()
self._class_level_values[type] = default
return default
# instance-level access
return instance._call_lists.setdefault(self, CallList())
class State(object):
def __init__(self):
# for the instance-level values
self._call_lists = {}
on_enter = CallListDescriptor()
我们将弱引用用于类级别的属性,以确保子类可以在超类仍在作用域内时正确地收集垃圾。
我们可以测试它是否有效:
class SubState(State):
pass
class OtherSubState(State):
pass
assert State.on_enter is State.on_enter
assert State.on_enter is not SubState.on_enter
assert State.on_enter is not OtherSubState.on_enter
assert SubState.on_enter is SubState.on_enter
instance = SubState()
assert instance.on_enter is not SubState.on_enter
但是,我建议摆脱子类功能,仅确保实例具有单独的值,然后将状态表示为
State
的实例而不是子类(除非您有充分的理由不这样做,否则可能是完美的):class CallListDescriptor(object):
def __get__(self, instance, type):
if instance is None:
return self
return instance._call_lists.setdefault(self, CallList())
class State(object):
def __init__(self):
# for the instance-level values
self._call_lists = {}
关于python - Python中的类变量和继承,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31559203/