python基础
1 Python类中的方法类型
在Python类中有四种方法类型,分别是实例方法、静态方法、类方法和普通方法。
- 实例方法(即对象方法):需要实例化对象之后才能调用,接受的第一个参数
self
就是对象本身,必须使用实例化对象才可以访问,不能通过类直接访问.
- 静态方法:可以通过类名直接调用,不需要传递
self
和cls
;也可以在实例化对象后调用
- 类方法:可以通过类名调用,也可以在实例化对象后调用。类方法需要一个
cls
参数,在调用时自动传递
- 普通方法:和正常的函数一样,可以直接调用,但是在类中不建议写这种方法
测试示例:
class A(object):
# 实例方法(对象方法),需要接收一个形参self,即实例对象自己
def instance_method_fun(self):
print("instance_method_fun,self is {}".format(self))
# 类方法,需要接收一个形参cls,在调用时自动传递
@classmethod
def classmethod_fun(cls):
print("classmethod_fun, cls is {}".format(cls))
# 静态方法
@staticmethod
def staticmethod_fun():
print("staticmethod_fun")
# 普通方法
def common_fun():
print("common_fun")
# A.instance_method_fun() # 报错:TypeError: instance_method_fun() missing 1 required positional argument: 'self'
A.classmethod_fun() # 输出:classmethod_fun, cls is <class '__main__.A'>
A.staticmethod_fun() # 输出:staticmethod_fun
A.common_fun() # 输出:common_fun (不建议在类中写普通方法)
a = A()
a.instance_method_fun() # 输出:instance_method_fun,self is <__main__.A object at 0x0000018674E1E588>
a.classmethod_fun()# 输出:classmethod_fun, cls is <class '__main__.A'>
a.staticmethod_fun()# 输出:staticmethod_fun
2 Python的参数传递类型
Python中的参数传递是引用传递,即我们可以对传递对象的属性,但是不能改变传递对象的指针。在Python中有一些对象的值是不可以更改的,例如int,float类型。如果在函数体内修改了不可修改对象的值,Python会在一个新的内存地址上创建一个变量,而不是使用原来的变量;如果在函数体内修改一个可修改对象的值,则在原内存地址操作。
例如:
def fun1(x):
x = x + 1
print("x:{},id(x):{}".format(x,id(x)))
def fun2(x):
print("b:{},id(b):{}".format(b,id(b)))
x.append(2)
print("b:{},id(b):{}".format(b,id(b)))
a = 1
print("a:{},id(a):{}".format(a,id(a)))
fun1(a)
print("a:{},id(a):{}".format(a,id(a)))
b = []
print("b:{},id(b):{}".format(b,id(b)))
fun2(b)
print("b:{},id(b):{}".format(b,id(b)))
# 输出为:
# a:1,id(a):1860272240
# x:2,id(x):1860272272
# a:1,id(a):1860272240
# b:[],id(b):2262818473288
# b:[],id(b):2262818473288
# b:[2],id(b):2262818473288
# b:[2],id(b):2262818473288
3 协程
这个是在前不久的面试中才知道有协程这个概念,其实也可以理解为用户线程,相比较内核线程而言,用户线程更加的灵活,并且减少了进出内核态的消耗,缺点是无法利用多核CPU的并行优势。
4 Python命名中的单下划线(_)和双下划线(__)
在Python中,双下划线开头和结尾的命名默认为Python的内部变量/方法,用以区分用户变量。例如场景的__init__()
,__dict__
,__dir__
等。
单下划线开头的命名默认为私有变量,不会在from a import *
中被导入
双下划线开头,但是没有下划线结尾的命名,Python在解释的时候会默认对其进行重命名为_类名__变量
。
class A():
def __init__(self) -> None:
self._b = "self._b"
self.__c = "self.__c"
a = A()
print(a._b) # 输出:self._b
# print(a.__c) # 报错:AttributeError: 'A' object has no attribute '__c'
print(a.__dict__) # 输出:{'_b': 'self._b', '_A__c': 'self.__c'}
# 我们发现__c变量被自动重命名为_A__c了
print(a._A__c) # 输出:self.__c
在Python中,当一个文件夹下有一个__init__.py
文件,则Python会识别这个文件夹为一个Python包
5 python字符串传参 %s和format
%s和format的区别在于,format可以传递列表、元组等类型,而%s不可以传递元组类型(%s可以传递列表类型),所以在日常使用时,使用format更加方便
6 python 迭代器和生成器
迭代器是python十分强大的一个功能,迭代器是一个可以记住遍历位置的对象。例如:
a = [1,2,3,4]
it = iter(a) # 获取一个迭代器对象
print(next(it)) # 遍历下一个位置,输出:1
print(next(it)) # 遍历下一个位置,输出:2
我们也可以使用迭代器来生成一个我们需要的列表,例如:
a = [i*i for i in range(1,9)] # 使用迭代器生成一个[1,9)的平方的列表
print(a) # 输出:[1, 4, 9, 16, 25, 36, 49, 64]
在这里如果我们将外面的[]
改为()
,a获取的将会是一个生成器,而不是迭代器。在python中,使用yield的函数被称为生成器,生成器返回的是一个迭代器的函数,只能用于迭代操作,在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
生成器不保留所有的数据信息,而是指记录当前运行的信息。因此生成器就不能直接获取某个下表的值,而是要通过next()
或者sent()
,亦或是迭代器来依次获取值。
例如:
a = (i*i for i in range(1,9)) # 使用生成器生成一个[1,9)的平方的列表
print(a) # 输出:[1, 4, 9, 16, 25, 36, 49, 64]
# print(a[2]) # 报错TypeError: 'generator' object is not subscriptable
it = iter(a) # 获取一个迭代器对象
print(next(a)) # 输出 1
print(next(a)) # 输出 4
print(next(a)) # 输出 9
print(next(a)) # 输出 16
print("=================")
for item in a:
print(item)
# 输出:
# 25
# 36
# 49
# 64
生成器常用场景:例如我们需要生成一个有规律向前推进的列表,或者一个从1到1亿的列表等等,当我们列表中元素数量十分大时,内存会爆栈。但是如何我们元素间是有规律的,则我们可以利用生成器来解决这个问题。
有需要的话可以参考这篇文章:学点简单的Python之Python生成器
7 python 装饰器
装饰器是一个十分常用的东西,经常被用在有切面需求的场景,大家耳熟能详的AOP就是这个,装饰器的主要功能就是为已经存在的函数提供一些可复用的定制化功能。
装饰器包含很多内容,需要系统的去看,这里不展开。如有需要,可以参考这篇文章:学点简单的Python之Python装饰器与闭包
8 python 变量中的作用域
python中变量总是默认本地变量,如果没有,则会创建一个本地变量。在函数中如果要使用全局变量,需要使用gloabl
进行声明。例如:
a = 5
def fun():
global a
a = a + 1
fun()
print(a)# 输出:6
9 python 闭包
python闭包与其他语言的闭包的意思是一样的,即我们在函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行。简单来说,就是在函数内定义函数,且函数内部定义的函数中使用了外部函数中的变量,且内部函数可以单独的运行。
这里用语言来描述还是比较的绕,我们可以通过下面这个小例子来更直观的理解:
# 定义一个函数extern_func
def extern_func():
# 在extern_func函数内定义一个空列表list
list = []
# 在extern_func函数内定义一个函数inner_func
def inner_func(name):
# inner_func函数的功能是在list列表中添加一个name,然后输出list
list.append(name)
print(list)
# exten_func函数的返回值是inner_func的函数体
return inner_func
# 调用extern_func函数,返回值赋值给ret1,即ret1为inner_func函数体
ret1 = extern_func()
ret1('zhangsan')# 调用ret1,在list中添加一个'zhangsan',并输出list
ret1('lisi')# 调用ret1,在list中添加一个'lisi',并输出list
# 调用extern_func函数,返回值赋值给ret2,即ret2为inner_func函数体
ret2 = extern_func()
ret2('wangwu')# 调用ret2,在list中添加一个'wangwu',并输出list
ret1('qiguanjie')# 调用ret1,在list中添加一个'lisi',并输出list
输出为:
['zhangsan']
['zhangsan', 'lisi']
['wangwu']
['zhangsan', 'lisi', 'qiguanjie']
我们发现ret1
和ret2
中虽然都是在list
中添加一个name
并返回,但是ret1
和ret2
是两次调用extern_func( )
返回的函数体,他们作用的list是不同的,他们作用的list
可以脱离原函数extern_func()
而单独使用。这就是函数闭包的简单使用。简而言之就是我们在函数中定义函数,并且使用了外部函数中的部分变量,我们内部的函数在脱离外部函数之后继续执行,且单独作用于外部函数的部分变量。
闭包一个常见错误:
我们看下面这个例子
def func():
list = []
for i in range(3):
def inner_func():
return i*i
list.append(inner_func)
return list
re1,re2,re3= func()
print(re1())
print(re2())
print(re3())
大家是不是以为三个输出的结果应该是0,1,4
?但实际上输出的结果都是4
,这是为什么呢?这里我们的i对于inner_func
来说是一个外部函数,我们在list
中添加是是inner_func
的函数体,里面返回的是i*i
,但是当我们i变化到2之后,我们才返回list,所以我们输出的三个值才都是4
,那如何避免这种情况呢?
第一种方法,区分变量
我们使用_i
来区分i
def func():
list = []
for i in range(3):
def inner_func(_i = i):
return _i*_i
list.append(inner_func)
return list
re1,re2,re3= func()
print(re1())
print(re2())
print(re3())
这里我们在inner_func
的参数中定义_i
变量,值为当前的i
,这时我们将函数体加入list
中,就可以保证值不受i
值变化的影响,输出为0,1,4。另一种方法就是我们直接在list
中存放计算好的值,而不是函数体(这种方法有一定的局限性,和之前的方法就是两种完全不同的方法了):
def func():
list = []
for i in range(3):
def inner_func():
return i*i
list.append(inner_func())
return list
re1,re2,re3= func()
print(re1())
print(re2())
print(re3())
123456789101112
这里我们这里添加到list中的是inner_func()
,一旦有()
则表明我们这个函数已经运行了,返回的是一个值。
第二种方法 nonlocal关键字
那如果我们要在内部函数中使用外部函数中的变量,并进行修改我们应该如何做呢?
def extern_func(name):
print('exter_func name is : %s' % name)
def inner_func():
name = 'inner_func ' + name
print('inner_func name is : %s' % name)
return inner_func
ret = extern_func('qiguanjie')()
如何我们直接修改的话,我们会发现这里编译会报错:UnboundLocalError: local variable 'name' referenced before assignment
这里报错的意思即我们这里的name
变量在使用前未被分配,这就和我们在函数内使用全局变量时要使用globle
关键字一样,这里在内部函数中要使用并更改外部函数中的变量,我们需要使用关键字nonlocal
,对程序进行修改:
def extern_func(name):
print('exter_func name is : %s' % name)
def inner_func():
nonlocal name
name = 'inner_func ' + name
print('inner_func name is : %s' % name)
return inner_func
ret = extern_func('qiguanjie')()
此时程序顺利编译,输出结果为:
exter_func name is : qiguanjie
inner_func name is : inner_func qiguanjie
10 python lambda函数
lambda函数即匿名函数,在很多场合都可以使用。lambda 函数比较轻便,即用即仍,很适合需要完成一项功能,但是此功能只在此一处使用,连名字都很随意的情况下。
例如在sort函数中指定排序的key
:
a = [{"a":13,"b":25,"c":62},{"a":63,"b":215,"c":612},{"a":3,"b":634,"c":216}]
a.sort(key=lambda x: x['a'])
print(a) # 输出: [{'a': 3, 'b': 634, 'c': 216}, {'a': 13, 'b': 25, 'c': 62}, {'a': 63, 'b': 215, 'c': 612}]
a.sort(key=lambda x: x['b'])
print(a) # 输出: [{'a': 13, 'b': 25, 'c': 62}, {'a': 63, 'b': 215, 'c': 612}, {'a': 3, 'b': 634, 'c': 216}]
a.sort(key=lambda x: x['c'])
print(a) # 输出: [{'a': 13, 'b': 25, 'c': 62}, {'a': 3, 'b': 634, 'c': 216}, {'a': 63, 'b': 215, 'c': 612}]
11 python中的深拷贝与浅拷贝
在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。
在深拷贝时,会只拷贝所有元素的值,包括可变对象,也仅拷贝对象中的值,而不是地址。
import copy
a = [1,2,3,4,['a','b','c']]
b = a # 赋值(引用传递)
c = copy.copy(a)# 浅拷贝
d = copy.deepcopy(a) # 深拷贝
a.append(5)
a[4].append('d')
print("a:{}, id(a):{}, id(a[4]):{}".format(a,id(a),id(a[4])))
print("b:{}, id(b):{}, id(b[4]):{}".format(b,id(b),id(b[4])))
print("c:{}, id(c):{}, id(c[4]):{}".format(c,id(c),id(c[4])))
print("d:{}, id(d):{}, id(d[4]):{}".format(d,id(d),id(d[4])))
# 输出为:
# a:[1, 2, 3, 4, ['a', 'b', 'c', 'd'], 5], id(a):1998224934024, id(a[4]):1998224933896
# b:[1, 2, 3, 4, ['a', 'b', 'c', 'd'], 5], id(b):1998224934024, id(b[4]):1998224933896
# c:[1, 2, 3, 4, ['a', 'b', 'c', 'd']], id(c):1998224936904, id(c[4]):1998224933896
# d:[1, 2, 3, 4, ['a', 'b', 'c']], id(d):1998224935752, id(d[4]):1998224957960
12 Python中*args和**kwargs
*args
表示传一个元组给函数,可以同时传递多个参数,这里的args
可以替换为其他名称,前面加一个*
即可,例如:*para
都可以。
**kwargs
表示传一个字典给函数,可以传多个键值对,这里的kwargs
同样也可以替换为其他名称,前面有**
即可。
两者的不同如下所示:
def fun(*args,**kwargs):
print("args: ",args)
print("kwargs: ",kwargs)
fun("hello","world","!","this","is","args",a=1,b=2,c=3)
# 输出为:
# args: ('hello', 'world', '!', 'this', 'is', 'args')
# kwargs: {'a': 1, 'b': 2, 'c': 3}
13 Python中__new__
和__init__
的区别
__new__
是静态方法,会返回一个创建的实例
__init__
是实例方法,无返回值
14 Python中的单例模式
单例模式是一种特别重要的设计模式,通过单例模式可以保证系统中一个类只有一个实例并且该实例易于被外界访问,方便控制实例个数并节约系统资源。实现单例模式的常用方法如下:
1 通过import
导入
在Python中使用import
来导入一个对象,则是天然的单例模式。因为模块在第一次导入时,会生成 .pyc
文件,当第二次导入时,就会直接加载 .pyc
文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。例如:
# a.py中
class A(object):
def fun(self):
pass
test_a = A
# b.py中
from a import test_a
2 使用装饰器
def Singleton(cls):
_state = {}
def _singleton(*args, **kargs):
if cls not in _state:
_state[cls] = cls(*args, **kargs)
return _state[cls]
return _singleton
@Singleton
class A(object):
a = 1
def __init__(self, x=0):
self.x = x
a1 = A()
a2 = A()
print("id(a1): ",id(a1))
print("id(a2): ",id(a2))
print("a1.a: ",a1.a)
print("a2.a: ",a2.a)
a1.a = 2
print("a1.a: ",a1.a)
a2.a = 3
print("a2.a: ",a2.a)
print("a1.a: ",a1.a)
# 输出为:
# id(a1): 2973113231736
# id(a2): 2973113231736
# a1.a: 1
# a2.a: 1
# a1.a: 2
# a2.a: 3
# a1.a: 3
3 使用类实现
使用类实现的时候需要加锁,否则在多线程中无法保证单实例
import time
import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __init__(self):
time.sleep(1)
@classmethod
def instance(cls, *args, **kwargs):
with Singleton._instance_lock:
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
def task(arg):
obj = Singleton.instance()
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
time.sleep(20)
obj = Singleton.instance()
print(obj)
# 输出:
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
# <__main__.Singleton object at 0x0000022E7C561E80>
4 基于__new__
方法实现
当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式
import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
with Singleton._instance_lock:
if not hasattr(Singleton, "_instance"):
Singleton._instance = object.__new__(cls)
return Singleton._instance
obj1 = Singleton()
obj2 = Singleton()
print(obj1)
print(obj2)
def task(arg):
obj = Singleton()
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
# 输出
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
# <__main__.Singleton object at 0x0000017B102EA978>
15 Python中is
和==
的区别
is
是对指针的比较,==
是对值的比较。
a = [1,2,3,4]
b = [1,2,3,4]
print(a is b) # 输出 False
print(a == b) # 输出 True
16 Python3 和Python2的区别
- Python2的print不用加
()
而python3需要
- python2的
/
表示整除(不加.0的时候),而Python3是除
- Python3的
A / B
的返回值类型都是float
,而Python2可能是整型
- python2默认编码是
ascii
,python3的默认编码是utf-8
- python3新增了nonlocal关键字,用于实现非局部变量
等等,这里例举的几个是常见的价格区别。
17 Python中a += X和a = a + x的区别
在Python中,a += X和a = a + x
的实现机制是不同的,这里分为四种情况。
- 可变类型
-
a += x
:将会在a
原地址上进行修改,a
的地址不变
-
a = a + x
:将会新创建一个对象,名称为a,但是地址与原来的地址不同。
- 不可变类型
-
a += x
:将会新创建一个对象,名称为a,但是地址与原来的地址不同。
-
a = a + x
:将会新创建一个对象,名称为a,但是地址与原来的地址不同。
程序示例:
a = [1,2,3]
print("a原地址为:{}".format(id(a)))
a += [4,5]
print("进行a += [4,5]操作后的a地址为:{}".format(id(a)))
a =a + [4,5]
print("进行a =a + [4,5]操作后的a地址为:{}".format(id(a)))
a = 1
print("a原地址为:{}".format(id(a)))
a += 2
print("进行a += 2操作后的a地址为:{}".format(id(a)))
a =a + 2
print("进行a =a + 2操作后的a地址为:{}".format(id(a)))
输出为:
a原地址为:140591562829000
进行a += [4,5]操作后的a地址为:140591562829000
进行a =a + [4,5]操作后的a地址为:140591562984456
a原地址为:4391820368
进行a += 2操作后的a地址为:4391820432
进行a =a + 2操作后的a地址为:4391820496
面试题
1、什么是Python?为什么它会如此流行?
Python是一种解释的、高级的、通用的编程语言。
Python的设计理念是通过使用必要的空格与空行,增强代码的可读性。
它之所以受欢迎,就是因为它具有简单易用的语法。
2、为什么Python执行速度慢,我们如何改进它?
Python代码执行缓慢的原因,是因为它是一种解释型语言。它的代码在运行时进行解释,而不是编译为本地语言。
为了提高Python代码的速度,我们可以使用CPython、Numba,或者我们也可以对代码进行一些修改。
-
减少内存占用。
-
使用内置函数和库。
-
将计算移到循环外。
-
保持小的代码库。
-
避免不必要的循环
3、Python有什么特点?
-
易于编码
-
免费和开源语言
-
高级语言
-
易于调试
-
OOPS支持
-
大量的标准库和第三方模块
-
可扩展性(我们可以用C或C++编写Python代码)
-
用户友好的数据结构
4、Python有哪些应用?
-
Web开发
-
桌面GUI开发
-
人工智能和机器学习
-
软件开发
-
业务应用程序开发
-
基于控制台的应用程序
-
软件测试
-
Web自动化
-
基于音频或视频的应用程序
-
图像处理应用程序
5、Python的局限性?
-
速度
-
移动开发
-
内存消耗(与其他语言相比非常高)
-
两个版本的不兼容(2,3)
-
运行错误(需要更多测试,并且错误仅在运行时显示)
-
简单性
6、Python代码是如何执行的?
首先,解释器读取Python代码并检查是否有语法或格式错误。
如果发现错误,则暂停执行。如果没有发现错误,则解释器会将Python代码转换为等效形式或字节代码。
然后将字节码发送到Python虚拟机(PVM),这里Python代码将被执行,如果发现任何错误,则暂停执行,否则结果将显示在输出窗口中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X6VcJfDh-1668657195604)(./img/1620.png)];
7、如何在Python中管理内存?
Python内存由Python的私有headspace管理。
所有的Python对象和数据结构都位于一个私有堆中。私用堆的分配由Python内存管理器负责。
Python还内置了一个的垃圾收集器,可以回收未使用的内存并释放内存,使其可用于headspace。
8、解释Python的内置数据结构?
Python中主要有四种类型的数据结构。
列表:列表是从整数到字符串甚至另一个列表的异构数据项的集合。列表是可变的。列表完成了其他语言中大多数集合数据结构的工作。列表在[ ]方括号中定义。
例如:a = [1,2,3,4]
集合:集合是唯一元素的无序集合。集合运算如联合|,交集&和差异,可以应用于集合。{}用于表示一个集合。
例如:a = {1,2,3,4}
元组:Python元组的工作方式与Python列表完全相同,只是它们是不可变的。()用于定义元组。
例如:a =(1,2,3,4)
字典:字典是键值对的集合。它类似于其他语言中的hash map。在字典里,键是唯一且不可变的对象。
例如:a = {‘number’:[1,2,3,4]}
9、解释//、%、* *运算符?
//(Floor Division)-这是一个除法运算符,它返回除法的整数部分。
例如:5 // 2 = 2
%(模数)-返回除法的余数。
例如:5 % 2 = 1
**(幂)-它对运算符执行指数计算。a ** b表示a的b次方。
例如:5 ** 2 = 25、5 ** 3 = 125
10、Python中的单引号和双引号有什么区别?
在Python中使用单引号(’ ')或双引号(" ")是没有区别的,都可以用来表示一个字符串。
这两种通用的表达方式,除了可以简化程序员的开发,避免出错之外,还有一种好处,就是可以减少转义字符的使用,使程序看起来更简洁,更清晰。
11、Python中append,insert和extend的区别?
append:在列表末尾添加新元素。
insert:在列表的特定位置添加元素。
extend:通过添加新列表来扩展列表。
numbers = [1,2,3,4,5]
numbers.append(6)
print(numbers)
>[1,2,3,4,5,6]
## insert(position,value)
numbers.insert(2,7)
print(numbers)
>[1,2,7,3,4,5,6]
numbers.extend([7,8,9])
print(numbers)
>[1,2,7,3,4,5,6,7,8,9]
numbers.append([4,5])
>[1,2,7,3,4,5,6,7,8,9,[4,5]]
12、break、continue、pass是什么?
break:在满足条件时,它将导致程序退出循环。
continue:将返回到循环的开头,它使程序在当前循环迭代中的跳过所有剩余语句。
pass:使程序传递所有剩余语句而不执行。
13、区分Python中的remove,del和pop?
remove:将删除列表中的第一个匹配值,它以值作为参数。
del:使用索引删除元素,它不返回任何值。
pop:将删除列表中顶部的元素,并返回列表的顶部元素。
numbers = [1,2,3,4,5]
numbers.remove(5)
> [1,2,3,4]
del numbers[0]
>[2,3,4]
numbers.pop()
>4
14、什么是switch语句。如何在Python中创建switch语句?
switch语句是实现多分支选择功能,根据列表值测试变量。
switch语句中的每个值都被称为一个case。
在Python中,没有内置switch函数,但是我们可以创建一个自定义的switch语句。
switcher = {
1: "January",
2: "February",
3: "March",
4: "April",
5: "May",
6: "June",
7: "July",
8: "August",
9: "September",
10: "October",
11: "November",
12: "December"
}
month = int(input())
print(switcher.get(month))
> 3
march
15、举例说明Python中的range函数?
range:range函数返回从起点到终点的一系列序列。
range(start, end, step),第三个参数是用于定义范围内的步数。
# number
for i in range(5):
print(i)
> 0,1,2,3,4
# (start, end)
for i in range(1, 5):
print(i)
> 1,2,3,4
# (start, end, step)
for i in range(0, 5, 2):
print(i)
>0,2,4
16、==和is的区别是?
==比较两个对象或值的相等性。
is运算符用于检查两个对象是否属于同一内存对象。
lst1 = [1,2,3]
lst2 = [1,2,3]
lst1 == lst2
>True
lst1 is lst2
>False
17、如何更改列表的数据类型?
要将列表的数据类型进行更改,可以使用tuple()或者set()。
lst = [1,2,3,4,2]
# 更改为集合
set(lst) ## {1,2,3,4}
# 更改为元组
tuple(lst) ## (1,2,3,4,2)
18、Python中注释代码的方法有哪些?
在Python中,我们可以通过下面两种方式进行注释。
-
三引号’‘’,用于多行注释。
-
单井号#,用于单行注释。
19、!=和is not运算符的区别?
!=如果两个变量或对象的值不相等,则返回true。
is not是用来检查两个对象是否属于同一内存对象。
lst1 = [1,2,3,4]
lst2 = [1,2,3,4]
lst1 != lst2
>False
lst1 is not lst2
>True
20、Python是否有main函数?
是的,它有的。只要我们运行Python脚本,它就会自动执行。
21、什么是lambda函数?
Lambda函数是不带名称的单行函数,可以具有n个参数,但只能有一个表达式。也称为匿名函数。
a = lambda x, y:x + y
print(a(5, 6))
> 11
22、iterables和iterators之间的区别?
iterable:可迭代是一个对象,可以对其进行迭代。在可迭代的情况下,整个数据一次存储在内存中。
iterators:迭代器是用来在对象上迭代的对象。它只在被调用时被初始化或存储在内存中。迭代器使用next从对象中取出元素。
# List is an iterable
lst = [1,2,3,4,5]
for i in lst:
print(i)
# iterator
lst1 = iter(lst)
next(lst1)
>1
next(lst1)
>2
for i in lst1:
print(i)
>3,4,5
23、Python中的Map Function是什么?
map函数在对可迭代对象的每一项应用特定函数后,会返回map对象。
24、解释Python中的Filter?
过滤器函数,根据某些条件从可迭代对象中筛选值。
# iterable
lst = [1,2,3,4,5,6,7,8,9,10]
def even(num):
if num%2==0:
return num
# filter all even numbers
list(filter(even,lst))
---------------------------------------------
[2, 4, 6, 8, 10]
25、解释Python中reduce函数的用法?
reduce()函数接受一个函数和一个序列,并在计算后返回数值。
from functools import reduce
a = lambda x,y:x+y
print(reduce(a,[1,2,3,4]))
> 10
26、什么是pickling和unpickling?
pickling是将Python对象(甚至是Python代码),转换为字符串的过程。
unpickling是将字符串,转换为原来对象的逆过程。
27、解释*args和**kwargs?
*args,是当我们不确定要传递给函数参数的数量时使用的。
def add(* num):
sum = 0
for val in num:
sum = val + sum
print(sum)
add(4,5)
add(7,4,6)
add(10,34,23)
---------------------
9
17
67
**kwargs,是当我们想将字典作为参数传递给函数时使用的。
def intro(**data):
print("\nData type of argument:",type(data))
for key, value in data.items():
print("{} is {}".format(key,value))
intro(name="alex",Age=22, Phone=1234567890)
intro(name="louis",Email="a@gmail.com",Country="Wakanda", Age=25)
--------------------------------------------------------------
Data type of argument: <class 'dict'>
name is alex
Age is 22
Phone is 1234567890
Data type of argument: <class 'dict'>
name is louis
Email is a@gmail.com
Country is Wakanda
Age is 25
28、解释re模块的split()、sub()、subn()方法?
split():只要模式匹配,此方法就会拆分字符串。
sub():此方法用于将字符串中的某些模式替换为其他字符串或序列。
subn():和sub()很相似,不同之处在于它返回一个元组,将总替换计数和新字符串作为输出。
import re
string = "There are two ball in the basket 101"
re.split("\W+",string)
---------------------------------------
['There', 'are', 'two', 'ball', 'in', 'the', 'basket', '101']
re.sub("[^A-Za-z]"," ",string)
----------------------------------------
'There are two ball in the basket'
re.subn("[^A-Za-z]"," ",string)
-----------------------------------------
('There are two ball in the basket', 10)
29、Python中的生成器是什么?
生成器(generator)的定义与普通函数类似,生成器使用yield关键字生成值。
如果一个函数包含yield关键字,那么该函数将自动成为一个生成器。
# A program to demonstrate the use of generator object with next() A generator function
def Fun():
yield 1
yield 2
yield 3
# x is a generator object
x = Fun()
print(next(x))
-----------------------------
1
print(next(x))
-----------------------------
2
30、如何使用索引来反转Python中的字符串?
string = 'hello'
string[::-1]
>'olleh'
31、类和对象有什么区别?
类(Class)被视为对象的蓝图。类中的第一行字符串称为doc字符串,包含该类的简短描述。
在Python中,使用class关键字可以创建了一个类。一个类包含变量和成员组合,称为类成员。
对象(Object)是真实存在的实体。在Python中为类创建一个对象,我们可以使用obj = CLASS_NAME()
例如:obj = num()
使用类的对象,我们可以访问类的所有成员,并对其进行操作。
class Person:
""" This is a Person Class"""
# varable
age = 10
def greets(self):
print('Hello')
# object
obj = Person()
print(obj.greet)
----------------------------------------
Hello
32、你对Python类中的self有什么了解?
self表示类的实例。
通过使用self关键字,我们可以在Python中访问类的属性和方法。
注意,在类的函数当中,必须使用self,因为类中没有用于声明变量的显式语法。
33、_init_在Python中有什么用?
“init”是Python类中的保留方法。
它被称为构造函数,每当执行代码时都会自动调用它,它主要用于初始化类的所有变量。
34、解释一下Python中的继承?
继承(inheritance)允许一个类获取另一个类的所有成员和属性。继承提供代码可重用性,可以更轻松地创建和维护应用程序。
被继承的类称为超类,而继承的类称为派生类/子类。
35、Python中OOPS是什么?
面向对象编程,抽象(Abstraction)、封装(Encapsulation)、继承(Inheritance)、多态(Polymorphism)
36、什么是抽象?
抽象(Abstraction)是将一个对象的本质或必要特征向外界展示,并隐藏所有其他无关信息的过程。
37、什么是封装?
封装(Encapsulation)意味着将数据和成员函数包装在一起成为一个单元。
它还实现了数据隐藏的概念。
38、什么是多态?
多态(Polymorphism)的意思是「许多形式」。
子类可以定义自己的独特行为,并且仍然共享其父类/基类的相同功能或行为。
39、什么是Python中的猴子补丁?
猴子补丁(monkey patching),是指在运行时动态修改类或模块。
from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
return "Hello!"
SomeClass.speak = speak
40、Python支持多重继承吗?
Python可以支持多重继承。多重继承意味着,一个类可以从多个父类派生。
41、Python中使用的zip函数是什么?
zip函数获取可迭代对象,将它们聚合到一个元组中,然后返回结果。
zip()函数的语法是zip(*iterables)
numbers = [1, 2, 3]
string = ['one', 'two', 'three']
result = zip(numbers,string)
print(set(result))
-------------------------------------
{(3, 'three'), (2, 'two'), (1, 'one')}
42、解释Python中map()函数?
map()函数将给定函数应用于可迭代对象(列表、元组等),然后返回结果(map对象)。
我们还可以在map()函数中,同时传递多个可迭代对象。
numbers = (1, 2, 3, 4)
result = map(lambda x: x + x, numbers)
print(list(result))
43、Python中的装饰器是什么?
装饰器(Decorator)是Python中一个有趣的功能。
它用于向现有代码添加功能。这也称为元编程,因为程序的一部分在编译时会尝试修改程序的另一部分。
def addition(func):
def inner(a,b):
print("numbers are",a,"and",b)
return func(a,b)
return inner
@addition
def add(a,b):
print(a+b)
add(5,6)
---------------------------------
numbers are 5 and 6
sum: 11
44、编写程序,查找文本文件中最长的单词
def longest_word(filename):
with open(filename, 'r') as infile:
words = infile.read().split()
max_len = len(max(words, key=len))
return [word for word in words if len(word) == max_len]
print(longest_word('test.txt'))
----------------------------------------------------
['comprehensions']
45、编写程序,检查序列是否为回文
a = input("Enter The sequence")
ispalindrome = a == a[::-1]
ispalindrome
>True
46、编写程序,打印斐波那契数列的前十项
fibo = [0,1]
[fibo.append(fibo[-2]+fibo[-1]) for i in range(8)]
fibo
> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
47、编写程序,计算文件中单词的出现频率
from collections import Counter
def word_count(fname):
with open(fname) as f:
return Counter(f.read().split())
print(word_count("test.txt"))
48、编写程序,输出给定序列中的所有质数
lower = int(input("Enter the lower range:"))
upper = int(input("Enter the upper range:"))
list(filter(lambda x:all(x % y != 0 for y in range(2, x)), range(lower, upper)))
-------------------------------------------------
Enter the lower range:10
Enter the upper range:50
[11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
49、编写程序,检查数字是否为Armstrong
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KpIKh4BX-1668657195605)(./img/1620-1668336903605182.png)];
将每个数字依次分离,并累加其立方(位数)。
最后,如果发现总和等于原始数,则称为阿姆斯特朗数(Armstrong)。
num = int(input("Enter the number:\n"))
order = len(str(num))
sum = 0
temp = num
while temp > 0:
digit = temp % 10
sum += digit ** order
temp //= 10
if num == sum:
print(num,"is an Armstrong number")
else:
print(num,"is not an Armstrong number")
50、用一行Python代码,从给定列表中取出所有的偶数和奇数
a = [1,2,3,4,5,6,7,8,9,10]
odd, even = [el for el in a if el % 2==1], [el for el in a if el % 2==0]
print(odd,even)
> ([1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[fibo.append(fibo[-2]+fibo[-1]) for i in range(8)]
fibo
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
47、编写程序,计算文件中单词的出现频率
```javascript
from collections import Counter
def word_count(fname):
with open(fname) as f:
return Counter(f.read().split())
print(word_count("test.txt"))
48、编写程序,输出给定序列中的所有质数
lower = int(input("Enter the lower range:"))
upper = int(input("Enter the upper range:"))
list(filter(lambda x:all(x % y != 0 for y in range(2, x)), range(lower, upper)))
-------------------------------------------------
Enter the lower range:10
Enter the upper range:50
[11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
49、编写程序,检查数字是否为Armstrong
[外链图片转存中…(img-KpIKh4BX-1668657195605)];
将每个数字依次分离,并累加其立方(位数)。
最后,如果发现总和等于原始数,则称为阿姆斯特朗数(Armstrong)。
num = int(input("Enter the number:\n"))
order = len(str(num))
sum = 0
temp = num
while temp > 0:
digit = temp % 10
sum += digit ** order
temp //= 10
if num == sum:
print(num,"is an Armstrong number")
else:
print(num,"is not an Armstrong number")
50、用一行Python代码,从给定列表中取出所有的偶数和奇数
a = [1,2,3,4,5,6,7,8,9,10]
odd, even = [el for el in a if el % 2==1], [el for el in a if el % 2==0]
print(odd,even)
> ([1, 3, 5, 7, 9], [2, 4, 6, 8, 10])