想当然

博客通过JUnit测试和比较Excel文件行内容的测试案例,揭示编程中读代码不能主观臆测、想当然的问题。JUnit测试中Boolean.getBoolean()方法与预期不同,Excel行比较实际只比行号。提醒程序员要有敏锐头脑和发散思维。

先看这个JUnit测试:

  public void testBoolean(){
       assertFalse(Boolean.getBoolean("true"));
  }

你认为能够测试通过吗?如果你觉得不能,那就请你亲自去运行一下看看。
......
结果如何?的确能够测试通过!


这行代码我好像是从effective java中看到的(记性不好:P),作者告诫我们读代码不能想当然,主观臆测。
看过Boolean.getBoolean()的注释或是实现之后(注1),其实这个方法与Boolean类并没有想象中的关系。不由内心生出一种被作者耍了的感觉,其实是我们读代码经常主观臆测,渐渐养成了想当然的毛病。


我时常提醒自己不要想当然,不幸的是恶习难改,今天又中招了。为了写测试类的,我需要比较excel文件中的2行的内容是否相等。我通过Apache的poi把excel中的行转化成HSSFRow对象,发现它overide了compareTo方法,大喜,以为又可以偷懒了。马上完成,运行测试,通过,更喜。将2行修改成不一样,运行,还是通过,大惊!检查无误后,不解,查看java doc:

 compareTo

 public int compareTo(java.lang.Object obj)
 
    Specified by:
        compareTo in interface java.lang.Comparable
    
什么也没有,汗。只好找来源代码,如下:

   public int compareTo(Object obj)
   {
       HSSFRow loc = (HSSFRow) obj;

       if (this.getRowNum() == loc.getRowNum())
       {
           return 0;
       }
       if (this.getRowNum() < loc.getRowNum())
       {
           return -1;
       }
       if (this.getRowNum() > loc.getRowNum())
       {
           return 1;
       }
       return -1;
   }
  
顿悟,原来只是比较行号是否相等而已。


也许是过于有规律的生活方式影响到了我们的思维方式,然而,作为一名程序员,我们要有敏锐的头脑和发散的思维。所以不敢耽误,马上写到blog上来,时时刻刻提醒我和看到这篇文章的人编程千万不可想当然哦。

注1:
    /**
     * Returns true if and only if the system property named
     * by the argument exists and is equal to the string "true".
     * (Beginning with version 1.0.2 of the JavaTM platform,
     * the test of this string is case insensitive.)
     * A system property is accessible through getProperty,
     * a method defined by the System class.
     * If there is no property with the specified name, or if
     * the specified name is empty or null, then false is returned.
     */
    public static boolean getBoolean(String name) {
        boolean result = false;
        try {
            result = toBoolean(System.getProperty(name));
        } catch (IllegalArgumentException e) {
        } catch (NullPointerException e) {
        }
        return result;
    }

    private static boolean toBoolean(String name) {
        return ((name != null) && name.equalsIgnoreCase("true"));
    }

<think> 我们面临两个主要问题:ModuleNotFoundError(模块未找到)和IndentationError(缩进错误)。根据问题解决的逻辑,我们应该先解决结构性问题(缩进错误),因为语法错误会阻止程序运行,然后再解决模块导入问题。但这里缩进错误是在交互式命令行中出现的,而模块导入错误是程序运行时的错误。实际上,我们首先需要确保代码的语法正确(包括缩进),然后才能解决模块导入问题。 然而,从用户提供的错误信息来看,这些错误是在交互式命令行(Python shell)中逐行输入的。所以,我们需要分别处理: 1. **IndentationError**:出现在定义函数和导入语句时,是因为在交互式环境中不能随意缩进。交互式环境通常要求顶层的代码不能有缩进(除了在复合语句如函数、循环等内部)。 2. **ModuleNotFoundError**:导入模块失败,可能是因为模块不在Python的搜索路径中,或者模块本身不存在。 ### 第一步:解决IndentationError(缩进错误) 在交互式环境中,我们需要严格按照提示符`>>>`和`...`来输入代码。当定义函数时,在`>>>`后输入`def my_func():`然后按回车,解释器会显示`...`提示符,表示等待函数体的输入,此时需要缩进。但是在错误示例中,用户在不同的地方出现了意外的缩进。 **解决方案:** - 在交互式环境中,避免手动输入多行代码,尤其是复杂的代码块(如函数、类)。 - 对于复杂的代码,建议在脚本文件中编写,然后运行脚本文件。 - 如果必须在交互式环境中输入,请按照以下规则: - 在`>>>`后输入函数定义的第一行(如`def my_func():`),然后按回车。 - 在出现的`...`提示符后,输入函数体内的语句,并且每一行都要有相同的缩进(通常4个空格或一个Tab)。 - 在函数体结束后,连续按两次回车,退出函数定义。 例如,正确的方式: ```python >>> def my_func(): ... print("Hello") # 这里缩进 ... ``` 而错误示例中,用户输入了: ``` >>> def my_func(): ``` 在`>>>`后面直接缩进了,这是不允许的。 另外,用户输入了: ``` >>> from paddle.base import libpaddle # 使用时才导入 ``` 在`>>>`后面有缩进,这也是不允许的。 **因此,第一步的具体操作:** 1. 退出当前的交互式环境(使用`exit()`或`quit()`,或者按Ctrl+D)。 2. 重新启动一个新的Python交互式环境。 3. 在输入代码时,确保在顶层(`>>>`后)的代码没有任何缩进(除了在复合语句内部由解释器自动提示`...`之后的缩进)。 ### 第二步:解决ModuleNotFoundError(模块未找到错误) 这个错误通常是因为Python找不到相应的模块。可能的原因: - 模块文件不在当前目录或Python搜索路径中。 - 模块文件没有命名为正确的名称。 **解决方案:** 1. 确保模块文件(module_a.py和module_b.py)存在于当前目录或Python可以搜索到的路径中。 2. 可以通过以下代码查看Python的搜索路径: ```python import sys print(sys.path) ``` 3. 如果需要添加模块所在的目录,可以使用: ```python sys.path.append("/path/to/your/module_directory") ``` **第一步具体操作(针对ModuleNotFoundError):** - 检查当前工作目录,确保模块文件存在。 在交互式环境中: ```python import os print(os.getcwd()) # 打印当前工作目录 ``` 然后,检查这个目录下是否有`module_a.py`和`module_b.py`。 - 如果模块文件不在当前目录,可以更改当前工作目录或添加模块所在的目录到`sys.path`。 ### 综合第一步方案(用户可执行) 根据问题,我们首先解决缩进错误,因为它在交互式环境中阻碍了代码的输入。然后解决模块导入错误。 **用户第一步操作指南:** 1. **退出当前交互式环境**(如果之前输入有误,建议重启): ``` >>> exit() ``` 2. **重新启动Python交互式环境**(在命令行输入`python`或`python3`)。 3. **在交互式环境中,重新输入代码,注意缩进规则**: - 顶层代码(函数定义、类定义、导入语句等)前面不要有空格,直接跟在`>>>`后面。 - 当定义函数时,在函数体内的语句前输入4个空格(或一个Tab),解释器会自动显示`...`提示符,此时输入缩进的代码。 例如,正确输入函数: ``` >>> def my_func(): ... print("Hello") ... ``` 4. **重新尝试导入模块**,如果之前导入失败,先检查模块是否存在: ``` >>> import os >>> os.listdir() # 列出当前目录的文件,查看是否有module_a.py, module_b.py ``` 5. **如果模块不在当前目录**,则添加模块所在路径: ``` >>> import sys >>> sys.path.append("/absolute/path/to/your/modules") >>> from module_a import func_a >>> from module_b import func_b ``` ### 预期结果 - 如果路径添加正确,模块文件存在且没有语法错误,导入应该成功。 - 如果仍然出现`ModuleNotFoundError`,则需要进一步检查模块的文件名和路径。 ### 下一步 根据第一步执行的结果,如果成功则进行后续操作;如果失败,则根据具体错误信息提供下一步解决方案。 ### 相关问题 1. 如何在Python中永久添加模块搜索路径? 2. Python交互式环境中如何正确输入多行代码? 3. 如何查看Python导入模块时搜索的路径? </think> ### 第一步:解决IndentationError(缩进错误) 在Python中,**缩进是语法的一部分**,错误的缩进会导致程序无法执行。根据错误提示,您遇到了`IndentationError: unexpected indent`,这是最常见的语法错误之一。请按照以下步骤修复: #### 📝 修复方案 1. **检查并统一缩进方式**: - 确保整个文件使用**4个空格**或**Tab中的一种**(不要混用) - 在VSCode/PyCharm中: - 查看右下角状态栏显示`Spaces: 4`或`Tab Size: 4` - 若不正确:右键 → "Convert Indentation to Spaces" 2. **修复示例中的具体错误**: ```python # 修复前(错误缩进) >>> from paddle.base import libpaddle # 意外缩进 # 修复后(正确缩进) from paddle.base import libpaddle # 顶格无缩进 ``` 3. **验证修复**: 在Python交互环境中重新输入代码,确保: - 所有顶级导入语句**没有缩进** - 函数/类内部的语句**统一缩进4空格** #### 🔍 验证步骤 ```python # 测试正确缩进 def test(): print("正确缩进4空格") # ← 内部语句缩进 print("顶级语句无缩进") # ← 顶级语句顶格 ``` #### ⚠️ 常见错误模式 | 错误代码 | 原因 | 修复方案 | |---------|------|---------| | `def my_func():`<br>`    print()`<br>`        return` | 嵌套缩进不一致 | 统一为4空格 | | `if True:`<br>`[Tab]print()` | 混用空格和Tab | 转换为空格 | | `import sys`<br>`    sys.path.append()` | 顶级语句缩进 | 删除缩进 | > Python的缩进规则借鉴自ABC语言,通过强制缩进来保证代码可读性[^1]。当解释器遇到意外缩进时,会立即抛出`IndentationError`终止执行[^2]。 ### 下一步行动建议 1. 先执行上述缩进修复 2. 重新运行代码并提供报错信息 3. 我将根据结果提供ModuleNotFoundError的解决方案 ### 相关问题 1. Python中为什么用缩进而不用大括号? 2. 如何配置VSCode自动修复Python缩进? 3. 有哪些工具可以检测Python的缩进错误?
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值