gpt4 book ai didi

python - Python 中的类变量和继承

转载 作者:太空宇宙 更新时间:2023-11-04 05:47:39 26 4
gpt4 key购买 nike

我希望能够定义一个存在但不在子类或实例之间共享的类变量(以某种方式在基类中)。我最初尝试的是以下内容:

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()

我们对类级属性使用 weakref 以确保子类可以在父类(super class)仍在范围内时正确地进行垃圾回收。

我们可以测试它是否有效:

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

不过,我会建议摆脱子类功能,只确保实例单独的值,然后将状态表示为 Stateinstances 而不是子类(除非你有一个很好的理由不这样做,完全有可能):

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com