当前位置: 首页 > 后端技术 > Python

Python代码工程实践-循环

时间:2023-03-26 10:51:30 Python

使用generative改进循环语句@dataclassclassEmployee:name:strage:intsalary:intaddress:str=field(default="")role:str=field(default="")deffind_developers(employees:Sequence[Employee])->List[Employee]:developers=[]foremployeeinemployees:ifemployee.role=="developer":developers.append(employee)returndevelopers列表生成使用列表生成重构通过公式:deffind_developers(employees:Sequence[Employee])->List[Employee]:return[eforeinemployeesife.role=="developer"]生成公式的优势不仅在于语法简单,而且还将多行代码合并为一行,其性能甚至比使用for循环语句还要好。多好,大家可以自己搜索,也可以自己测试。请记住,在对列表或序列进行简单的转换或过滤时,由于使用了for循环,请使用列表理解。当循环条件复杂时,请继续使用for循环以保持代码的可读性。生成器推导使用生成器推导,将[]换成()即可,如deffind_developers(employees:Sequence[Employee])->List[Employee]:return(eforeinemployeesife.role=="developer")笔记!生成器的使用特点是“边迭代边计算”,也就是说生成器创建时,内存中并没有新的数据,只存储了转换方法。只有迭代的时候才会从内存中一个一个的读取数据,按照转换的方式进行计算。所以生成器的好处是按需占用内存,而不是提前在内存中准备数据。当需要提前在内存中准备数据时,不应使用生成器推导式,而应使用列表推导式。多次迭代生成器时可能会发生生成器耗尽。看下面的代码developers=find_developers(employees=employees)fordeveloperindevelopers:print(developer.name)fordeveloperindevelopers:print(developer.salary)developers变量是一个生成器,我们迭代两次,第一次迭代按预期打印名称,但第二次迭代不执行任何操作。所以,请记住,不要多次迭代生成器。生成器耗尽的问题在实际工作中很容易发现,但是另外一类问题就比较难发现了,比如下面的:(假设员工按照id从小到大排序)developers=find_developers(employees=employees)fordeveloperindevelopers:ifdeveloper.salary>10000:print(developer.name)breakfordeveloperindevelopers:ifdeveloper.age>30:print(developer.name)break这里有两个循环,我们期望第一个在第一个循环,找到第一个工资大于10000的开发者。第二个循环,我们期望在所有员工中找到第一个年龄大于30的开发者。但实际情况是第一个循环按预期找到了第一个工资大于10000的开发者,但是第二个循环找到了第一个工资大于10000的开发者之后年龄大于30的开发者,而这不是符合预期。使用高阶函数在上面的例子中,生成器理解可以使用高阶函数过滤器来代替deffind_developers(employees:Sequence[Employee])->Generator[Employee]:returnfilter(lambdae:e.role=="developer",employees)我们可以迭代它的返回值。我们也可以定义自己的高阶函数来实现更灵活的过滤规则find_developers(employees,lambdae:e.role=="developer")find_developers(employees,lambdae:e.role=="developer"ande.age>30)同样,我们可以使用map函数来实现iterable的对象的变形操作这里不举例。尽量避免使用whileTrue而True是一个无限循环,使用时需要特别注意退出条件,否则会继续执行,除非这是预期的行为。大多数时候,除非您正在编写常驻进程,否则您不应期望您的程序不会退出。所以在这个前提下,应该尽量避免使用whileTrue进行循环。如果需要轮询,建议使用重试机制(我们项目框架中提供了重试装饰器,自己实现很容易),并设置明确的执行次数。记住,除非你清楚地知道程序应该无休止地运行,否则不要使用whileTrue,你总会有更好的选择。避免使用递归除非递归的实现比循环更简洁有趣,并且易于阅读,否则不要使用递归。不可否认,递归是解决一些问题的有效方法,但我的建议是,除非你对自己的代码和算法能力有充分的信心,并计划进行充分的测试(单元测试或其他测试),否则不要使用递归,这可能会导致维护困难。