python代码的问题?如何使用上一步的结果进行计算?

破案1101起查缴财物6.9亿元!江苏打击整治养老诈骗专项行动战果显著

破案1101起查缴财物6.9亿元!江苏打击整治养老诈骗专项行动战果显著

}

二、模拟平台安装和基本使用

三、基于OpenCV的自动驾驶控制

具体效果如下视频所示(第1个是在模拟环境中通过深度学习实现,第2个是真实的使用树莓派搭建的深度学习自动驾驶小车):

基于深度学习的自动驾驶小车

基于纯视觉的端到端自动驾驶小车,使用pytorch和神经网络计算棒实现 完整教程请在csdn上搜索“钱彬的博客 一文掌握基于深度学习的自动驾驶小车开发”

二、模拟平台安装和基本使用

该地址中提供的模拟器是基于Unity开发的,是经过删减过后的可执行程序,不再需要额外安装unity,下载下来后就可以直接运行。目前覆盖windows、Linux、Mac共3个版本。本文为了简单教学,只讲解如何在windows平台上运行和使用该模拟器。

安装好以后我们可以运行下面的python代码来实现小车的控制(注意:运行下面的代码前先启动模拟器,并停留在模拟器主界面上):

读万卷书不如行万里路,捧着所谓的经典论文或者经典书籍死记硬背不如真正的动手实践,遇到问题解决问题,在实践中才能真正的脱胎换骨。

AI这世界,星辰大海,你准备好了吗?

}

题目001: 在Python中如何实现单例模式。

“点评:单例模式是指让一个类只能创建出唯一的实例,这个题目在面试中出现的频率极高,因为它考察的不仅仅是单例模式,更是对Python语言到底掌握到何种程度,建议大家用装饰器和元类这两种方式来实现单例模式,因为这两种方式的通用性最强,而且也可以顺便展示自己对装饰器和元类中两个关键知识点的理解。 ”

方法一:使用装饰器实现单例模式。

“扩展:装饰器是Python中非常有特色的语法,用一个函数去装饰另一个函数或类,为其添加额外的能力。通常通过装饰来实现的功能都属横切关注功能,也就是跟正常的业务逻辑没有必然联系,可以动态添加或移除的功能。装饰器可以为代码提供缓存、代理、上下文环境等服务,它是对设计模式中代理模式的践行。在写装饰器的时候,带装饰功能的函数(上面代码中的wrapper函数)通常都会用functools模块中的wraps再加以装饰,这个装饰器最重要的作用是给被装饰的类或函数动态添加一个__wrapped__属性,这个属性会将被装饰之前的类或函数保留下来,这样在我们不需要装饰功能的时候,可以通过它来取消装饰器,例如可以使用President pile函数创建正则表达式对象,这样会减少频繁编译同一个正则表达式所造成的开销。

match方法是从字符串的起始位置进行正则表达式匹配,返回Match对象或None。search方法会扫描整个字符串来找寻匹配的模式,同样也是返回Match对象或None。

题目010:下面这段代码的执行结果是什么。

上面代码的运行结果很容易被误判为[0, 100, 200, 300]。首先需要注意的是multiply函数用生成式语法返回了一个列表,列表中保存了4个Lambda函数,这4个Lambda函数会返回传入的参数乘以i的结果。需要注意的是这里有闭包(closure)现象,multiply函数中的局部变量i的生命周期被延展了,由于i最终的值是3,所以通过m(100)调列表中的Lambda函数时会返回300,而且4个调用都是如此。

方法一:使用生成器,让函数获得i的当前值。

方法二:使用偏函数,彻底避开闭包。

题目011:Python中为什么没有函数重载?

“点评:C++、Java、C#等诸多编程语言都支持函数重载,所谓函数重载指的是在同一个作用域中有多个同名函数,它们拥有不同的参数列表(参数个数不同或参数类型不同或二者皆不同),可以相互区分。重载也是一种多态性,因为通常是在编译时通过参数的个数和类型来确定到底调用哪个重载函数,所以也被称为编译时多态性或者叫前绑定。这个问题的潜台词其实是问面试者是否有其他编程语言的经验,是否理解Python是动态类型语言,是否知道Python中函数的可变参数、关键字参数这些概念。

首先Python是解释型语言,函数重载现象通常出现在编译型语言中。其次Python是动态类型语言,函数的参数没有类型约束,也就无法根据参数类型来区分重载。再者Python中函数的参数可以有默认值,可以使用可变参数和关键字参数,因此即便没有函数重载,也要可以让一个函数根据调用者传入的参数产生不同的行为。

“点评:这个题目看似简单,但实际上还是比较考察面试者的功底。因为Python内置的max函数既可以传入可迭代对象找出最大,又可以传入两个或多个参数找出最大;最为关键的是还可以通过命名关键字参数key来指定一个用于元素比较的函数,还可以通过default命名关键字参数来指定当可迭代对象为空时返回的默认值。 ”

获取可迭代对象中最大的元素或两个及以上实参中最大的元素 :param key: 提取用于元素比较的特征值的函数,默认为None :param default: 如果可迭代对象为空则返回该默认值,如果没有给默认值则引发ValueError异常 :return: 返回可迭代对象或多个元素中的最大元素

题目013:写一个函数统计传入的列表中每个数字出现的次数并返回对应的字典。

“点评:送人头的题目,不解释。 ”

'b2.txt', 'b10.txt', 'b19.txt']。提示一下,可以通过字符串替换的方式为文件名补位,根据补位后的文件名用sorted函数来排序,大家可以思考下这个问题如何解决。 ”

题目35:如何剖析Python代码的执行性能?

剖析代码性能可以使用Python标准库中的cProfilepstats模块,cProfilerun函数可以执行代码并收集统计信息,创建出Stats对象并打印简单的剖析报告。Statspstats模块中的类,它是一个统计对象。当然,也可以使用三方工具line_profilermemory_profiler来剖析每一行代码耗费的时间和内存,这两个三方工具都会用非常友好的方式输出剖析结构。如果使用PyCharm,可以利用“Run”菜单的“Profile”菜单项对代码进行性能分析,PyCharm中可以用表格或者调用图(Call Graph)的方式来显示性能剖析的结果。

下面是使用cProfile剖析代码性能的例子。

如果使用line_profiler三方工具,可以直接剖析is_prime函数每行代码的性能,需要给is_prime函数添加一个profiler装饰器,代码如下所示。

题目36:如何使用random模块生成随机数、实现随机乱序和随机抽样?

“点评:送人头的题目,因为Python标准库中的常用模块应该是Python开发者都比较熟悉的内容,这个问题回如果答不上来,整个面试基本也就砸锅了。 ”

  1. random.choice(seq)函数可以从非空序列中取出一个随机元素。
  2. random.choices(population, weights=None, *, cum_weights=None, k=1)函数可以从总体中随机抽取(有放回抽样)出容量为k的样本并返回样本的列表,可以通过参数指定个体的权重,如果没有指定权重,个体被选中的概率均等。
  3. random.sample(population, k)函数可以从总体中随机抽取(无放回抽样)出容量为k的样本并返回样本的列表。

“扩展:random模块提供的函数除了生成均匀分布的随机数外,还可以生成其他分布的随机数,例如random.gauss(mu,

题目37:解释一下线程池的工作原理。

“点评:池化技术就是一种典型空间换时间的策略,我们使用的数据库连接池、线程池等都是池化技术的应用,Python标准库currrent.futures模块的ThreadPoolExecutor就是线程池的实现,如果要弄清楚它的工作原理,可以参考下面的内容。 ”

线程池是一种用于减少线程本身创建和销毁造成的开销的技术,属于典型的空间换时间操作。如果应用程序需要频繁的将任务派发到线程中执行,线程池就是必选项,因为创建和释放线程涉及到大量的系统底层操作,开销较大,如果能够在应用程序工作期间,将创建和释放线程的操作变成预创建和借还操作,将大大减少底层开销。线程池在应用程序启动后,立即创建一定数量的线程,放入空闲队列中。这些线程最开始都处于阻塞状态,不会消耗CPU资源,但会占用少量的内存空间。当任务到来后,从队列中取出一个空闲线程,把任务派发到这个线程中运行,并将该线程标记为已占用。当线程池中所有的线程都被占用后,可以选择自动创建一定数量的新线程,用于处理更多的任务,也可以选择让任务排队等待直到有空闲的线程可用。在任务执行完毕后,线程并不退出结束,而是继续保持在池中等待下一次的任务。当系统比较空闲时,大部分线程长时间处于闲置状态时,线程池可以自动销毁一部分线程,回收系统资源。基于这种预创建技术,线程池将线程创建和销毁本身所带来的开销分摊到了各个具体的任务上,执行次数越多,每个任务所分担到的线程本身开销则越小。

一般线程池都必须具备下面几个组成部分:

  1. 线程池管理器:用于创建并管理线程池。
  2. 工作线程和线程队列:线程池中实际执行的线程以及保存这些线程的容器。
  3. 任务接口:将线程执行的任务抽象出来,形成任务接口,确保线程池与具体的任务无关。
  4. 任务队列:线程池中保存等待被执行的任务的容器。

举一个简单的例子,变量a是一个字典,执行int(a['x'])这个操作就有可能引发上述三种类型的异常。如果字典中没有键x,会引发KeyError;如果键x对应的值不是strfloatintbool以及bytes-like类型,在调用int函数构造int类型的对象时,会引发TypeError;如果a[x]是一个字符串或者字节串,而对应的内容又无法处理成int时,将引发ValueError

题目39:说出下面代码的运行结果。

“点评:Python函数在定义的时候,默认参数items的值就被计算出来了,即[]。因为默认参数items引用了对象[],每次调用该函数,如果对items引用的列表进行了操作,下次调用时,默认参数还是引用之前的那个列表而不是重新赋值为[],所以列表中会有之前添加的元素。如果通过传参的方式为items重新赋值,那么items将引用到新的列表对象,而不再引用默认的那个列表对象。这个题在面试中经常被问到,通常不建议使用容器类型的默认参数,像PyLint这样的代码检查工具也会对这种代码提出质疑和警告。

题目40:如何读取大文件,例如内存只有4G,如何读取一个大小为8G的文件?

很显然4G内存要一次性的加载大小为8G的文件是不现实的,遇到这种情况必须要考虑多次读取和分批次处理。在Python中读取文件可以先通过open函数获取文件对象,在读取文件时,可以通过read方法的size参数指定读取的大小,也可以通过seek方法的offset参数指定读取的位置,这样就可以控制单次读取数据的字节数和总字节数。除此之外,可以使用内置函数iter将文件对象处理成迭代器对象,每次只读取少量的数据进行处理,代码大致写法如下所示。

在Linux系统上,可以通过split命令将大文件切割为小片,然后通过读取切割后的小文件对数据进行处理。例如下面的命令将名为filename的大文件切割为大小为512M的多个文件。

如果愿意, 也可以将名为filename的文件切割为10个文件,命令如下所示。

“扩展:外部排序跟上述的情况非常类似,由于处理的数据不能一次装入内存,只能放在读写较慢的外存储器(通常是硬盘)上。“排序-归并算法”就是一种常用的外部排序策略。在排序阶段,先读入能放在内存中的数据量,将其排序输出到一个临时文件,依此进行,将待排序数据组织为多个有序的临时文件,然后在归并阶段将这些临时文件组合为一个大的有序文件,这个大的有序文件就是排序的结果。 ”

题目41:说一下你对Python中模块和包的理解。

每个Python文件就是一个模块,而保存这些文件的文件夹就是一个包,但是这个作为Python包的文件夹必须要有一个名为__init__.py的文件,否则无法导入这个包。通常一个文件夹下还可以有子文件夹,这也就意味着一个包下还可以有子包,子包中的__init__.py并不是必须的。模块和包解决了Python中命名冲突的问题,不同的包下可以有同名的模块,不同的模块下可以有同名的变量、函数或类。在Python中可以使用importfrom ... import ...来导入包和模块,在导入的时候还可以使用as关键字对包、模块、类、函数、变量等进行别名,从而彻底解决编程中尤其是多人协作团队开发时的命名冲突问题。

题目42:说一下你知道的Python编码规范。

“点评:企业的Python编码规范基本上是参照PEP-8或谷歌开源项目风格指南来制定的,后者还提到了可以使用Lint工具来检查代码的规范程度,面试的时候遇到这类问题,可以先说下这两个参照标准,然后挑重点说一下Python编码的注意事项。 ”

    • 使用空格来表示缩进而不要用制表符(Tab)。
    • 和语法相关的每一层缩进都用4个空格来表示。
    • 每行的字符数不要超过79个字符,如果表达式因太长而占据了多行,除了首行之外的其余各行都应该在正常的缩进宽度上再加上4个空格。
    • 函数和类的定义,代码前后都要用两个空行进行分隔。
    • 在同一个类中,各个方法之间应该用一个空行进行分隔。
    • 二元运算符的左右两侧应该保留一个空格,而且只要一个空格就好。
    • 变量、函数和属性应该使用小写字母来拼写,如果有多个单词就使用下划线进行连接。
    • 类中受保护的实例属性,应该以一个下划线开头。
    • 类中私有的实例属性,应该以两个下划线开头。
    • 类和异常的命名,应该每个单词首字母大写。
    • 模块级别的常量,应该采用全大写字母,如果有多个单词就用下划线进行连接。
    • 类的实例方法,应该把第一个参数命名为self以表示对象自身。
    • 类的类方法,应该把第一个参数命名为cls以表示该类自身。
    • 采用内联形式的否定词,而不要把否定词放在整个表达式的前面。例如:if a is not b就比if not a is b更容易让人理解。
    • 不要用检查长度的方式来判断字符串、列表等是否为None或者没有元素,应该用if not x这样的写法来检查它。
    • 就算if分支、for循环、except异常捕获等中只有一行代码,也不要将代码和ifforexcept等写在一起,分开写才会让代码更清晰。
    • import语句总是放在文件开头的地方。
    • 如果有多个import语句,应该将其分为三部分,从上到下分别是Python标准模块、第三方模块和自定义模块,每个部分内部应该按照模块名称的字母表顺序来排列。

题目43:运行下面的代码是否会报错,如果报错请说明哪里有什么样的错,如果不报错请说出代码的执行结果。

“点评:这道题有两个考察点,一个考察点是对___开头的对象属性访问权限以及@property装饰器的了解,另外一个考察的点是对动态语言的理解,不需要过多的解释。 ”

“扩展:如果不希望代码运行时动态的给对象添加新属性,可以在定义类时使用__slots__魔法。例如,我们可以在上面的A中添加一行__slots__ = ('__value', ),再次运行上面的代码,将会在原来的第10行处产生AttributeError错误。 ”

题目44:对下面给出的字典按值从大到小对键进行排序。

“点评:sorted函数的高阶用法在面试的时候经常出现,key参数可以传入一个函数名或一个Lambda函数,该函数的返回值代表了在排序时比较元素的依据。 ”

题目45:说一下namedtuple的用法和作用。

“点评:Python标准库的collections模块提供了很多有用的数据结构,这些内容并不是每个开发者都清楚,就比如题目问到的namedtuple,在我参加过的面试中,90%的面试者都不能准确的说出它的作用和应用场景。此外,deque也是一个非常有用但又经常被忽视的类,还有CounterOrderedDict

在使用面向对象编程语言的时候,定义类是最常见的一件事情,有的时候,我们会用到只有属性没有方法的类,这种类的对象通常只用于组织数据,并不能接收消息,所以我们把这种类称为数据类或者退化的类,就像C语言中的结构体那样。我们并不建议使用这种退化的类,在Python中可以用namedtuple(命名元组)来替代这种类。

命名元组与普通元组一样是不可变容器,一旦将数据存储在namedtuple的顶层属性中,数据就不能再修改了,也就意味着对象上的所有属性都遵循“一次写入,多次读取”的原则。和普通元组不同的是,命名元组中的数据有访问名称,可以通过名称而不是索引来获取保存的数据,不仅在操作上更加简单,代码的可读性也会更好。

命名元组的本质就是一个类,所以它还可以作为父类创建子类。除此之外,命名元组内置了一系列的方法,例如,可以通过_asdict方法将命名元组处理成字典,也可以通过_replace方法创建命名元组对象的浅拷贝。

总而言之,命名元组能更好的组织数据结构,让代码更加清晰和可读,在很多场景下是元组、字典和数据类的替代品。在需要创建占用空间更少的不可变类时,命名元组就是很好的选择。

题目46:按照题目要求写出对应的函数。

“要求:写一个函数,传入一个有若干个整数的列表,该列表中某个元素出现的次数超过了50%,返回这个元素。 ”

“点评:LeetCode上的题目,在Python面试中出现过,利用元素出现次数超过了50%这一特征,出现和temp相同的元素就将计数值加1,出现和temp不同的元素就将计数值减1。如果计数值为0,说明之前出现的元素已经对最终的结果没有影响,用temp记下当前元素并将计数值置为1。最终,出现次数超过了50%的这个元素一定会被赋值给变量temp

题目47:按照题目要求写出对应的函数。

“要求:写一个函数,传入的参数是一个列表(列表中的元素可能也是一个列表),返回该列表最大的嵌套深度。例如:列表[1, 2, 3]的嵌套深度为1,列表[[1], [2, [3]]]的嵌套深度为3。 ”

“点评:看到题目应该能够比较自然的想到使用递归的方式检查列表中的每个元素。 ”

题目48:按照题目要求写出对应的装饰器。

“要求:有一个通过网络获取数据的函数(可能会因为网络原因出现异常),写一个装饰器让这个函数在出现指定异常时可以重试指定的次数,并在每次重试之前随机延迟一段时间,最长延迟时间可以通过参数进行控制。 ”

“点评:我们不止一次强调过,装饰器几乎是Python面试必问内容,这个题目比之前的题目稍微复杂一些,它需要的是一个参数化的装饰器。 ”

题目49:写一个函数实现字符串反转,尽可能写出你知道的所有方法。

“点评:烂大街的题目,基本上算是送人头的题目。 ”

“扩展:这些方法其实都是大同小异的,面试的时候能够给出几种有代表性的就足够了。给大家留一个思考题,上面这些方法,哪些做法的性能较好呢?我们之前提到过剖析代码性能的方法,大家可以用这些方法来检验下你给出的答案是否正确。 ”

题目50:按照题目要求写出对应的函数。

“要求:列表中有1000000个元素,取值范围是[),设计一个函数找出列表中的重复元素。 ”

“点评:这道题的解法和计数排序的原理一致,虽然元素的数量非常多,但是取值范围[1000, 10000)并不是很大,只有9000个可能的取值,所以可以用一个能够保存9000个元素的dups列表来记录每个元素出现的次数,dups列表所有元素的初始值都是0,通过对items列表中元素的遍历,当出现某个元素时,将dups列表对应位置的值加1,最后dups列表中值大于1的元素对应的就是items列表中重复出现过的元素。

}

我要回帖

更多关于 python简单代码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信