1、下面代码的输出结果将是什么?
list = ['a','b','c','d','e']
print(list[10:])
代码将输出[],不会产生IndexError错误,就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,尝试获取list[10]和之后的成员,会导致IndexError。然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。这成为特别让人恶心的疑难杂症,因为运行的时候没有错误产生,导致Bug很难被追踪到。
2、python新式类和经典类的区别?
a. 在python里凡是继承了object的类,都是新式类 b. Python3里只有新式类 c. Python2里面继承object的是新式类,没有写父类的是经典类 d. 经典类目前在Python里基本没有应用
3、python中内置的数据结构有几种?
a. 整型 int、 长整型 long、浮点型 float、 复数 complex b. 字符串 str、 列表list、 元祖tuple c. 字典 dict 、 集合 set
4、python如何实现单例模式?请写出两种实现方式?
第一种方法:使用装饰器
def singleton(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Foo(object):
pass
foo1 = Foo()
foo2 = Foo()
print foo1 is foo2 #True
第二种方法:使用基类 New 是真正创建实例对象的方法,所以重写基类的new 方法,以此保证创建对象的时候只生成一个实例
class Singleton(object):
def __new__(cls,*args,**kwargs):
if not hasattr(cls,'_instance'):
cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
return cls._instance
class Foo(Singleton):
pass
foo1 = Foo()
foo2 = Foo()
print foo1 is foo2 #True
第三种方法:元类,元类是用于创建类对象的类,类对象创建实例对象时一定要调用call方法,因此在调用call时候保证始终只创建一个实例即可,type是python的元类
class Singleton(type):
def __call__(cls,*args,**kwargs):
if not hasattr(cls,'_instance'):
cls._instance = super(Singleton,cls).__call__(*args,**kwargs)
return cls._instance
class Foo(object):
__metaclass__ = Singleton
foo1 = Foo()
foo2 = Foo()
print foo1 is foo2 #True
5、对装饰器的理解,并写出一个计时器记录方法执行性能的装饰器?
装饰器本质上是一个python函数,它可以在让其他函数在不需要做任何代码的变动的前提下增加额外的功能。装饰器的返回值也是一个函数的对象,它经常用于有切面需求的场景。比如:插入日志,性能测试,事务处理,缓存。权限的校验等场景,有了装饰器就可以抽离出大量的与函数功能本身无关的雷同代码并发并继续使用。
import time
def timeit(func):
def wrapper():
start = time.clock()
func()
end = time.clock()
print('used:',end-start)
return wrapper
@timeit
def foo():
print('in foo()'foo())
6、解释以下什么是闭包?
在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包。
7、生成器,迭代器的区别?
迭代器是一个更抽象的概念,任何对象,如果它的类有next方法和iter方法返回自己本身,对于string,list,dict,tuple等这类容器对象,使用for循环遍历是很方便的,在后台for语句对容器对象调用iter()函数,iter()是python的内置函数,iter()会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内元素,next()也是python的内置函数,在没有后续元素时,next()会抛出一个StopIteration异常。 生成器(Generator)是创建迭代器的简单而强大的工具。它们写起来就像是正规的函数,只是在需要返回数据的时候使用yield语句。每次next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值) 区别: 生成器能做到迭代器能做的所有事,而且因为自动创建iter()和next()方法,生成器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出StopIteration异常。
8、Python list列表删除元素(3种方法)
在列表中删除元素,主要分为以下 3 种应用场景:
根据目标元素所在位置的索引值进行删除,可使用 del 语句;(索引可以是范围)
根据元素的值进行删除,可使用列表(list类型)提供的 remove() 方法;remove() 方法会删除第一个和指定值相同的元素,如果找不到该元素,该方法将会引发 ValueError 错误。
将列表中所有元素全部删除,可使用列表(list类型)提供的 clear() 方法。
9、可变类型和不可变类型
可变对象创建后可改变但地址不会改变,即变量指向的还是原来的变量;不可变对象创建之后便不能改变,如果改变则会指向一个新的对象。
不可变:Number(数字)、String(字符串)、Tuple(元组)。
可以变:Set(集合)、List(列表)、Dictionary(字典)。
10、super函数的具体用法和场景
super() 函数用于调用下一个父类(超类)并返回该父类实例的方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
11、Python中类方法、类实例方法、静态方法有何区别?
实例方法
定义:第一个参数必须是实例对象,该参数名一般约定为“self”,通过它来传递实例的属性和方法(也可以传类的属性和方法);
调用:只能由实例对象调用。
类方法
定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);
调用:实例对象和类对象都可以调用。
静态方法
定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;
调用:实例对象和类对象都可以调用。
12、python内存管理与垃圾回收机制
1)引用计数。是指每一个对象别引用一次,将标记引用计数加1,而减少一次引用将计数减1,增加引用计数的情况包括创建对象,别名赋值,list,dict等容器添加对象,作为参数传入等,减少引用次数包括销毁对象,变量赋值指向其他对象,容器一出或者容器销毁,离开作用域等,当引用计数为0,将被自动回收到内存。sys.getrefcount能够获取当前对象的引用次数(注意会比实际多一次,是因为这个函数本身调用会引用一次也记录到其中了)。
2)清除和标记。对于存在循环引用的类型,比如类,list,dict等容器每一次创建都会标记到链表中,在回收的时候从gcroot开始去寻找那些能直接或者间接到达的引用,不可达到的就是循环引用,这时候能清除掉(重写__del__也不能达到,这个需要手动回收)。
3)分代回收。分代回收策略是那些经常用的不会回收的放到二代,在次检测的时候放到三代中,这里有一个回收阈值。
13、函数装饰器有什么作用?
装饰器本质上是一个 Python 函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
14、简述浏览器通过 WSGI 请求动态资源的过程?
1、发送 http 请求动态资源给 web 服务器
2、web 服务器收到请求后通过 WSGI 调用一个属性给应用程序框架
3、应用程序框架通过引用 WSGI 调用 web 服务器的方法,设置返回的状态和头信息。
4、调用后返回,此时 web 服务器保存了刚刚设置的信息
5、应用程序框架查询数据库,生成动态页面的 body 的信息
6、把生成的 body 信息返回给 web 服务器
7、web 服务器吧数据返回给浏览器