TypeError求助:float()参数应为字符串/实数而非Value对象
问题解决:TypeError: float() argument must be a string or a real number, not 'Value'
执行draw_dot(d)时触发如下错误:
TypeError: float() argument must be a string or a real number, not 'Value'
错误根源
代码里有三处关键问题导致了这个错误:
__mul__方法参数顺序错误:创建乘法结果的Value对象时,把运算符'*'误传给了_children参数,导致节点的_prev属性变成字符串而非子节点集合,后续遍历逻辑完全混乱。trace函数子节点错误包装:v._prev本身就是Value对象的集合,不需要用map(Value, v._prev)重新包装,这会把原Value对象当作新Value的data值,最终导致n.data变成Value类型而非数值。draw_dot函数缩进错误:return dot写在了边遍历循环的内部,导致函数提前返回,图形未构建完成。
修复后的完整代码
class Value: def __init__(self, data, _children=(), _op='', label=''): self.data = data self._prev = set(_children) self._op = _op self.label = label # REPR allows for nicer looking expression in python def __repr__(self): return f"Value(data={self.data})" def __add__(self, other): out = Value(self.data + other.data, (self, other), '+') return out def __mul__(self, other): # 修复:正确传递_children和_op参数 out = Value(self.data * other.data, (self, other), '*') return out a = Value(2.0, label='a') b = Value(-3.0, label='b') c = Value(10.0, label='c') e = a * b; e.label='e' # a * b + c d = e + c; d.label='d' f = Value(-2.0, label='f') L = d * f !pip install graphviz import graphviz from graphviz import Digraph def trace(root): # builds a set of all nodes and edges in a graph nodes, edges = set(), set() def build(v): if v not in nodes: nodes.add(v) # 修复:直接遍历v._prev里的子节点,不需要重新包装成Value for child in v._prev: edges.add((child, v)) build(child) build(root) return nodes, edges def draw_dot(root): dot = Digraph(format='svg', graph_attr={'rankdir': 'LR'}) nodes, edges = trace(root) for n in nodes: uid = str(id(n)) # for any value in the graph create a record (rectanglualr node for it) dot.node(name=uid, label="{data %.4f}" % float(n.data), shape='record') if n._op: # If this value is a result of some operation, create a node for it dot.node(name=uid + n._op, label=n._op) # and connect this node to it dot.edge(uid + n._op, uid) for n1, n2 in edges: # connect n1 to the op node of n2 dot.edge(str(id(n1)), str(id(n2)) + n2._op) # 修复:把return移到循环外面,确保图形构建完成后再返回 return dot draw_dot(d)
内容的提问来源于stack exchange,提问作者Leviathan
相关产品推荐
相关产品推荐

