You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python报错'tuple' object has no attribute 'x'原因与解决

错误运行截图

问题现象

运行求解三维空间两线段最短距离的Python代码时,mid(a, b)函数抛出'tuple' object has no attribute 'x'错误,无法访问入参a、b的x、y、z属性。自定义point类中x、y、z均为公开属性,但传入mid的参数被解释器识别为tuple类型,连续触发3次同类错误。

错误根因

报错是传参错误导致的,和point类的属性定义无关:

  • 在my_sol函数构造next列表的第一行,错误写为mid((p, q), q),其中(p, q)是将两个point对象打包成的元组,不是point实例,传入mid函数后尝试访问元组的x属性,自然触发报错。
  • 对比同函数其余3个next元素的计算逻辑、以及direction函数中的同场景写法,L1线段右侧中点的正确传参应该是mid(mid(p, q), q),多余的一层括号把两个点包成了元组,是触发错误的直接原因。

补充:point类定义时类层级写的x=0/y=0/z=0属于冗余类属性,实例初始化时会被__init__里的实例属性覆盖,不影响功能运行,可以删除。

修复方案

将my_sol函数中出错的那行代码的多余括号删除即可,修正后的关键代码段:

def my_sol(p, q, r, s, prev_l, flag):

    ep = 0.0001
    # end condition
    next = []
    # 修正前:mid((p, q), q) 多了一层括号把p、q包成元组
    next.append(my_length(mid(mid(p, q), q), mid(r, s)))
    next.append(my_length(mid(p, mid(p, q)), mid(r, s)))
    next.append(my_length(mid(p, q), mid(r, mid(r, s))))
    next.append(my_length(mid(p, q), mid(mid(r, s), s)))
    # 其余逻辑保持不变

修正后完整可运行代码:

import math

points = []


class point:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

    def printInfo(self):
        print(f"x={self.x} | y={self.y} | z={self.z}")


def my_length(a, b):
    length = math.sqrt(
        math.pow(a.x - b.x, 2) + math.pow(a.y - b.y, 2) + math.pow(a.z - b.z, 2)
    )
    return length


def mid(a, b):
    x1 = a.x * 0.5 + b.x * 0.5
    y1 = a.y * 0.5 + b.y * 0.5
    z1 = a.z * 0.5 + b.z * 0.5
    return point(x1, y1, z1)


def my_input():

    global points

    for i in range(4):
        x, y, z = map(int, input().split())
        points.append(point(x, y, z))
    return


def direction(p, q, r, s, flag):
    if flag == "L1":
        len_1 = my_length(mid(p, mid(p, q)), mid(r, s))
        len_2 = my_length(mid(mid(p, q), q), mid(r, s))
        if len_1 > len_2:
            return "Right"
        elif len_1 < len_2:
            return "Left"
        else:
            return "change"
    elif flag == "L2":
        len_1 = my_length(mid(p, q), mid(r, mid(r, s)))
        len_2 = my_length(mid(p, q), mid(mid(r, s), s))
        if len_1 > len_2:
            return "Right"
        elif len_1 < len_2:
            return "Left"
        else:
            return "change"


def my_sol(p, q, r, s, prev_l, flag):

    ep = 0.0001
    next = []
    next.append(my_length(mid(mid(p, q), q), mid(r, s)))
    next.append(my_length(mid(p, mid(p, q)), mid(r, s)))
    next.append(my_length(mid(p, q), mid(r, mid(r, s))))
    next.append(my_length(mid(p, q), mid(mid(r, s), s)))

    if abs(min(next) - prev_l) < 0.05:
        print(my_length(mid(p, q), mid(r, s)))
        return my_length(mid(p, q), mid(r, s))

    if flag == "L1":
        if direction(p, q, r, s, flag) == "Right":
            my_sol(mid(p, q), q, r, s, next[0], "L1")
        elif direction(p, q, r, s, flag) == "Left":
            my_sol(p, mid(p, q), r, s, next[1], "L1")
        elif direction(p, q, r, s, flag) == "change":
            my_sol(p, q, r, s, my_length(mid(p, q), mid(r, s)), "L2")
    else:
        if direction(p, q, r, s, flag) == "Right":
            my_sol(p, q, r, mid(r, s), next[2], "L2")
        elif direction(p, q, r, s, flag) == "Left":
            my_sol(p, q, mid(r, s), s, next[3], "L2")
        elif direction(p, q, r, s, flag) == "change":
            my_sol(p, q, r, s, my_length(mid(p, q), mid(r, s)), "L2")


if __name__ == "__main__":
    my_input()
    a, b, c, d = points[0], points[1], points[2], points[3]
    my_sol(a, b, c, d, 0, "L1")

内容的提问来源于stack exchange,提问作者차현대

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:15:41