python面试_总结01_概念和内置高阶函数
- 简答题
1、请谈谈Python中is 和 == 的区别(代码演示)
is用于比较两个变量是否引用了同一个内存地址,is表示的是对象标识符(object identity),作用是用来检查对象的标识符是否一致,也就是比较两个对象在内存中的地址是否一样。
==用于比较两个变量的值是否相等,==表示的是相等(equality)。
is是检查两个对象是否指向同一块内存地址,而==是检查他们的值是否相等。
可以看出,is是比==更严格的检查,is返回True表明两个对象指向同一块内存,值也一定相同。
# case 1:对于数值型和字符串型对象, python的存储机制使得a和b其实指向同一个地址,所以is和==都是True a = 7 b = 7 print("a和b是int型") print("a的地址是", id(a)) print("b的地址是", id(b)) # 比较地址 print("a和b的地址值相同?", a is b) # 比较值 print("a和b的数值相同?", a == b)
a和b是int型 a的地址是 139947890484128 b的地址是 139947890484128 a和b的地址值相同? True a和b的数值相同? True
# case 2:对于list、tuple等容器,a和b虽然内容一样,但是是两个不同的对象引用,指向两个不同的内存地址 a = [1, 2, 3] b = [1, 2, 3] print("a和b是列表") print("a的地址是", id(a)) print("b的地址是", id(b)) # 比较地址 print("a和b的地址值相同?", a is b) # 比较值 print("a和b的数值相同?", a == b) print("*"*20) a = (1, 2, 3) b = (1, 2, 3) print("a和b是元组") print("a的地址是", id(a)) print("b的地址是", id(b)) # 比较地址 print("a和b的地址值相同?", a is b) # 比较值 print("a和b的数值相同?", a == b)
a和b是列表 a的地址是 139947465543432 b的地址是 139947786638728 a和b的地址值相同? False a和b的数值相同? True ******************** a和b是元组 a的地址是 139947474361656 b的地址是 139947474360072 a和b的地址值相同? False a和b的数值相同? True
# case 3:实际上可以通过修改对象的__eq__方法改变==的比较方式 # 对象相等的判断 # python中的对象是否相等有两个层面, # 一个层面是是否是同一个对象,及在内存中是否共用一个内存区域,用is判断,另一个是对象的值是否相等,用==判断。 # 比较两个python对象是否相等,看个例子: class student(object): def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def __eq__(self, *args, **kwargs): return object.__eq__(self, *args, **kwargs) like = student("like", 25, "male") xue = student("xue", 23, "female") dong = student("like", 25, "male") print(like is xue) # False print(like is dong) # False print(like == dong) # False # 这里有两个student类的实例化对象,like和xue很明显是两个不同的对象,他们的不同体现在所占内存地址不同且对象的属性也不同。 # ************************************************************************ # like和dong虽然属性相同,但是is和==两种判断的结果也都为false, # 在实际情况中,我们大多都希望like和dong属性相同,就认为是同一个对象,所以我们需要重写类的eq方法: class student(object): def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def __eq__(self,other): return self.__dict__ == other.__dict__ # return self.name == other.name like = student("like",25,"male") dong = student("like",25,"male") print(like == dong) # True # 调用一个对象的dict方法可以用字典的形式输出其属性列表,由于两个对象的属性相同,所以==运算为True。 # ************************************************************************ # 自定义python对象相等的条件 # 当然在实际情况下,可以更灵活的定义两个对象相等的条件,比如名字一样就认为相等。 class student(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __eq__(self,other): return self.name == other.name like = student("like", 25, "male") dong = student("like", 23, "female") print(like == dong) # True # ************************************************************************ # 在实际应用中,有一个场景是处理对象是否在list里,不在就加入。 like = student("like", 25, "male") dong = student("like", 25, "male") list1 = [] list1.append(like) if dong not in list1: list1.append(dong) print(len(list1)) # 1
False False False True True 1
2、Python中的高阶函数是指什么
map、reduce、filter、zip这类函数
2.1、map()
map() 顾名思义,map函数的作用是映射。python源码解释如下:
map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from each of the iterables. Stops when the shortest iterable is exhausted.
简单来说,
map()它接收一个函数 f 和一个可迭代对象(这里理解成 list),并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。
注意:map()函数不改变原有的 list,而是返回一个新的 list。
# 举例: _list = [1, 2, 3] def f(x): return x * x # map(f, _list) # map at 0x7f43e045dba8> print(list(map(f, _list))) # 通过map,完成了对列表每个元素开平方的功能 # 结合匿名函数使用,实现功能同上 print(list(map(lambda x: x * x, _list))) # 任务 # 假设用户输入的英文名字不规范,没有按照首字母大写,后续字母小写的规则, # 请利用map()函数,把一个list(包含若干不规范的英文名字)变成一个包含规范英文名字的list: list_ = ['lll', 'lKK', 'wXy'] def f_(abc): ''' 首字母大写,后续字母小写 ''' return abc[0:1].upper() + abc[1:].lower() # return abc.capitalize() print(list(map(f_, list_)))
[1, 4, 9] [1, 4, 9] ['Lll', 'Lkk', 'Wxy']
2.2、reduce()
reduce()和map()类似,但是reduce()传入的函数 f 必须接收两个参数,而且reduce()还要导包。。。差评
# 举例 from functools import reduce ## 累加求和,小学经典的求前100个数的问题。。。 def add(x, y): return x + y print(reduce(add, [i for i in range(1, 101)])) # 匿名函数实现同样功能 print(reduce(lambda x, y: x + y, [i for i in range(1, 101)]))
5050 5050
2.3、filter()
顾名思义,过滤用的函数,用法同map()类似,filter()函数接收一个函数 f 和一个list,只不过这里的f起到的是判断的作用,符合条件的留下,不符合的丢掉
# 举例 # 过滤列表中所有能被3乘除的数和等于2的数 list_ = [-9, -7, -6, 0, 2, 16, 99] def f(x): if x % 3 == 0: return x # 非0即真,这里的0认为是false,无法被选中 elif x == 2: # x == 0。。。抑郁了 return x # filter(f, list_) # <filter at 0x7f43e0308b70> list(filter(f, list_))
[-9, -6, 2, 99]
2.4、zip()
zip函数接受任意多个可迭代对象作为参数,将对象中对应的元素打包成一个tuple,然后返回一个可迭代的zip对象
# 举例 a1=[1,2,3] a2=[4,5,6] a3=[7,8,9] a4=["a","b","c","d"] zip1 = zip(a1,a2,a3) print(zip1) # <zip object at 0x7f43e03def08> # print(list(zip1)) # 这里变成list的话,直接输出[(1, 4, 7), (2, 5, 8), (3, 6, 9)],下面的for循环就没有输出了 print("*"*20) for i in zip1: print(i) print("*"*20) # 这个可迭代对象可以使用循环的方式列出其元素 # 若多个可迭代对象的长度不一致,则所返回的列表与长度最短的可迭代对象相同. zip2 = zip(a1, a4) # print(list(zip2)) for i in zip2: print(i)
<zip object at 0x7f480ef99788> ******************** (1, 4, 7) (2, 5, 8) (3, 6, 9) ******************** (1, 'a') (2, 'b') (3, 'c')
3、Python类中有哪些的成员,如何分类他们,他们各自又有哪些用途?
python是一种以面向对象为思想的编程语言,面向对象的核心在于,一切皆对象,而对象由两部分组成,属性 + 方法。
python类中包括了类属性(即类变量)、类方法、成员属性(实例属性)、成员函数(实例方法)、静态方法。
比如我们构建动物类 class Animal,这个Animal类可以有体重,颜色等类属性,当实例化Animal类的实例对象时,
这些类属性是共用的(实例对象共用),同理类方法也是这个意思。而Animal类在构建的时候有一种魔法方法成为构造方法,"_init_",
它会在实例化对象的时候给每个对象初始化不同的实例属性,这个是每个成员独有的。
而在Animal类其中所写的任何(不加装饰器)类似python函数(def开头的...)的方法都是实例方法,他们是类实例化对象所共有的方法。
对于类方法和静态方法,都是在def前面加上装饰器(@classmethod和@staticmethod),类方法即类和对象都可以用,
静态方法类似于普通函数,不仅该类和对象共用静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,
也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。
4、Python中列表,元组的相同之处及区别都有哪些?集合与字典呢?
列表、元组、集合、字典都是python中的容器,可以存大量单独的int,str等数据。
列表和元组相同点:1、有序,2、都是一种序列,3、都是可迭代对象,都支持索引切片等操作
不同点:列表是可变数据类型,元组是不可变数据类型
集合和字典相同点:都是无序的
不同点:1、集合中不存重复相同的元素,2、字典中所存的元素都是键值对一一对应的,是以哈希表为基础的映射关系