Python 面试题学习
Python的函数参数传递
- 在Python中,strings,tuples=('abc',123,2.2,'join),numbers 是不可更改的对象。
- list=['abc',123,2.23,'john'],dict等则是可以修改的对象。
示例:
a = 1
def fun(a):
a = 2
fun(a)
print a #
a = []
def fun(a):
a.append(1)
fun(a)
print a # [1]
@staticmethod和@classmethod
- python有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法。
def foo(x):
print "executing foo(%s)"%(x) class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x) @classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x) @staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x a=A()
这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x)
,这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self, x)
,为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)
(其实是foo(a, x)
).类方法一样,只不过它传递的是类而不是实例,A.class_foo(x)
.注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.
对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)
或者A.static_foo(x)
来调用.
类变量和实例变量???????
class Person:
name=[] p1=Person()
p2=Person()
p1.name.append(1)
print p1.name # [1]
print p2.name # [1]
print Person.name # [1]
class Test(object):
num_of_instance = 0
def __init__(self, name):
self.name = name
Test.num_of_instance += 1 if __name__ == '__main__':
print Test.num_of_instance
t1 = Test('jack')
print Test.num_of_instance
t2 = Test('lucy')
print t1.name , t1.num_of_instance
print t2.name , t2.num_of_instance
Python自省
- 自省(让对象告诉我们他是什么),用于实现在运行时获取未知对象的信息。
访问对象属性:
- hasattr(obj, attr) 这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。
- getattr(obj, attr) 调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。
- setattr(obj, attr, val) 调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。
推导式
- 列表推导式(list) 提供一种方便的列表创建方法,返回一个列表。格式:用中括号括起来,中间用for语句,后面跟if语句用作判读,满足条件的传到for语句前面用作构建先的列表.
>>> li=[i*2 for i in range(10) if i % 2 == 0]
>>> print (li)
[0, 4, 8, 12, 16]
>>>
- 字典推导式(dic) 格式:d = {key: value for (key, value) in iterable}
>>> mca={"a":1, "b":2, "c":3, "d":4}
>>> dicts={v:k for k,v in mca.items()}
>>> print (dicts)
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
>>>
- 集合推导式(跟列表推导式的区别:1.不使用中括号,使用大括号;2.结果中无重复;3.结果是一个set()集合,集合里面是一个序列)
>>> squared={i*2 for i in [1,1,2]}
>>> print (squared)
set([2, 4])
>>>
Python中单下划线和双下划线??????
_foo
:
- 在一个模块中以单下划线开头的变量和函数被默认当作内部函数,如果使用 from a_module import * 导入时,这部分变量和函数不会被导入。不过值得注意的是,如果使用 import a_module 这样导入模块,仍然可以用 a_module._some_var 这样的形式访问到这样的对象。
- 一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.
__foo
:
- 这个有真正的意义:解析器用
_classname__foo
来代替这个名字,以区别和其他类相同的命名. - 双下划线开头的命名形式在 Python 的类成员中使用表示名字改编 (Name Mangling),即如果有一 Test 类里有一成员 __x,那么 dir(Test) 时会看到 _Test__x 而非 __x。这是为了避免该成员的名称与子类中的名称冲突。但要注意这要求该名称末尾没有下划线.
__foo__
:
- 一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突.
- 双下划线开头双下划线结尾的是一些 Python 的“魔术”对象,如类成员的 __init__、__del__、__add__、__getitem__ 等,以及全局的 __file__、__name__ 等。 Python 官方推荐永远不要将这样的命名方式应用于自己的变量或函数,而是按照文档说明来使用。
>>> class MyClass():
... def __init__(self):
... self.__superprivate = "Hello"
... self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
字符串格式化:%和.format
对于%
最烦人的是它无法同时传递一个变量和元组.
name = (1,2,3)
print ("hi there %s" % name) # 报错
print ("hi there %s" % (name,)) # 提供一个单元素的数组而不是一个参数
.format通过{}和.来代替%
- 通过位置:
print ("{0},{1}".format('lujf',123))
- 通过关键字参数
print ("{name},{age}".format(name='lujf',age=23))
- 通过对象属性???????
class Person:
def __init__(self,name,age):
self.name,self.age = name,age
def __str__(self):
return 'This guy is {self.name},is {self.age} old'.format(self=self)
- 通过下标
p = ['lujf',23]
print ('{0[0]},{0[1]}'.format(p))
迭代器和生成器
迭代器:
- 迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束。迭代器只能往前不会后退。
- 对于原生支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
- 迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等
迭代器更大的功劳是提供了一个统一的访问集合的接口,只要定义了__iter__()方法对象,就可以使用迭代器访问。
迭代器有两个基本的方法
- next方法:返回迭代器的下一个元素
- __iter__方法:返回迭代器对象本身
class Fab(object):
def __init__(self, max):
self.max = max
self.n, self.a, self.b = 0, 0, 1 def __iter__(self):
return self def next(self):
if self.n < self.max:
r = self.b
self.a, self.b = self.b, self.a + self.b
self.n = self.n + 1
return r
raise StopIteration() #python处理迭代器越界是抛出StopIteration异常
使用迭代器:
- 使用内建的工厂函数iter(iterable)可以获取迭代器对象:
>>> lst = range(5)
>>> it = iter(lst)
>>> it
<listiterator object at 0x01A63110>
- 使用next()方法可以访问下一个元素:
>>> it.next()
0
>>> it.next()
1
>>> it.next()
2
事实上,因为迭代器如此普遍,python专门为for关键字做了迭代器的语法糖。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。
生成器:
- 带有 yield 的函数在 Python 中被称之为 generator(生成器)。
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
- return的作用
在一个生成器中,如果没有return,则默认执行到函数完毕;如果遇到return,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。
*args and **kwargs
如果我们不确定往一个函数中传入多少参数,或者我们希望以元组(tuple)或者列表(list)的形式传参数的时候,我们可以使用*args 。当函数的参数前面有一个星号*号的时候表示这是一个可变的位置参数。星号*把序列或者集合解包(unpack)成位置参数。
def print_everything(*args):
for count, thing in enumerate(args): #enumerate()为python内置函数
print('{},{}'.format(count, thing))
print_everything('apple', 'banana', 'cabbage') #输出
#0,apple
#1,banana
#2,cabbage
如果我们不知道往函数中传递多少个关键词参数或者想传入字典的值作为关键词参数的时候我们可以使用**kwargs。两个星号**把字典解包成关键词参数。
def table_things(**kwargs):
for name, value in kwargs.items(): #Python 字典(Dictionary) items()方法
print ('{} = {}'.format(name, value))
table_things(apple = 'fruit', cabbage = 'vegetable') #输出
#apple = fruit
#cabbage = vegetable
面向切面编程AOP和装饰器
# -*- coding: utf-8 -*-
import time def foo():
'in foo()' # 定义一个计时器,传入一个,并返回另一个附加了计时功能的方法
def timeit(func):
# 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装
def wrapper():
start = time.clock()
func()
end = time.clock()
print ('used:', end - start) # 将包装后的函数返回
return wrapper foo = timeit(foo)
foo()
在在这个例子中,函数进入和退出时需要计 时,这被称为一个横切面(Aspect),这种编程方式被称为面向切面的编程(Aspect-Oriented Programming)。
Python重载(python 自然就不需要函数重载)
函数重载主要是为了解决两个问题:
- 可变参数类型(因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。)
- 可变参数个数(缺省参数)
示例:
def f(a,L=[]):
L.append(a)
print L
f(1) #[1]
f(2) #[1,2]
缺省参数在python中是与函数绑定在一起的。
也就是说,一个函数中定义了一个缺省参数,那么这个参数会随着被调用而改变。(一个坑)
在一次调用中改变了缺省参数的值,可能会影响到这个函数的另外一次调用。
__new__ 和__init__的区别
lass Book(object):
def __new__(cls, title):
print'__new__'
return super(Book, cls).__new__(cls) def __init__(self, title):
print'__init__'
super(Book, self).__init__(self)
self.title = title b = Book('The Django Book')
print(b.title)
官方文档:
- __init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值。
- __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法
也就是,__new__在__init__之前被调用,__new__的返回值(实例)将传递给__init__方法的第一个参数,然后__init__给这个实例设置一些参数。
Python中的作用域
- Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。
- 当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)
GIL线程全局锁
- 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.
协程
简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.
lambda函数
- 简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。
map( lambda x: x*x, [y for y in range(10)] )
def sq(x):
return x * x map(sq, [y for y in range(10)])
- map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。
Python 引用和copy(),deepcopy()的区别
Python中对象之间的赋值是按引用传递的,如果要拷贝对象需要使用标准模板中的copy
- 赋值:Python中对象之间的赋值是按引用传递的
- copy.copy:浅拷贝,只拷贝父对象,不拷贝父对象的子对象。
- copy.deepcopy:深拷贝,拷贝父对象和子对象。
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象 b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝 a.append(5) #修改对象a
a[4].append('c') #修改对象a中的['a', 'b']数组对象 print ('a = ', a)
print ('b = ', b)
print ('c = ', c)
print ('d = ', d) 输出结果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
注意: 浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。
Python 的 is 和 ==
python中的对象包含三要素:id、type、value
其中 id 用来唯一标识一个对象。
- is是对比地址
- ==是对比值
read,readline 和 readlines
- read 读取整个文件。
- readline 读取下一行,使用生成器方法。
- readlines 读取整个文件到一个迭代器以供我们遍历。
f = open('poem.txt','r')
a = f.read()
print (a)
f = open('poem.txt','r')
result = list()
for line in open('poem.txt'):
line = f.readline()
print (line)
result.append(line)
print (result)
f.close()
f = open('poem.txt', 'r') #以读方式打开文件
result = list()
for line in f.readlines(): #依次读取每行
line = line.strip() #去掉每行头尾空白
if not len(line) or line.startswith('#'): #判断是否是空行或注释行
continue #是的话,跳过不处理
result.append(line) #保存
result.sort() #排序结果
print result
Python的垃圾回收机制 (garbage collection)
Python中的垃圾回收是以引用计数为主,标记-清除和分代收集为辅。
- 引用计数:Python在内存中存储每个对象的引用计数,如果计数变成0,该对象就会消失,分配给该对象的内存就会释放出来。
- 标记-清除:一些容器对象,比如list、dict、tuple,instance等可能会出现引用循环,对于这些循环,垃圾回收器会定时回收这些循环(对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边)。
- 分代收集:Python把内存根据对象存活时间划分为三代,对象创建之后,垃圾回收器会分配它们所属的代。每个对象都会被分配一个代,而被分配更年轻的代是被优先处理的,因此越晚创建的对象越容易被回收。
说明os,sys模块的不同
os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口。
sys模块负责程序与Python解释器的交互,提供了一系列的函数和变量用户操作Python运行时的环境。
lambda表达式
简单来说,lambda表达式通常是当你需要使用一个函数,但是又不想费脑袋去命名一个函数的时候使用,也就是通常所说的匿名函数。
#示例
f = lambda x,y,z: x + y + z
print(f(1,2,3))
L = {'f1':(lambda x,y: x**2 + y**2),
'f2':(lambda x,y: x**3 + y**3),
'f3':(lambda x,y: x**4 + y**3)}
print(L['f2'](3,2))
Python 面试题学习的更多相关文章
- Python面试题整理-更新中
几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路 ...
- 震惊!几道Python 理论面试题,Python面试题No18
本面试题题库,由公号:非本科程序员 整理发布 第1题: 简述解释型和编译型编程语言? 解释型语言编写的程序不需要编译,在执行的时候,专门有一个解释器能够将VB语言翻译成机器语言,每个语句都是执行的时候 ...
- 面试前赶紧看了5道Python Web面试题,Python面试题No17
目录 本面试题题库,由公号:非本科程序员 整理发布 第1题: Flask中的请求上下文和应用上下文是什么? 第2题:django中间件的使用? 第3题: django开发中数据做过什么优化? 第4题: ...
- 千万不要错过这几道Python面试题,Python面试题No16
第1题: python下多线程的限制以及多进程中传递参数的方式? python多线程有个全局解释器锁(global interpreter lock),简称GIL,这个GIL并不是python的特性, ...
- Python 装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...
- Python面试题 —— 获取列表中位数
中位数是一个可将数值集合划分为相等的上下两部分的一个数值.如果列表数据的个数是奇数,则列表中间那个数据就是列表数据的中位数:如果列表数据的个数是偶数,则列表中间那2个数据的算术平均值就是列表数据的中位 ...
- 【Todo】Python面试题分析记录(修饰器等)
首先,看这一段代码: class A(object): x = 1 gen = (lambda t: (t for _ in xrange(10)))(x) if __name__ == '__mai ...
- Requests:Python HTTP Module学习笔记(一)(转)
Requests:Python HTTP Module学习笔记(一) 在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用并且功能强大,完全可以代替python的标 ...
- 从Theano到Lasagne:基于Python的深度学习的框架和库
从Theano到Lasagne:基于Python的深度学习的框架和库 摘要:最近,深度神经网络以“Deep Dreams”形式在网站中如雨后春笋般出现,或是像谷歌研究原创论文中描述的那样:Incept ...
随机推荐
- RabbitMQ 运转流程
生产者发送消息 1.生产者连接到 RabbitMQ Broker,建立一个连接(Connection),开启一个信道(Channel) 2.生产者声明一个交换器,并设置相关属性,比如交换机类型.是否持 ...
- struts的问题
将SSH框架进行整合的时候,将三者的jar包加入到lib下面,然后测试struts,结果页面显示不出来报404错误,可是路径没有问题 找到罪魁祸首是:原因两个:(1)在未用到spring的时候,先不要 ...
- 实验一:使用ADO.NET方式读数据
第一步:创建Asp.net应用程序 在VS中,点击文件->新建->项目,按如图方式选择并输入: 第二步:新建产品浏览网页窗体Listing.aspx: 在项目SportsStoreEx上点 ...
- Docker Swarm 服务编排之命令
一.简介 Docker有个编排工具docker-compose,可以将组成某个应该的多个docker容器编排在一起,同时管理.同样在Swarm集群中,可以使用docker stack 将一组相关联的服 ...
- select标签和多行文本标签
一.多行文本textarea <form> <div> <textarea name="more"></textarea> < ...
- 怎么在.net里面解析JSON文件?
我在网上搜了好多的文章,讲了很多的方法.但是无一例外的都看不懂...可能是因为我在这方面是个白痴吧... 所幸的是,我搜到了一个博客,写的很是清晰,比我之前看的大片文章写的好多了,在这里:http:/ ...
- mongo转换副本集
本文介绍如何把独立的mongo实例转换成包含3个成员的副本集.开发和测试使用独立实例,生产使用副本集.如何安装独立的mongo实例本文不再赘述. 如果在部署副本集时还没有安装mongo实例,可以查看部 ...
- mongodb3.6集群搭建:分片集群认证
上篇集群已经创建,现在加入认证. 1. 生成密钥文件每个服务器上创建路径: mkdir -p /var/lib/mongo/auth 生成64字节的密钥文件openssl rand -base64 6 ...
- Spring和springmvc父子容器注解扫描问题详解
一.Spring容器和springmvc容器的关系如下图所示: Spring和springmvc和作为两个独立的容器,会把扫描到的注解对象分别放到两个不同的容器中, Springmvc容器是spr ...
- Dubbo学习笔记3:Dubbo管理控制台与监控中心的搭建
Dubbo源码下载与编译 本文来讲下如何在Dubbo源码编译后,得到用于搭建管理控制台的war包和监控平台的jar包. 首先需要到Github上下载Dubbo的源码,解压后如下: 在dubbo-2.5 ...