今天刷到一个视频,讲的是input返回一个字符串。如果想拿到数字的话,需要用int或者float类型转换。这个用法挺常见,也挺基础的。
但是突然想到上学期(大二上)Python课上老师给我们讲的是eval(当时我就已经学过Python了,所以当时没有听,后来有同学问我题,我才知道老师上课这么写)
其实eval本身没错,换句话说,代码能够正常运行。但是但凡懂一点编程知识的都知道,如果用eval做input的类型转换,是多么搞笑的一件事
eval算是一个函数,它的功能就是接收一个字符串参数,将字符串里的内容按照Python的代码进行执行,并将返回值赋给前面的变量。
其实说到这,只要你熟悉input,很多人就已经反应过来了
我们拿下面这段代码举例
a = eval(input())
比如我在控制台输入了1,这时候input就会返回字符串的1。字符串1就作为evil的参数,在eval看来,这个字符串里的内容就是一个数字一这个就是一个Python代码,那么一我就会认为这是一个整数,a就会被赋值为一个整数1。
这时候,你主要重点的理解是返回值和参数,第2个就是理解引号的层级。1加一对引号表示字符串1,eval转化代码的区域就是字符串的内容,而不是字符串。你可以认为最外层的这个引号就是用来规定数据类型的,它是一个字符串,eval真正能看到的是引号内的内容,所以如果你想表示字符串,你需要有两层引号,或者通过转义符的方式进行表示。
这时问题也就显而易见了,自己敲程序玩还好,如果真的在面对用户服务的程序中写这样的代码,用户输入一些危险命令,eval会直接把这些字符串转化成真正的Python代码并执行,整个程序崩溃都是轻的,甚至导致整个公司破产。
我认为最搞笑的就是你意识到这些并不需要懂什么严谨的黑客思维,比如不信任前端发来的任何东西,分析可能的逻辑漏洞和代码风险。你仅仅只需要掌握input的用法和eval的用法,并且愿意思考和学习,基本就能意识到这里面的问题。(跟着无脑敲代码和连学都不学的人除外)
但是这个写法就这样持续了这么多年,堂而皇之的直到2025年都还被教授,程序一边强调着漏洞思维,安全意识,一边教着这样的代码。这不是搞笑是什么?难道是严谨吗[旺柴]。
现在突然又想起来这件事,我突然又意识到另一个问题。为什么都到今天了还会就这样的代码,或者更本质一点,这样的写法是哪儿来的,难道没有人知道这样的问题吗?
了解了一下,原来这个起源还跟Python2有关。在Python2中input的返回就自带了eval功能。或者说input的返回就已经是相应的python内容了,比如你输入hello,返回的就是字符串hello。输入1返回就是整数1,而实现这个的方式就是简单粗暴的让输入的内容过一下eval,然后返回。
在Python3中,这样的一个特性就被修复了,估计是Python的官方也反应过来了,这样的操作有多危险,所以Python返回所有都是字符串类型,正常的做法就是根据输入要求自行做类型转换。
但是当时的教材可能为了图省事,不是少了个eval功能吗?我直接手动补回来。然后Python开始越来越受欢迎,用的人越来越多,课程和教材就一起逐渐被推行。而授课的老师一般都不是专业的程序员,他们没有什么所谓的高级的思维,多数都是在硬背教案,程序能运行那就是对的。总之在各种各样的问题之下,成就了如今的局面。
我顺便问了豆包Python2和Python3的差别,然后在他的回答下,我想起来了另一个位置,在Python2中是否写Object,会定义出两种类,而Python3默认全部继承自Object。我们老师当时教我们写面向对象的时候,告诉我们尽量要在定义类的时候,如果没有继承其他类,就要写一个继承自Object,这样一个程序就可以在Python2和Python3中通用,或者说Python3程序也能兼容Python2。
现在想想,这件事的幽默程度丝毫不亚于用eval写input。且不说所谓的兼容也只能是一定程度上的,整个Python2和Python有多处的用法都不一样,说个最简单的,就连print的用法都是完全不同的,一个是关键字,一个是函数。我实在是不觉得在2025年,写一个程序要兼容早就被废弃好多年,官方早就停止维护的一个充满争议和缺陷的版本有什么意义。
其实咱们客观来讲,这句话说法本身没问题,因为在好几年之前,那个时候Python2的确是主流,Python3刚刚出现。许多程序就采用这样一种方法,希望达到两者兼容的形式,作为一个系统升级的过渡方案。但是在2025年,大家都能够理解这样的做的意义到底有没有。
豆包把这两件事情称为行业的黑色幽默。我只是笑笑,不说话,豆包也有他的想法,好好去当个评论家。
今天有点累了,我就先不怎么说了,真想到了啥找时间再补吧。
找时间把和豆包的发言粘过来。
祝前程似锦

Comments NOTHING