为什么我要写这篇文章?

  1. 我本来想写一个一次函数计算器的,但是为了方便想压行。
  2. 前不久,我了解到 Python 海象运算符。起初觉得这和 C++ 的特性一样嘛,经常会在记忆化搜索等类似的算法中用到。然后在实战中应用了一下,就突然发掘出了 Python 压行的玩法。

警告:
压行是为了整活,有时可以帮助减少代码体积。但是这样做很可能降低代码可读性,而且极难调试!
尽量不要在开发使用这样的手段!


需求和推论

需求:平面直角坐标系内,给出两个不同的点 A(x1,y1)A(x_1,y_1)B(x2,y2)B(x_2,y_2),求直线 ABAB 的表达式。
方法:待定系数法。
yAB=kx+by_{AB}=kx+b.
A(x1,y1)A(x_1,y_1)B(x2,y2)B(x_2,y_2) 代入,得 {y1=kx1+by2=kx2+b\left\{\begin{matrix}y_1=kx_1+b\\y_2=kx_2+b\end{matrix}\right..
所以 {k=y2y1x2x1b=y1kx1\left\{\begin{matrix}k=\frac{y_2-y_1}{x_2-x_1}\\b=y_1-kx_1\end{matrix}\right..

其他要求:

  1. 结果应该化成 y=kx+by=kx+b 的形式。
  2. 输入共两行,每行两个数,用空格隔开,分别表示 AABB 两点的横、纵坐标。输入可能为小数。
  3. k=±1k=\pm1 时,化为 y=±x+by=\pm x+b 的形式。
  4. b=0b=0 时,化为 y=kxy=kx 的形式。
  5. k=0k=0 时,化为 y=by=b 的形式。
  6. 能化为整数的化为整数,不要有 1.01.02.02.0 等的数出现。

原始代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
_x1, _y1 = input("A >>> ").split()
_x2, _y2 = input("B >>> ").split()
x1, y1 = eval(_x1), eval(_y1)
x2, y2 = eval(_x2), eval(_y2)
k = (y2 - y1) / (x2 - x1)
b = y1 - k * x1
if int(k) == float(k):
k = int(k)
if int(b) == float(b):
b = int(b)
if not k:
print("y=" + str(b))
exit()
if not b:
b = ""
else:
b = "+" + str(b)
if k == 1:
k = ""
elif k == -1:
k = "-"
print(f"y={k}x{b}")

冗杂,多余。

利用列表简化输入

我们知道,同一行输入了两个数,用空格隔开,因此我们使用 split() 函数分割成单独的字符串,再利用 evaleval 转化为对应的数据类型。
每一个点使用了两个临时变量,不妨改成列表。
因此我们试着写成这样:

1
2
x1, y1 = [eval(i) for i in input("A >>> ").split()]
x2, y2 = [eval(i) for i in input("B >>> ").split()]

这就利用了 for 循环和列表避免了临时变量。

合并条件判断

1
x, z, y = "-" if (k := (f := lambda x: int(x) if int(x) == float(x) else x)(k := (y2 - y1) / (x2 - x1))) == -1 else "" if k == 1 else k, "" if not (b := f(b := y1 - k * x1)) else b, ["", "+"][b > 0]

完整代码

这样,我们可以在三行内完成此程序设计。

1
2
3
(x1, y1), (x2, y2) = (f := lambda l: [eval(i) for i in input(f"{l} >>> ").split()])("A"), f("B")
x, z, y = "-" if (k := (f := lambda x: int(x) if int(x) == float(x) else x)(k := (y2 - y1) / (x2 - x1))) == -1 else "" if k == 1 else k, "" if not (b := f(b := y1 - k * x1)) else b, ["", "+"][b > 0]
print(f"y={x}x{y}{z}") if k else print(f"y={b}")

再利用分号,就可以把它们全部压缩至一行。如下:

1
(x1, y1), (x2, y2) = (f := lambda l: [eval(i) for i in input(f"{l} >>> ").split()])("A"), f("B"); x, z, y = "-" if (k := (f := lambda x: int(x) if int(x) == float(x) else x)(k := (y2 - y1) / (x2 - x1))) == -1 else "" if k == 1 else k, "" if not (b := f(b := y1 - k * x1)) else b, ["", "+"][b > 0]; print(f"y={x}x{y}{z}") if k else print(f"y={b}")

Perfect!