化繁为简 or 化简为繁

为什么我要写这篇文章?

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

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


需求和推论

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

其他要求:

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

原始代码

_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() 函数分割成单独的字符串,再利用 e v a l eval eval 转化为对应的数据类型。
每一个点使用了两个临时变量,不妨改成列表。
因此我们试着写成这样:

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

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

合并条件判断

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]

完整代码

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

(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}")

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

(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!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值