gpt4 book ai didi

python - Python中的描述符类设计(带继承)

转载 作者:行者123 更新时间:2023-12-01 05:23:53 25 4
gpt4 key购买 nike

我正在尝试设计一个描述符类,我可以通过其他类使用它,该类是一个类的子类,而另一个类是一个类的子类。

class MyDescriptorClass(object):
def __init__(self, owner, name, activates = 0):
self.value = None
self.name = name
self.owner = owner
self.activates = 0
self.connects = []

def __set__(self, obj, val):
self.set(val)
def __get__(self, instance, owner):
return self.value

def set(self, value):
if self.value == value:
return 0
self.value = value
if self.activates:
self.owner.evaluate()

def connect(self, inputs):
if not isinstance(inputs, list):
inputs = list(inputs)
for input in inputs:
self.connects.append(input)

class ParentClass(object):
def __init__(self, name):
self.states = {}
self.name = name
self.A = MyDescriptorClass(self, name, activates = 1)
self.B = MyDescriptorClass(self, name, activates = 1)
self.states.setDefault('A', self.A)
self.states.setDefault('B', self.B)

class ChildClass1(ParentClass):
def __init__(self, name)
super(ChildClass1, self).__init__(name)
self.ans = None
def evaluate(self):
self.ans = self.A.value + self.B.value

class ChildClass2(ParentClass):
def __init__(self, name)
super(ChildClass1, self).__init__(name)
self.ans = None
def evaluate(self):
self.ans = self.A.value * self.B.value

self.A = MyDescriptorClass() 将无法根据 python docs 工作

所以唯一的方法是我将 ParentClass 中的 A = MyDescriptorClass() 声明为

class ParentClass(object):
A = MyDescriptorClass() # here I am unable to pass the owner

由于我使用的是子类,super 调用会跳过这部分并直接从 __init__ 开始

有什么方法可以修改设计以便直接设置ChildClass1.A实例的值吗?

  c = ChildClass1("c1")
c.A = 10 # I directly want to set this value instead of using c.A.set(10)
c.B = 20
c.evaluate()
print c.ans # 30
c.B = 40
print c.ans # 50

最佳答案

尽量不要在描述符中放入特定于实例的信息。在实例属性中保留特定于实例的信息,并在描述符中保留特定于描述符的信息(如 activates ):

class MyDescriptorClass(object):
def __init__(self, activates = 0):
self.value = None
self.activates = activates
self.connects = []

def __set__(self, instance, val): # 1
if self.value == val:
return 0
self.value = val
if self.activates:
instance.evaluate()
def __get__(self, instance, instcls): # 1
return self.value
  1. 请注意 __set____get__方法通过 instance正在访问描述符。因此,你不需要存储owner在我的描述符中。 instance是个 owner .
<小时/>

鉴于下面评论中问题的澄清,以下是我将如何实现描述符。

class GateInput(object):
def __init__(self, index):
self.index = index # 4

def __get__(self, inst, instcls):
return inst.inputs[self.index].ans # 5

def __set__(self, inst, val):
if isinstance(val, (float, int)):
inst.inputs[self.index] = Constant(val)
else:
inst.inputs[self.index] = val


class Constant(object):
def __init__(self, val):
self.ans = val


class Gate(object):
A = GateInput(0) # 1
B = GateInput(1) # 1

def __init__(self, name):
self.name = name
self.inputs = [Constant(0), Constant(0)] # 2


class Adder(Gate):
@property
def ans(self):
result = 0
for gate in self.inputs:
result += gate.ans # 3
return result


class Multiplier(Gate):
@property
def ans(self):
result = 1
for gate in self.inputs:
result *= gate.ans
return result

b = Multiplier('b1')
b.A = 2
b.B = 3
print(b.A)
# 2
print(b.ans)
# 6

c = Adder('c1')
c.A = 10
print(c.ans)
# 10

# This connects output of b to an input of c
c.B = b
print(c.ans)
# 16
  1. 描述符必须定义为类属性,而不是实例属性。由于描述符被所有实例访问,您可能不希望描述符仅仅因为一个而改变正在创建实例。因此,不要实例化__init__中的描述符.
  2. Gate 的每个实例都有一个输入列表。项目 self.inputs是 Constant 或 Gate 的实例。
  3. 这里我们看到了 Constant 类的用途。对于每个gate , gate.ans需要返回一个值。
  4. 索引记录了inst.input中的哪一项GateInput是连接到。
  5. inst 是 Gate 的一个实例。例如,c.A导致Python调用GateInput.__get__(self, c, type(c)) 。因此,instc在这里。

关于python - Python中的描述符类设计(带继承),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21780529/

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