元组

元组基本概念

元组(Tuple)是 Python 中的一种有序、不可变(immutable)的序列类型,用于存储一组元素。

  • “有序”意味着元组中的元素按添加顺序排列,可以通过索引访问。
  • “不可变”意味着元组创建后,其内部的元素不能被修改、删除或添加

用途

  • 用于存储固定的数据集合,例如日期(年、月、日)、RGB 颜色值、坐标点等。
  • 可以作为字典的键(因为元组是不可变的),而列表不能。
  • 元组操作通常比列表更高效,适合不需要修改的场景。

Python 元组是一系列逗号分隔的项目,括在括号中 ()。Python 元组中的项目不需要具有相同的数据类型。

以下是 Python 元组的一些示例:

tup1 = ("Rohan", "Physics", 21, 69.75)
tup2 = (1, 2, 3, 4, 5)
tup3 = ("a", "b", "c", "d")
tup4 = (25.50, True, -55, 1+2j)

空元组写成两个括号,不包含任何内容:

tup1 = ();

要编写包含单个值的元组,即使只有一个值,也必须包含一个逗号:

tup1 = (50,);

创建元组

使用小括号 () —— 最常见方式

t = (1, 2, 3, 4)
print(t)        # (1, 2, 3, 4)
print(type(t))  # <class 'tuple'>

特点:

  • 元素可以是任意类型(数字、字符串、布尔、列表、元组等)。
  • 推荐方式,最直观。

不加括号,直接用逗号分隔

t = 1, 2, 3, 4
print(t)        # (1, 2, 3, 4)
print(type(t))  # <class 'tuple'>

重点:Python 中,只要有逗号,就会生成元组。括号只是帮助我们更清晰地表示。

创建单元素元组

容易出错的地方

t1 = (5,)     # 正确,单元素元组
t2 = (5)      # 错误,这是 int 类型
t3 = 5,       # 正确,不加括号也行

原因:

  • Python 里 (5) 会被当作数学运算中的括号,结果就是整数 5
  • 只有加上逗号 (5,),才会被识别为元组。

创建空元组

t = ()
print(t)        # ()
print(type(t))  # <class 'tuple'>

通常用于初始化,后续再替换。

使用 tuple() 构造函数

可以把其他可迭代对象转换为元组:

# 列表转元组
t1 = tuple([1, 2, 3])
print(t1)  # (1, 2, 3)

# 字符串转元组
t2 = tuple("abc")
print(t2)  # ('a', 'b', 'c')

# range 转元组
t3 = tuple(range(5))
print(t3)  # (0, 1, 2, 3, 4)

# 字典转元组(只取 key)
t4 = tuple({"a":1, "b":2})
print(t4)  # ('a', 'b')

嵌套元组

元组中可以再包含元组(或其他对象):

t = (1, (2, 3), (4, 5, 6))
print(t)        # (1, (2, 3), (4, 5, 6))
print(t[1][0])  # 2

这在存储二维/多维数据时很常用,比如矩阵、坐标点集。

从函数返回多个值

函数可以“同时返回多个值”,其实就是返回一个元组:

def get_point():
    return 10, 20

point = get_point()
print(point)      # (10, 20)
x, y = get_point()
print(x, y)       # 10 20

这也是 Python 元组的常见应用场景

元组创建的注意点

  1. 小括号可省略,但建议保留,增加可读性。

  2. 单元素元组必须带逗号 (x,),否则不是元组。

  3. 不可变但可以包含可变对象

    t = (1, [2, 3])
    t[1][0] = 100
    print(t)  # (1, [100, 3])
    

    元组本身不可变,但内部可变对象的内容可以修改。

访问元组项目

元组(tuple)是有序不可变序列:每个元素在元组中都有唯一的位置(索引),但不能修改。

访问(Access)操作:就是根据索引、切片、解包等方式,读取其中的数据,而不是修改。

索引(Indexing)

  • 正索引:从左到右,0 开始。
  • 负索引:从右到左,-1 表示最后一个。
t1 = ("Rohan", "Physics", 21, 69.75)
t2 = (1, 2, 3, 4, 5)

print(t1[0])   # Rohan
print(t2[2])   # 3

# 负索引
t3 = ("a", "b", "c", "d")
print(t3[-1])  # d
print(t3[-3])  # b

切片(Slicing)

  • 语法:tuple[start:stop:step]
  • 特点:返回新的子元组,不会修改原元组。
t = (0, 1, 2, 3, 4, 5)

print(t[1:4])   # (1, 2, 3)  从索引1到3
print(t[:3])    # (0, 1, 2)  省略 start,默认0
print(t[3:])    # (3, 4, 5)  省略 stop,默认到结尾
print(t[::2])   # (0, 2, 4)  步长为2
print(t[::-1])  # (5, 4, 3, 2, 1, 0)  倒序

注意:切片的 stop 不包含 对应索引。

使用负索引进行切片

t = ("a", "b", "c", "d", "e")

print(t[-3:])   # ('c', 'd', 'e')  从倒数第3个到最后
print(t[1:-1])  # ('b', 'c', 'd')  去掉首尾

子元组(Subtuple)

子元组就是通过切片获取的一部分元组。

tuple1 = ("a", "b", "c", "d")
tuple2 = (25.50, True, -55, 1+2j)

print(tuple1[1:3])  # ('b', 'c')
print(tuple2[0:2])  # (25.5, True)

遍历访问

元组是可迭代对象,可以逐一访问:

t = ("apple", "banana", "cherry")

# 只取元素
for item in t:
    print(item)

# 同时取索引和元素
for i, v in enumerate(t):
    print(i, v)

解包(Unpacking)

一次性把元组的元素取出来,赋值给多个变量:

t = ("Tom", 18, "Physics")

name, age, subject = t
print(name, age, subject)  # Tom 18 Physics

# 带 *
nums = (1, 2, 3, 4, 5)
a, *b = nums
print(a)  # 1
print(b)  # [2, 3, 4, 5]

访问嵌套元组

元组里还能套元组,需要多级索引。

t = (1, (2, 3), (4, (5, 6)))

print(t[1])        # (2, 3)
print(t[1][0])     # 2
print(t[2][1][1])  # 6

index():获取元素位置

t = ("a", "b", "c", "b")
print(t.index("b"))      # 1
print(t.index("b", 2))   # 3  从索引2开始查找

count():统计元素出现次数

t = (1, 2, 2, 3, 2, 4)
print(t.count(2))  # 3

len():获取长度

t = (10, 20, 30)
print(len(t))   # 3
print(t[len(t)-1])  # 30,最后一个元素

注意事项

  1. 不可变性:元组不能修改元素值,但如果内部有 可变对象(如 list),则能改。

    t = (1, [2, 3])
    t[1][0] = 99
    print(t)  # (1, [99, 3])
    
  2. 越界会报错

    t = (1, 2, 3)
    print(t[5])  # IndexError
    
  3. 解包必须匹配数量,除非用 *

    t = (1, 2, 3)
    a, b = t  # ❌ ValueError
    

更新元组

元组(tuple)是不可变的序列类型

  • 一旦创建,不能直接修改、添加或删除元素
  • 如果需要“更新”,只能通过 重建新的元组 来实现。

所谓“更新元组”,实际上是:

  • 组合(concatenate):把多个元组拼接成新元组。
  • 切片(slice)+拼接:用切片截取部分,再插入新元素。
  • 转换为列表修改:借助列表的可变性修改,再转回元组。
  • 推导式/解包:用 Python 特性生成新的元组。

使用 串连接运算符 +

T1 = (10, 20, 30, 40)
T2 = ('one', 'two', 'three', 'four')

# 通过拼接生成新元组
T1 = T1 + T2
print(T1)

输出:

(10, 20, 30, 40, 'one', 'two', 'three', 'four')

适合在元组末尾增加新元素。
注意:这会创建一个新元组,而不是修改原元组。

使用 切片 + 拼接

T1 = (37, 14, 95, 40)
new_elements = ('green', 'blue', 'red', 'pink')

# 切片 + 拼接
updated_tuple = T1[:2] + new_elements + T1[2:]
print("Original:", T1)
print("Updated:", updated_tuple)

输出:

Original: (37, 14, 95, 40)
Updated: (37, 14, 'green', 'blue', 'red', 'pink', 95, 40)

适合在指定位置插入元素。

使用 列表推导式(list comprehension)

T1 = (10, 20, 30, 40)

# 转成列表并更新
updated_list = [item + 100 for item in list(T1)]
updated_tuple = tuple(updated_list)

print("Original:", T1)
print("Updated:", updated_tuple)

输出:

Original: (10, 20, 30, 40)
Updated: (110, 120, 130, 140)

适合批量更新元组里的元素。

使用 append()(间接)

T1 = (10, 20, 30, 40)
new_elements = [50, 60, 70]

# 转换为列表后用 append()
list_T1 = list(T1)
for element in new_elements:
    list_T1.append(element)

updated_tuple = tuple(list_T1)

print("Original:", T1)
print("Updated:", updated_tuple)

输出:

Original: (10, 20, 30, 40)
Updated: (10, 20, 30, 40, 50, 60, 70)

适合多个元素逐一添加。

使用 解包(unpacking)

T = (1, 2, 3, 4)

# 修改第一个元素
T = (100, *T[1:])
print(T)  # (100, 2, 3, 4)

直观地替换某个位置的值。

使用生成器表达式生成新元组

T = (1, 2, 3, 4, 5)
# 生成每个元素平方的新元组
T = tuple(x**2 for x in T) # x**2 for x in T 是一个生成器表达式,需要转换为元组类型
print(T)  # (1, 4, 9, 16, 25)

元组中含有可变对象(间接更新)

T = (1, [2, 3], 4)

# 修改元组中的列表元素
T[1][0] = 200
print(T)  # (1, [200, 3], 4)

虽然元组不可变,但里面的可变对象(列表、字典)可以被修改。

元组解包

什么是解包?

  • 解包(unpacking):把元组(或其他可迭代对象)中的元素“拆开”,分别赋值给多个变量。
  • 打包(packing):把多个值组合成一个元组。

示例:

t1 = (10, 20)      # 元组写法 1
t2 = 10, 20        # 元组写法 2(括号可省略)
print(type(t1))    # <class 'tuple'>
print(type(t2))    # <class 'tuple'>

基础解包

tup1 = (10, 20, 30)
x, y, z = tup1
print("x:", x, "y:", y, "z:", z)
# 输出: x: 10 y: 20 z: 30

要点:左侧变量数量必须和右侧元组元素数量相等。

解包时报错(ValueError)

如果变量个数不匹配,就会报错:

tup1 = (10, 20, 30)

x, y = tup1
# ValueError: too many values to unpack (expected 2)

x, y, p, q = tup1
# ValueError: not enough values to unpack (expected 4, got 3)

使用 * 号进行灵活解包

Python 允许在解包时用 *变量 接收“剩余元素”,避免报错。
接收到的结果会是一个 列表

  1. 接收剩余元素

    tup1 = (10, 20, 30)
    x, *y = tup1
    print("x:", x, "y:", y)
    # 输出: x: 10 y: [20, 30]
    
  2. 左右两边都解包

    tup1 = (10, 20, 30, 40, 50, 60)
    x, *y, z = tup1
    print("x:", x, "y:", y, "z:", z)
    # 输出: x: 10 y: [20, 30, 40, 50] z: 60
    
  3. 前面用 *

    tup1 = (10, 20, 30, 40, 50, 60)
    *x, y, z = tup1
    print("x:", x, "y:", y, "z:", z)
    # 输出: x: [10, 20, 30, 40] y: 50 z: 60
    

嵌套解包

t = (1, (2, 3), 4)
a, (b, c), d = t
print(a, b, c, d)   # 1 2 3 4

解包忽略值(用 _ 占位)

tup = (10, 20, 30)
x, _, z = tup
print(x, z)   # 10 30

解包在实际中的应用

  1. 交换变量

    a, b = 1, 2
    a, b = b, a
    print(a, b)   # 2 1
    
  2. 遍历时同时解包

    pairs = [(1, 'a'), (2, 'b')]
    for num, char in pairs:
        print(num, char)
    
  3. 解压(zip 与解包)

    pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
    nums, letters = zip(*pairs)
    print(nums)     # (1, 2, 3)
    print(letters)  # ('a', 'b', 'c')
    

循环元组

元组是 可迭代对象(iterable),这意味着我们可以使用循环(如 for)逐个访问其中的元素。
常见用途:

  • 遍历元组中的所有元素;
  • 遍历时解包多个值;
  • 搭配 enumerate() 获取索引和值;
  • 搭配 zip() 同时遍历多个元组。

基础循环:遍历整个元组

tup = ("apple", "banana", "cherry")

for item in tup:
    print(item)

输出:

apple
banana
cherry

和列表一样,元组遍历的顺序是 从左到右,保持元素的 有序性

使用索引循环(range(len())

有时我们需要访问 索引

tup = ("apple", "banana", "cherry")

for i in range(len(tup)):
    print("Index:", i, "Value:", tup[i])

输出:

Index: 0 Value: apple
Index: 1 Value: banana
Index: 2 Value: cherry

使用 enumerate() 同时取索引和值

这是更 Pythonic 的写法:

tup = ("apple", "banana", "cherry")

for index, value in enumerate(tup):
    print(f"Index {index} -> {value}")

输出:

Index 0 -> apple
Index 1 -> banana
Index 2 -> cherry

循环时解包元组

当元组本身嵌套多个元素时,可以 直接解包

students = [("Tom", 20), ("Alice", 22), ("Bob", 19)]

for name, age in students:
    print(f"{name} is {age} years old")

输出:

Tom is 20 years old
Alice is 22 years old
Bob is 19 years old

while 循环遍历元组

虽然 for 更常用,但 while 也能遍历:

tup = ("a", "b", "c", "d")
i = 0

while i < len(tup):
    print(tup[i])
    i += 1

索引变量在循环中使用,以跟踪序列中的当前位置或索引,例如元组或数组。它通常在循环之前初始化,并在循环中更新以迭代序列。

使用 zip() 同时循环多个元组

names = ("Tom", "Alice", "Bob")
ages = (20, 22, 19)

for name, age in zip(names, ages):
    print(f"{name} -> {age}")

输出:

Tom -> 20
Alice -> 22
Bob -> 19

循环中的 breakcontinue

tup = (10, 20, 30, 40, 50)

for num in tup:
    if num == 30:
        continue  # 跳过 30
    if num == 50:
        break     # 遇到 50 停止循环
    print(num)

输出:

10
20
40

嵌套元组的循环

matrix = ((1, 2), (3, 4), (5, 6))

for row in matrix:
    for col in row:
        print(col, end=" ")
    print()

输出:

1 2 
3 4 
5 6 

all()any() 搭配循环

tup = (2, 4, 6, 8)
print(all(x % 2 == 0 for x in tup))  # True(全是偶数)
print(any(x > 5 for x in tup))       # True(至少一个大于5)

sorted() 遍历

tup = (3, 1, 4, 2)
for x in sorted(tup):
    print(x, end=" ")
# 输出: 1 2 3 4

加入元组

元组是不可变(immutable)的,也就是说一旦创建,它的内容(元素的数量和顺序)就不能被直接修改。因此,元组没有像 list.append()list.extend() 这样的直接方法。

元组的不可变性保证了:

  • 元组可以作为字典的键;
  • 元组可以作为集合的元素;
  • 提高数据的安全性和哈希性能。

所以 不能直接增删改元组的元素,但我们可以 通过生成新元组来实现“加入”效果

+ 运算符连接元组(最常见)

示例:

tup = (1, 2, 3)
tup = tup + (4,)   # 注意 (4,) 必须加逗号,才能表示元组
print(tup)

输出:

(1, 2, 3, 4)

使用 += 运算符

其实和 + 类似,本质上也是创建了新元组。

示例:

tup = (1, 2, 3)
tup += (4, 5)
print(tup)

输出:

(1, 2, 3, 4, 5)

使用 tuple() 和列表转换(灵活)

如果你要频繁“加入元素”,建议先把元组转为列表,操作完成后再转回元组。

示例:

tup = (1, 2, 3)
temp_list = list(tup)
temp_list.append(4)      # 列表支持 append
tup = tuple(temp_list)
print(tup)

输出:

(1, 2, 3, 4)

适用场景:需要多次修改时,比频繁用 + 效率更高。

使用 * 解包方式加入元素(灵活可控)

解包 (*) 可以让你把一个元组拆开,再与新元素组合。

示例:

tup = (1, 2, 3)
tup = (*tup, 4, 5)   # 在末尾加入
print(tup)

输出:

(1, 2, 3, 4, 5)

也可以插入到开头:

tup = (1, 2, 3)
tup = (0, *tup)
print(tup)

输出:

(0, 1, 2, 3)

使用 sum() 函数

sum() 通常用于数值相加,但加元组时也能“拼接”,不过需要指定起始值 ()

T1 = (10, 20)
T2 = (30, 40)
T3 = (50, 60)

joined = sum((T1, T2, T3), ())
print(joined)

输出:

(10, 20, 30, 40, 50, 60)

注意sum() 内部会做大量拷贝,效率比不上 +*,所以不推荐在大数据下使用。

使用 for 循环逐个加入

通过循环遍历一个元组的元素,用 += 拼接到另一个元组。

T1 = (10, 20)
T2 = (30, 40)

for item in T2:
    T1 += (item,)

print(T1)

输出:

(10, 20, 30, 40)

适用场景:理解拼接原理,但实际效率不高。

在指定位置插入元素

虽然没有直接的 insert,但可以通过切片和拼接实现。

示例:

tup = (1, 2, 3, 4)
pos = 2   # 想在下标 2 的位置插入 99
tup = tup[:pos] + (99,) + tup[pos:]
print(tup)

输出:

(1, 2, 99, 3, 4)

一次性加入多个元素

无论是 + 还是 * 解包,都可以一次性加入多个元素。

示例:

tup = (1, 2, 3)
tup = tup + (4, 5, 6)
print(tup)

输出:

(1, 2, 3, 4, 5, 6)

使用生成器生成新元组

虽然元组推导式不存在,但可以用生成器表达式再转成元组,顺便加上新元素。

示例:

tup = (1, 2, 3)
new_tup = tuple(x for x in tup) + (4,)
print(new_tup)

输出:

(1, 2, 3, 4)

元组方法

元组概述

  • 元组(tuple 是 Python 的基本数据结构之一,是一种 有序、不可变(immutable)的序列类型
  • 列表(list) 不同,元组一旦创建就 无法修改(不能增删元素),因此非常适合表示 固定的数据集合
  • 元组的不可变性在 数据安全性与稳定性 很重要的场景下非常有用,比如:
    • 表示一个 坐标点 (x, y)
    • 作为 字典的键(需要可哈希对象);
    • 表示函数的 多返回值

元组可以包含 不同数据类型:整数、浮点数、字符串,甚至其他元组。

查看元组支持的方法

可以通过 dir()help() 探索元组支持的所有方法与属性:

print(dir((1, 2)))
print(help((1, 2).index))

输出(截取关键部分):

['__add__', '__class__', ..., 'count', 'index']
Help on built-in function index:
index(value, start=0, stop=9223372036854775807, /)

结论:元组真正提供的 可直接调用的方法只有 2 个

  1. tuple.count(obj)
  2. tuple.index(obj)

元组方法详解

  1. tuple.count(obj)

    • 功能:返回指定对象在元组中出现的次数。

    • 语法

      tuple.count(obj)
      
    • 返回值:整数,表示出现次数。

    示例 1:基本用法

    tup1 = (10, 20, 45, 10, 30, 10, 55)
    print("Tup1:", tup1)
    c = tup1.count(10)
    print("count of 10:", c)
    

    输出:

    Tup1: (10, 20, 45, 10, 30, 10, 55)
    count of 10: 3
    

    示例 2:包含表达式的情况

    tup1 = (10, 20/80, 0.25, 10/40, 30, 10, 55)
    print("Tup1:", tup1)
    c = tup1.count(0.25)
    print("count of 0.25:", c)
    

    输出:

    Tup1: (10, 0.25, 0.25, 0.25, 30, 10, 55)
    count of 0.25: 3
    
  2. tuple.index(obj[, start[, end]])

    • 功能:返回指定对象在元组中首次出现的索引。

    • 语法

      tuple.index(obj, start=0, end=len(tuple))
      
    • 返回值:整数,表示元素第一次出现的位置。

    • 异常:如果元素不存在,则抛出 ValueError

    示例:

    tup1 = (25, 12, 10, -21, 10, 100)
    print("Tup1:", tup1)
    x = tup1.index(10)
    print("First index of 10:", x)
    

    输出:

    Tup1: (25, 12, 10, -21, 10, 100)
    First index of 10: 2
    

    示例(指定起始索引):

    tup = ('a','b','c','b','d')
    print(tup.index('b', 2))   # 从索引 2 开始找
    

    输出:

    3
    

虽然元组只有 2 个方法,但由于它实现了 序列协议,所以我们还能用很多内置函数和操作符:

操作 示例 说明
索引 t[0] 访问单个元素
切片 t[1:3] 获取子元组
拼接 t1 + t2 返回新元组
重复 t * 3 元组重复
成员测试 x in t 判断元素是否存在
长度 len(t) 获取长度
迭代 for x in t: 遍历元素
解包 a, b = (1, 2) 多值赋值
带星号解包 a, *b, c = (1,2,3,4) 剩余部分收集为列表
排序 sorted(t) 返回排序后的 列表
统计 min(t), max(t), sum(t) 求最值、总和

命名元组

什么是 NamedTuple

  • namedtuple 是 Python collections 模块中的一个工厂函数,用于创建 带字段名的元组子类
  • 它结合了元组的不可变性和字典的可读字段:
    • 可以像元组一样 索引访问
    • 可以像对象一样 通过字段名访问

优势

  1. 可读性高:可以通过字段名访问,而不是记住索引;
  2. 占用内存小:比字典更轻量;
  3. 不可变:保证数据安全;
  4. 兼容元组操作:可进行切片、索引等操作。

导入与创建 NamedTuple

  1. 导入

    from collections import namedtuple
    
  2. 创建命名元组

    语法:

    NamedTupleClass = namedtuple('ClassName', ['field1', 'field2', ...])
    
    • 'ClassName':命名元组类名(首字母大写惯例);
    • ['field1', 'field2', ...]:字段名列表(也可用空格分隔的字符串)。

    示例:

    from collections import namedtuple
    
    # 定义一个二维坐标类 Point
    Point = namedtuple('Point', ['x', 'y'])
    
    # 创建实例
    p = Point(10, 20)
    
    print(p)       # Point(x=10, y=20)
    print(p.x, p.y)  # 10 20
    

    注意:字段名不能是 Python 保留关键字,否则可加参数 _rename=True 自动重命名。

访问 NamedTuple 字段

  1. 通过字段名

    print(p.x)  # 10
    print(p.y)  # 20
    
  2. 通过索引

    print(p[0])  # 10
    print(p[1])  # 20
    
  3. 使用 getattr()

    print(getattr(p, 'x'))  # 10
    print(getattr(p, 'y'))  # 20
    
  4. 遍历

    for value in p:
        print(value)
    

NamedTuple 内置方法

命名元组除了普通元组的方法,还带有一些专用方法:

方法 功能 示例
_fields 返回字段名元组 Point._fields('x', 'y')
_make(iterable) 从可迭代对象创建实例 Point._make([30, 40])Point(x=30, y=40)
_asdict() 转换为字典 p._asdict(){'x': 10, 'y': 20}
_replace(**kwargs) 替换字段创建新实例 p._replace(x=100)Point(x=100, y=20)

示例:

# _fields
print(p._fields)  # ('x', 'y')

# _make
p2 = Point._make([30, 40])
print(p2)  # Point(x=30, y=40)

# _asdict
print(p._asdict())  # {'x': 10, 'y': 20}

# _replace
p3 = p._replace(x=50)
print(p3)  # Point(x=50, y=20)

使用 ** 运算符

** 运算符可以将命名元组的字段解压缩成关键字参数,用于函数调用或创建命名元组。

示例:

Student = namedtuple('Student', ['name', 'age', 'DOB'])

di = {'name': "ravi", 'age': 24, 'DOB': '13-9-1997'}
s = Student(**di)
print(s)  # Student(name='ravi', age=24, DOB='13-9-1997')

其他用法

  1. 默认值

    Person = namedtuple('Person', ['name', 'age', 'city'], defaults=['Unknown'])
    p1 = Person('Alice')
    print(p1)  # Person(name='Alice', age='Unknown', city='Unknown')
    
  2. 嵌套命名元组

    Point3D = namedtuple('Point3D', ['x', 'y', 'z'])
    Line = namedtuple('Line', ['start', 'end'])
    
    line = Line(Point3D(0,0,0), Point3D(1,1,1))
    print(line.start.x)  # 0
    print(line.end.z)    # 1
    
  3. 配合函数返回多个值

    def get_point():
        return Point(5, 10)
    
    pt = get_point()
    print(pt.x, pt.y)  # 5 10
    

更多推荐