(一) 元类
1. @property的用法
@property是 python 的一种装饰器,用以修饰方法。使用@property装饰器来创建只读属性,将方法转换为相同名称的只读属性,,以防止属性被修改。
class DataSet(object):
@property
def method_with_property(self): # 含@property
return 15
def method_without_property(self): # 不含@property
return 15
l = DataSet()
# 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()
print(l.method_with_property)
print(l.method_without_property())
2. new和init的区别
1、new是一个静态方法,而init是一个实例方法
2、new方法会返回一个创建的实例,而init什么都不返回
3、只有在new返回一个cls的实例时后面的init才能被调用
4、当创建一个新实例时调用new,初始化一个实例时用init
3. 如何实现一个单例
方法一 :
实例化一个的对象,要用时直接 import 导如这个对象,而不是再实例化一个,这样就做到了单例模式了,每次都用的是同一个对象。
方法二 :
我们知道,当我们实例化一个对象时,是先执行了类的 new 方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的 init 方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式。
方法三:
通过装饰器实现单例模式,任意一个类使用了该装饰器就会变成一个单例模式的类。
装饰器是 Python中非常有特色的语法,用一个函数去装饰另一个函数或类,为其添加额外的能力。通常通过装饰来实现的功能都属横切关注功能,也就是跟正常的业务逻辑没有必然联系,可以动态添加或移除的功能。装饰器可以为代码提供缓存、代理、上下文环境 等服务,它是对设计模式中代理模式的践行。
方法四 :
使用元类实现单例模式。
4. python查找对象属性的顺序
对象属性的查找顺序:对象自己>>类中>>报错
5. 什么是init?
用来初始化一个类(class)的新成员(instance)
6. Python中的self是什么?
self是类的实例或对象
7. 深拷贝和浅拷贝有什么区别?
1.浅拷贝
只会拷贝基本数据类型的值和实际的引用地址,实际指向还是同一个对象,对基本类型数据修改,原对象也会紧接着修改
2.深拷贝,基本数据类型和所指向的对象都会进行复制,内部实际指向的不是一个对象,所以在做修改时两者不会同时改变
8. 什么是猴子补丁?
猴子补丁(monkey patching):在运行时动态修改模块、类或函数,通常是添加功能或修正缺陷。猴子补丁在代码运行时内存中)发挥作用,不会修改源码,因此只对当前运行的程序实例有效。因为猴子补丁破坏了封装,而且容易导致程序与补丁代码的实现细节紧密耦合,所以被视为临时的变通方案,不是集成代码的推荐方式。
9. 字典推导式
expr for value in collection if condition
10. super函数的具体用法和场景
在子类中调用父类的方法,多用于类的继承关系。
11. Python中类方法、类实例方法、静态方法有何区别?
- 类方法:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);调用:实例对象和类对象都可以调用。
- 静态方法:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;调用:实例对象和类对象都可以调用。
- 实例方法:实例方法就是类的实例能够使用的方法。
12. 遍历一个object的所有属性,并print每一个属性名?
class Car:
def __init__(self,name,loss): # loss [价格,油耗,公里数]
self.name = name
self.loss = loss
def getName(self):
return self.name
def getPrice(self):
# 获取汽车价格
return self.loss[0]
def getLoss(self):
# 获取汽车损耗值
return self.loss[1] * self.loss[2]
Bmw = Car("宝马",[60,9,500]) # 实例化一个宝马车对象
print(getattr(Bmw,"name")) # 使用getattr()传入对象名字,属性值。
print(dir(Bmw)) # 获Bmw所有的属性和方法
13. 写一个类,并让它尽可能多的支持操作符?
class Array:
__list = []
def __init__(self):
print "constructor"
def __del__(self):
print "destruct"
def __str__(self):
return "this self-defined array class"
def __getitem__(self,key):
return self.__list[key]
def __len__(self):
return len(self.__list)
def Add(self,value):
self.__list.append(value)
def Remove(self,index):
del self.__list[index]
def DisplayItems(self):
print "show all items---"
for item in self.__list:
print item
14. 请描述抽象类和接口类的区别和联系
1、抽象类和接口都不能直接实例化。如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2、抽象类要被子类继承,接口要被类实现。
3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
6、抽象方法只能申明,不能实现。
7、抽象类里可以没有抽象方法
8、如果一个类里有抽象方法,那么这个类只能是抽象类
9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
10、接口可以继承接口,并且可多继承接口,但类只能单一继承。
11.接口可以通过匿名内部类实例化。
接口是对动作的抽象,抽象类是对根源的抽象。抽象类表示的是,这个对象是什么。而接口表示的是,这个对象能做什么。
15. Python中如何动态获取和设置对象的属性?
(1)在类外面获取类属性
方式一:print(类名.属性名)
方式二:getattr(参数1,参数2,参数3),可用于动态获取
参数1:类名
参数2:属性名
参数3:如果属性不存在,则返回该值
(2)在类外面定义类属性
方式一:类名.属性名=属性值
方式二:setattr(参数1,参数2,参数3),可用于动态设置
参数1:类名
参数2:属性名
参数3:属性值
(3)动态删除属性
delattr(参数1,参数2)
参数1:类名
参数2:属性名
(4)判断属性是否存在
hasattr(参数1,参数2)
参数1:类名
参数2:属性名
若存在返回值为True,不存在返回False
16.对设计模式的理解,简述你了解的设计模式?
设计模式是经过总结,优化的,对我们经常会碰到的一些编程问题的可重用解决方案。
一个设计模式并 不像一个类或一个库那样能够直接作用于我们的代码,反之,设计模式更为高级,它是一种必须在特定 情形下实现的一种方法模板。常见的是工厂模式和单例模式 。
17. 单例模式的应用场景有那些?
需要频繁创建和销毁的对象;
创建花费太多时间或资源,但经常使用的对象;
工具类对象;
经常访问数据库或文件的对象。
18. 对装饰器的理解,并写出一个计时器记录方法执行性能的装饰器?
装饰器本质上是一个callable object,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
import time
from functools import wraps
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.clock()
ret = func(*args, **kwargs)
end = time.clock()
print('used:',end-start)
return ret
return wrapper
@timeit
def foo():
print('in foo()'foo())
19. Python的魔法方法
方法 | 说明 |
---|---|
new(cls[, …]) | 创建对象的方法,当通过类去创建对象时就是调用__new__方法去创建的 |
init(self[, …]) | 初始化方法,当实例被创建的时候调用的初始化方法 |
del(self) | 析构方法,当实例被销毁的时候调用的方法 |
call(self[, args…]) | 允许一个类的实例像函数一样被调用:x(a, b) 调用 x.call(a, b) |
repr(self) | 定义当被 repr() 调用时的行为 |
str(self) | 定义当被 str() 调用时的行为 |
bytes(self) | 定义当被 bytes() 调用时的行为 |
hash(self) | 定义当被 hash() 调用时的行为 |
bool(self) | 定义当被 bool() 调用时的行为,应该返回 True 或 False |
format(self, format_spec) | 定义当被 format() 调用时的行为 |
20. 描述元类的概念。Python有没有接口?
元类就是用来创建类的
Python没有接口
(二)内存管理与垃圾回收机制
1. Python是如何进行内存管理的?
python中的内存管理由Python私有堆空间管理。所有Python对象和数据结构都位于私有堆中。程序员无权访问此私有堆。python解释器负责处理这个问题。Python对象的堆空间分配由Python的内存管理器完成。
1、对象在引用计数机制的时候,通常采用四增五减的方式。
Python中简单的使用了计数的技术,也就是说在内存中个想一直保持对内存中的对象进行追踪的时候,就使用这个技术,比如说
sys.getrefcount(a),在这里的对象a就是使用了引用计数,在使用引用的时候记得计数要比原来的数大1。2、垃圾的回收机制
在Python中垃圾回收机制又可以分成手动自动,分代回收,就像平时一个人一样,如果吃的太多就会变胖,在Python也是这样的。如果在Python中存在的对象越来越多的时候,它们需要占据的内存就会变得越来越多,此时你不用担心Python的体格,因为它会在适当的时候进行内存的回收,启动垃圾的回收时,就会适当的清除没有用的对象。
但是需要注意的地方是,它只会在特定的条件下才开启垃圾回收机制。3、内存池机制
Python中的内存可以分成两种,分别是大内存和小内存,两者的界限大小为256k,如果你是使用的大内存管理的话,使用的malloc进行分配,如果是小内存,那么就会由内存池进行管理了,在Python中会有两套方法针对大小对象,当内存大于或者是小于256k时,pymalloc就开始在内存池中发出内存管理的请求,如果内存大于256K时,那么管理大内存的malloc则会直接执行系统来申请内存空间。
2. 当Python退出时,为什么不清除所有分配的内存?
- 循环引用其它对象或引用自全局命名空间的对象的模块,在 Python 退出时并非完全释放。另外,也不会释放 C 库保留的内存部分
- 退出时,由于具有自己有效的清除机制,Python 会尝试取消分配/销毁所有其他对象。
3. Python中变量的作用域?(变量查找顺序)
python 函数变量的查找顺序:优先级为: 局部—> 全局—> 如果仍没找到,将引发NameError错误。
4. 哪些操作会导致Python内存溢出,怎么处理?
1.当内存中一次性加载数据量过大时就可能会造成内存溢出问题,例如从数据库中一次性取出几百万条数据的时候,特别是mysql等数据库又是直接放在内存中加载数据的。
那么解决方法很简单,只需要修改一下查询语句,将总数据分为每次只取几千几万条就行。
2.python内存溢出可能是因为达到设定好的上限才造成的,这是因为python解释器(JVM)为了不让程序在运行过程之中占用过多内存资源导致其他程序运行受到影响,会给解释器能使用的内存给定一个上限值。
而解决方法就是打开python解释器的配置文件,将里面内存上限值设置大一点的数,可以通过代码来实现,示例如下:import resource soft, hard = resource.getrlimit(resource.RLIMIT_AS)
3.还有一个可能的原因就是程序中存在了过多的对象引用没有处理,或者是循环和实例对象对象过多,这些都会造成资源的极大无效占用。手动调用垃圾处理机制来回收对象,并且修改代码即可。
5. 内存泄露是什么?如何避免?
内存泄露是指:内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。
平常养成良好的代码书写习惯,该销毁的对象要销毁比如destory啊 广播啊 ,涉及到要用到content上下文的优先考虑全局上线文对象。
6. 浅拷贝会创建新对象,其内容非原对象本身的引用,而是原对象内第一层对象的引用
7. 提高python运行效率的方法
1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
3、核心模块用Cython PyPy等,提高效率
4、多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率
(三)函数
1. 简述 yield和yield from关键字
yield 替换函数里的return可以变为生成器
yield from generator 。实际上就是返回另外一个生成器。
yield from 后面可以跟的式子有“ 生成器 元组 列表等可迭代对象以及range()函数产生的序列”
2. 什么是pickling和unpickling?
- Pickle模块可以处理所有的Python对象并将其转换为字符串的表现形式,并可以使用dump函数将其转储到文件中,这个过程称为Pickle。
- 从存储的字符串中检索原始Python对象的过程称为unpickle。
3. python中的生成器是什么?
生成器是一个特殊的迭代器,它保存的是算法,每次调用next()或send()就计算出下一个元素的值,直到计算出最后一个元素,没有更多的元素时,抛出StopIteration。生成器有两种类型,一种是生成器表达式(又称为生成器推导),一种是生成器函数。
4. 你如何把字符串的第一个字母大写?
使用 capitalize()函数
5. 如何将字符串转换为全小写?
使用 lower()
6. operators中的is、not和in各有什么功能?
Operators是特殊函数,它们比较一个或多个值并产生相应的结果。
is:当2个操作数为true时返回true(例如:“a”是’a’)
not:返回布尔值的倒数
in:检查某个元素是否存在于某个序列中
7. Python中help()和dir()函数的用法是什么?
- help函数是一个内置函数,用于查看函数或模块用途的详细说明
- dir()函数时python的内置函数,dir()函数不带参数时,返回当前范围内的变量、方法和定义的类型列表,带参数时,返回参数的属性、方法列表
8. 为什么使用* args,** kwargs?
*args是非关键字参数,用于元组,kwargs是关键字参数 (字典) 也就是说args表示任何多个无名参数,然而kwags表示一个一个有着对应关系的关键字参数,
在使用的时候需要注意,*args要在kwags之前,不然会发生语法错误
9. len()函数有什么作用?
返回对象的长度参数可以是序列(字符串str、元组tuple、列表list)或集合(字典dict、集合set或冻结集合frozenset)
10. 在Python中split(),sub(),subn()功能。
split(): 使用正则表达式模式将给定字符串“拆分”到列表中。
sub(): 查找正则表达式模式匹配的所有子字符串,然后用不同的字符串替换它们
subn(): 它类似于sub(),并且还返回新字符串。
11. Python中的函数是什么?
python函数是指组织好的、可重复使用的、用来实现单一或相关联功能的代码段。python函数包含系统中自带的一些函数、第三方函数、以及用户自定义的函数。
12. 什么是lambda函数?
匿名函数lambda:指一类无需定义的标识符(函数名)的函数或子程序。lambda函数可以接收任意多个参数(包括可选参数)并且返回单个表达式的值。
13. Python中的yield用法
- yield函数是python里面的关键字,带有yield的函数相当于一个生成器generator.当你使用一个yield的时候,对应的函数就是一个生成器
- 在python里面类似于return函数,他们主要的区别就是:遇到return会直接返回值,不会执行接下来的语句.但是yield并不是,在本次迭代返回之后,yield函数在下一次迭代时,从上一次迭代遇到的yield后面的代码(下一行)开始执行
14.python递归的最大层数
一般来说是998层 python专门设置的一种机制用来防止无限递归造成Python溢出崩溃, 最大递归次数是可以重新调整的
15.编程用sort进行排序,然后从最后一个元素开始判断
a=[1,2,4,2,4,5,7,10,5,5,7,8,9,0,3]
a.sort()
last=a[-1]
for i in range(len(a)-2,-1,-1):
if last==a[i]:
del a[i]
else:
last=a[i]
print(a)
16.python2和python3的range(100)的区别
- Python2中使用内置函数range(100)返回是列表集合。
- Python3中内置类range(100)返回是可迭代对象
17.一句话解释什么样的语言能够用装饰器?
装饰器的目的是在编程时,相同的代码不要重复写,最好只写异常,然后在其他地方可以直接引用。这样就提高了代码重用率,缩减代码量,同时也有助于提高代码的可读性和可维护下,当需要更改的时候,只需要更改一个地方就可以了。
18.请写出一段Python代码实现删除一个list里面的重复元素
# initializing list
test_list = [1, 3, 5, 6, 3, 5, 6, 1]
print ("The original list is : " + str(test_list))
# using naive method to remove duplicated from list
res = []
for i in test_list:
if i not in res:
res.append(i)
# printing list after removal
print ("The list after removing duplicates : " + str(res))
19.常见的内置函数
- lambda 变量名: 返回值
- replace() #适用对象 : 字符串
- split() #适用对象: 字符串
- join #适用对象: 字符串,列表
20.filter,map,reduce的作用
- map主要作用是计算一个序列或者多个序列进行函数映射之后的值
- filter主要作用是过滤掉序列中不符合函数条件的元素
- reduce是对一个序列进行计算,结果只得到一个值
21.统计函数的执行效率
def cst_time(func, *args, **kwargs):
def wrapper(*args, **kwargs):
start = time.time()
ret = func(*args, **kwargs)
end = time.time()
timestrap = end -start
print('function %s running time is %s'%(func.__name__,timestrap))
return ret
return wrapper
22.Yield关键字和生成器
生成器就是自定义迭代器,本质上就是迭代器。如果函数体内包含yield关键字,那么这个函数在调用的时候并不会执行函数体代码,而返回的结果是一个生成器对象。生成器内置有__iter__()方法和__next__()方法,通过生成器对象调用__next__()方法,就会触发函数体代码的执行。
yield关键字可以用于返回值,但不同于return关键字,函数遇到return就直接结束,而yield可以保持函数运行状态“暂停”函数,用来返回多次值。
23.装饰器的作用和功能
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能
24.介绍一下Python下range()函数的用法?
- range的三种用法:
- 1只有一个参数(小括号中只有一个数)
- 2给了两个参数(小括号中有两个数)
- 3给了三个参数(小括号内有三个数)
25.你知道几种排序,讲一讲你最熟悉的一种?
冒泡排序、选择排序、快速排序、插入排序、堆排序、希尔排序、归并排序
# 冒泡排序
def bubble_sort(alist):
# j为每次遍历需要比较的次数,是逐渐减小的
for j in range(len(alist)-1,0,-1):
for i in range(j):
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1],alist[i]
li = [1,3, 4, 5, 2, 11, 6, 9, 15]
bubble_sort(li)
print(li)
25.是否使用过functools中的函数?其作用是什么?
functools用于高阶函数:指那些作用于函数或者返回其他函数的函数。通常情况下,只要是可以被当做函数调用的对象就是这个模块的目标
26.给定一个任意长度数组,实现一个函数,让所有奇数都在偶数前面,而且奇数升序排列,偶数降序排序,如字符串’1982376455’,变成’1355798642’
# 方法一
def func1(l):
if isinstance(l, str):
l = [int(i) for i in l]
l.sort(reverse=True)
for i in range(len(l)):
if l[i] % 2 > 0:
l.insert(0, l.pop(i))
print(''.join(str(e) for e in l))
# 方法二
def func2(l):
print("".join(sorted(l, key=lambda x: int(x) % 2 == 0 and 20 - int(x) or int(x))))
27.什么是Hash(散列函数)?
python中hash是一个算法函数,又称哈希算法;主要指把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值,能够应用于“密码”、“文件完整性校验”、“数字签名”等方向。
28.python函数重载机制?
重载主要是为了解决两个问题。 1。可变参数类型。 2。可变参数个数。
另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。
对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。
那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。
29.编写函数的4个原则
- 原则一:函数设计要尽量短小,嵌套层次不宜过深。
- 函数中需要用到if;elif;while;for等循环语句的地方,尽量不要嵌套过深,最好能控制在3层以内。
- 原则二:参数个数不宜太多。
- 函数申明应该做到合理、简单、易于使用。除了函数名能够正确反映其答题功能外,参数的设计也应该简洁明了,参数个数不宜过多。
- 原则三:函数参数设计应该考虑向下兼容。
- 通过加入默认参数避免退化,做到向下兼容
- 原则四:一个函数只做一件事情,尽量保证函数语句粒度的一致性。
- 要保证一个函数只做一件事,就要尽量保证抽象层级的一致性,所有的语句尽量在一个粒度上。同时在一个函数中处理多件事情也不利于代码的重用。
30.函数调用参数的传递方式是值传递还是引用传递?
- Python的参数传递有:位置参数、默认参数、可变参数、关键字参数。 函数的传值到底是值传递还是引用传递、要分情况:
- 不可变参数用值传递:像整数和字符串这样的不可变对象,是通过拷贝进行传递的,因为你无论如何都 不可能在原处改变不可变对象。
- 可变参数是引用传递:比如像列表,字典这样的对象是通过引用传递、和C语言里面的用指针传递数组 很相似,可变对象能在函数内部改变。
31.使用Python内置的filter()方法来过滤
1.filter()函数的功能是:根据指定的条件过滤一个序列中不符合条件的元素。
2.filter()函数的语法为:filter(function,iterable),该方法接收两个参数,第一个参数为函数,函数的返回值为True或False,第二个参数为序列,序列的每个元素作为参数依次传递给函数,判断返回值为True或False,最后将返回True的元素放到新列表中。
32.回调函数,如何通信的?
回调函数是把函数的指针(地址)作为参数传递给另一个函数,将整个函数当作一个对象,赋值给调用的函数。
33.map(lambda x:x*x,[y for y in range(3)])的输出?
[0, 1, 4]
34.hasattr() getattr() setattr() 函数使用详解?
- hasattr(object,name) 函数
- 判断一个对象里面是否有 name 属性或者 name 方法,返回 bool 值,如果有 name 属性(方法)则返回 True ,否则返回 False 。注意: name 需要使用引号括起来。
- getattr(object,name[,default]) 函数
- 获取对象 object 的属性或者方法,若存在则打印出来;若不存在,则打印默认值,默认值可选。注意:如果返回的是对象的方法,那么打印的结果是方法的内存地址。如果需要运行这个方法,那么可以在后面添加括号 () 。
- setattr(object,name,values) 函数
- 给对象的属性赋值,若属性不存在,则先创建再赋值。
35.一句话解决阶乘函数?
reduce(lambda x,y : x*y,range(1,n+1))
36.递归函数停止的条件?
递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是return,,返回终止递归。
终止的条件:判断递归的次数是否达到某一限定值,判断运算的结果是否达到某个范围等,根据设计的目的来选择
37.python写一个匿名函数求两个数的和
lambda x,y:x+y
38.函数装饰器有什么作用?
可以抽象出一些与函数功能无关的重复代码,通过@符号加在其他函数上,增加额外的功能。
39.怎么移除一个字符串中的前导空格?
使用 lstrip()函数
40.在Python中怎样获取输入?
使用input()函数
41.如何检查字符串中所有的字符都为字母数字?
str.isalnum() 所有字符都是数字或者字母
42.什么是函数?
函数是指组织好的、可重复使用的、用来实现单一或相关联功能的代码段,Python函数包含系统中自带的一些函数、第三方函数以及用户自定义的函数。
43.什么是递归?
是指一段程序直接或者间接调用自身的一种方法,通过这种形式执行需要进行一些固定步骤的许多操作,它可以把一个复杂并且庞大的问题简单化,通过专注于解决它分化出来的小问题从而解决大问题,从而大大减少我们的代码量,是提高我们编码效率的很好方法。
44.请说说生成器和迭代器之间的区别
1.迭代器是访问容器的一种方式,也就是说容器已经出现。我们是从已有元素拓印出一份副本,只为我们此次迭代使用。而生成器则是,而生成器则是自己生成元素的。
2.在用法上生成器只需要简单函数写法,配合yield就能实现。而迭代器真正开发中很难使用到。我们可以把生成器看做,python给我们提供的特殊接口实现的迭代器。
3.生成器是只能遍历一次的。
45.函数zip()的是干嘛的?
zip():该函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。
#构造字典:
x = ['a', 'b', 'c']
y = ['x', 'y', 'z']
z = zip(x, y)
d = dict(z)
print(d)
'''输出结果:
{'a': 'x', 'b': 'y', 'c': 'z'}
'''
46. 简述any()和all()方法
all()函数:全真为真,一假为假
any()函数:一真为真,全假为假
47.如何计算一个字符串的长度?
使用内置函数len
48.列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]
def f(x):
return x**2
res = map(f, [1, 2, 3, 4, 5])
print([i for i in res if i > 10])
49.python中断言方法举例
assert()方法,断言成功,则程序继续执行,断言失败,则程序报错:
a = 3;assert(a>1) print("断言成功,程序继续向下执行")
b=4;assert(b>7);print("断言失败程序报错")
50.s = “ajldjlajfdljfddd”,去重并从小到大排序输出"adfjl"
s = "ajldjlajfdljfddd"
a = set(s)
b= ''.join(a)
print(b)
d = sorted(b)
print(''.join(d))
51.用lambda函数实现两个数相乘
lambda x,y:x*y
52.filter方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = filter(lambda x: x % 2 != 0, a)
for i in b:
print(i)
53.log日志中,我们需要用时间戳记录error,warning等的发生时间,请用datetime模块打印当前时间戳 “2018-04-01 11:38:54”
import datetime
print(datetime.datetime.now())
print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) #当前时间戳
a = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) + ' 星期' + str(datetime.datetime.now().isoweekday())
print(a)
'''
输出结果:
2022-12-18 11:26:46.313971
2022-12-18 11:26:46
2022-12-18 11:26:46 星期7
'''
54.求三个方法打印结果
1,str()和repr()
str()目的是可读性,repr()目的是使结果清晰、无歧义,两者没有多大的区别
2,建议使用以下.format()的格式打印:print (‘A is {} and B is {}’.format(‘a’, ‘b’))
3,可以在大括号内使用数字控制输出位置:print (‘A is {1} and B is {0}’.format(‘a’, ‘b’))
4,输出格式控制,ascii()用‘!a’,str()用’!s’,repr()用’!r‘:import math print (‘The value of PI is {!r}’.format(math.pi))
5,使用’:’更有效地控制输出格式
55.a = " hehheh ",去除收尾空格
a="aaaa. "
a.strip()
"""aaaa."""
56.统计字符串中某字符出现次数
a = "hello world"
b="o"
c=a.count(b)
print(c)#2
57.字符串转化大小写
upper():将字符串中所有小写字符转换为大写字符。
lower():将字符串中所有大写字符转换为小写字符。
swapcase():将字符串中小写转换为大写,大写转换为小写。
title():将每个单词的首字母大写。
capitalize():将字符串的第一个字符转换为大写,也就是行首字母大写。
58.请将[i for i in range(3)]改成生成器
( i for i in range(3))
59.编程用sort进行排序,然后从最后一个元素开始判断
b = [1,4,2,5,6,4,3,6,8,4,9,5]
b.sort() # 从小到大排序
last = b[-1]
for i in range(len(b)-2,-1,-1): # 去重
if last == b[i]:
del b[i]
else:
last = b[i]
print(b)
(四) 面向对象
1.多继承写法以及继承顺序问题
python 中继承方式有两种:深度优先、广度优先。
查找顺序
(1)本地优先,自己定义或重写的方法优先。本地没有的,按照继承列表,从左往右查找;
(2)单调性,所有子类,也要满足查找顺序。也就是说 A 继承 B C,A 会先找 B 再找 C。但是在 A 查找之前,B 如果有多个继承,那么它先得按查找顺序查找。
2.析构函数
python之中的析构函数是起到和构造函数相反作用的,构造函数是赋值和定义。那么析构函数的作用就是在一个对象的生命周期,也就是它已经被使用过在接下来的程序之中不会在使用的时候就会调用析构函数来将其给清除掉。
所以析构函数的实际作用就是当程序之中临时变量使用完毕、对象没有调用、变量一直占据内存的这些情况之下就将它们给销毁掉。这样就能将程序所占据的内存空间给减少了,也能提交程序执行速度。
3.继承,在执行析构函数时,先执行父类的,还是先执行子类的?
- 父类先构造,然后才是子类
- 子类先析构,然后才是父类
- 构造子类时,会先调用父类的构造函数,析构子类时,也会调用父类的析构函数
4.继承时,所有的方法都会被继承吗?
不会,比如构造函数和析构函数,它们不能被继承。
5.Python中的self关键字
self代表类的实例。通过使用 "self "关键字,我们可以在python中访问类的属性和方法。它将属性与给定的参数绑定在一起。
6.多态
多态性是指采取多种形式的能力。因此,例如,如果父类具有一个名为 ABC 的方法, 那么子类也可以具有一个具有相同名称和参数的 ABC 方法。Python 允许多态。
7.面向对象深度优先和广度优先是什么?
在子类继承多个父类时,属性查找方式分深度优先和广度优先两种。
当类是经典类时,多继承情况下,在要查找属性不存在时,会按照深度优先方式查找下去。
当类是新式类时,多继承情况下,在要查找属性不存在时,会按照广度优先方式查找下去。
8. 列举面向对象中带双下划线的魔术方法?
#__len__:len() 调用对象会返回 __len__ 方法 return 的值,必须返回 integer
class A:
def __len__(self):
return 4
a = A()
print(len(a))
# 输出结果
4
# __eq__:定义等于号的行为:x == y
class A:
def __init__(self):
self.a = 1
self.b = 2
def __eq__(self, obj):
print("call eq method.")
if self.a == obj.a and self.b == obj.b:
return True
a = A()
b = A()
# 实例对象有 == 行为时,自动调用 __eq__() 方法
print(a == b)
# 输出结果
call eq method.
True
9.列举面向对象中的特殊成员以及应用场景
# 1. __doc__ 描述类的信息
class Foo(object):
# 单引号和双引号都可以
"""这里描述类的信息"""
def func(self):
pass
print(Foo.__doc__)
# __call__方法的执行是由对象加括号触发的,即:对象()或者 类()()
class Foo(object):
def __call__(self, *args, **kwargs):
print("running call", args, kwargs)
foo = Foo()
foo(1, 2, 3, name = "UserPython")
Foo()(1, 2, 3, name = "UserPython")
# __dict__ 查看类或对象中的所有成员
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
foo = Foo("UserPython", 17)
print(Foo.__dict__) #打印类里的所有属性,不包括实例属性
print(foo.__dict__) #打印所有实例属性,不包括类属性
# __str__ 如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "<obj:%s>" % self.name
foo = Foo("UserPython", 17)
print(foo) #>>><obj:UserPython>
10. 用尽量多的方法实现单例模式。
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。简单的说就是保证只有一个对象,节约内存空间,我们可以通过修改类中的 __new__方法,实现一个简单的单例类。
#方法一:模块单例
#Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。
#foo1.py
class Singleton(object):
def foo(self):
pass
singleton = Singleton()
#foo.py
from foo1 import singleton
#方法二:静态变量方法
#先执行了类的__new__方法(我们没写时,默认调用object.__new__),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式。
class Singleton(object):
def __new__(cls,a):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls)
return cls._instance
def __init__(self,a):
self.a = a
def aa(self):
print(self.a)
a = Singleton("a")
#方法三:元类方法:此方法是在__new__方法的更上层对实例化过程进行控制。
#原理:执行元类的 元类的__new__方法和__init__方法用来实例化类对象,__call__ 方法用来对实例化的对象的实例即类的对象进行控制。__call__方法会调用实例类的 __new__方法,用于创建对象。返回对象给__call__方法,然后调用类对象的 __init__方法,用于对对象初始化。
class Singleton1(type):
def __init__(self, *args, **kwargs):
self.__instance = None
super(Singleton1,self).__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton1,self).__call__(*args, **kwargs)
return self.__instance
class Singleton2(type):
_inst = {}
def __call__(cls, *args, **kwargs):
print(cls)
if cls not in cls._inst:
cls._inst[cls] = super(Singleton2, cls).__call__(*args)
return cls._inst[cls]
class C(metaclass=Singleton1):
pass
#方法四:装饰器
#原理:装饰器用来控制类调用__call__方法。
def singleton(cls, *args, **kw):
instance = {}
def _singleton(args):
if cls not in instance:
instance[cls] = cls(*args, **kw)
return instance[cls]
return _singleton
@singleton
class A:
pass
11.Python有OOps概念吗?
Python是一种面向对象的编程语言。这意味着可以通过创建对象模型在python中解决任何程序。但是,Python既可以作为过程语言,也可以作为结构语言。
12. Python中的闭包是什么?
- 如果在一个外函数中定义了一个内函数,内函数中引用了外函数的临时变量,并且外函数的返回值是对内函数的引用。这样就构成了闭包
13.谈谈你对面向对象的理解?
面向对象 ( Object Oriented ) 是将现实问题构建关系,然后抽象成 类 ( class ),给类定义和方法后,再将类实例化成 实例 ( instance ) ,通过访问实例的属性和调用方法来进行使用。在不同的语言中,的定义范围不同。在 Python 中“类”和“类的实例”都称为 对象 ( Object ),因为 Python 的类是更顶级的 type 实例化后的对象,也就是常说的“Python 里万物皆对象”;而在 Java 等静态语言中,一般把类的实例称为对象。
14.面向对象中怎么实现只读属性?
方式1:定义私有属性,定义私有属性-属性前置双下划线实现,通过共有方法提供一个读取数据的接口
方式2:@property 只读,如果需要修改,再加一个@属性名.setter
15.如何在一个函数内部修改全局变量
在函数内修改全局变量需要使用global关键字