文章目录
前言
写博客的第二篇:
为什么要写这篇文章?因为这是作者所经历过的面试,一鼻子的灰,作者一直想找数据分析的工作,可只会简单的爬取,知道爬虫思路,当被问到基础的东西时,就突然一脸懵逼,咦?这个我好想用过啊!是怎么来着?也过于紧张,在面试的时候双脚抖得疼痛。以python的对象来说,大脑是对象,还是空白的那种。面试某公司,面试官让我买本书看看!深受打击,在面试的前一晚,作者复习爬虫到3点,之后就被基础的知识问傻了,人也傻了。写这篇文章,也在于激励自己,绝不放弃,也希望能给各位一些小经验,基础!基础!基础!
字典
字典相加合并
dict_a = {'a':'这是字典a','b':'这是字典b'}
dict_b = {'c':'这是字典c','d':'这是字典d'}
merge_dict = dict(list(dict_a.items())+list(dict_b.items()))
print(merge_dict)
#输出{'a':'这是字典a','b':'这是字典b','c':'这是字典c','d':'这是字典d'}
这里使用了items方法,何为items方法呢?Python 字典items() 函数以列表返回可遍历的(键, 值) 元组数组。这是网上解释,作者分解一下,请看!
dict_a = {'a':'这是字典a','b':'这是字典b'}
c = dict_a.items()
print(c)
print(type(c))
#输出dict_items([('a', '这是字典a'), ('b', '这是字典b')])
#输出<class 'dict_items'>
对了!返回的不是列表,而是’dict_items’,而这里要合并需将’dict_items’转换为’list’。list(dict_a.items())+list(dict_b.items())就相当于两个列表合并,再转换为字典,相信你脑海已经有结果。
dict()合并字典
dict_a = {'a':'这是字典a','b':'这是字典b'}
dict_b = {'c':'这是字典c','d':'这是字典d'}
merge_dict = dict(dict_a,**dict_b)
print(merge_dict)
#输出{'a': '这是字典a', 'b': '这是字典b', 'c': '这是字典c', 'd': '这是字典d'}
这是dict方法,dict()函数用于创建一个字典。用法可以自行上网搜一下。
列表
列表合并相加
list_a = ['a','b']
list_b = ['c','d']
merge_list = list_a+list_b
print(merge_list)
#输出['a', 'b', 'c', 'd']
这个就简单的两个列表相加。
extend()方法合并
list_a = ['a','b']
list_b = ['c','d']
list_a.extend(list_b)
print(list_a)
#输出['a', 'b', 'c', 'd']
extend()该方法没有返回值,但会在已存在的列表中添加新的列表内容。
列表字典转换
列表转字典
l1 = ['a','b']
l2 = [1,2]
z1 = zip(l1,l2)#这里方便理解分开写了
z = dict(z1)
print(z1)
print(z)
print(type(z1))
'''输出
<zip object at 0x0000028318EF40C8>
{'a': 1, 'b': 2}
<class 'zip'>
'''
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
那为什么打印出print(z)是<zip object at 0x0000028318EF40C8>这个玩意呢?
再来看看
l1 = ['a','b']
l2 = [1,2]
z1 = list(zip(l1,l2))#这里方便理解分开写了
print(z1)
#输出[('a', 1), ('b', 2)]
zip()函数打印出来的就是这样,再加个 dict(z1)也就转换为字典了。
字典转列表
dict_1 = {'a': 1, 'b': 2}
a = list(dict_1.keys())
b = list(dict_1.values())
print(a)
print(b)
'''输出
['a', 'b']
[1, 2]
'''
字典就是键值对,分别取出字典的键和值转换为列表就行了。
切片使用
题目
输入字符串’123456789’,想提取出2468,13579。
解答一
s = '123456789'
return_s = s[0:10:2]
print(return_s)
return_s1 = s[1:10:2]
print(return_s1)
#输出13579
#输出2468
这是切片的使用,start : end : step
其实位置:start
末尾位置:end
步长:step
解答二
s = '123456789'
a = []
b = []
for i in range(len(s)):
if int(s[i])%2 ==0:
a.append(s[i])
else:
b.append(s[i])
print(a)
print(b)
#a输出['2', '4', '6', '8']
#b输出['1', '3', '5', '7', '9']
这里采用了余数的计算方法,当然和切片使用没有关系,只是根据题目而言,这里这是做简单的操作。
装饰器
装饰器概念及用途
装饰器本质上还是函数,可以让其他函数在不做任何代码修改的前提下增加额外功能,它通常用于切面需求,例如:插入日志、性能测试、权限校验等。
写一个装饰器(题目)
def f2(func):
def f1():
return func()+1
return f1
@f2
def func():
print('func()函数')
return 1
print(func())
'''输出
func()函数
2
'''
通过@符号和装饰器名实现装饰器函数与被装饰器函数联系。再说一遍,‘让其他函数在不做任何代码修改的前提下增加额外功能’。
不要装饰器,代码是这样的👇
def f2(func):
def f1(): #闭包
return func()+1
return f1
def func():
print('func()函数')
return 1
a = f2(func)
print(a())
装饰器的本质就是一个嵌套函数,外层函数的参数是被修饰的函数,内层函数是一个闭包并在其中增加新功能(装饰器的功能函数)。
生成器与迭代器
生成器
生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。调用一个生成器函数,返回的是一个迭代器对象。
import sys
def f2():
a = 0
while a<5:
yield a
a += 1
b = f2()
while True:
try:
print(b.__next__(),b)
except StopIteration: #StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况。
sys.exit()
'''输出
0 <generator object f2 at 0x0000021BA724D848>
1 <generator object f2 at 0x0000021BA724D848>
2 <generator object f2 at 0x0000021BA724D848>
3 <generator object f2 at 0x0000021BA724D848>
4 <generator object f2 at 0x0000021BA724D848>
'''
生成器相比一次列出所有内容的优势:
1.更节省存储空间
2.响应速度更快
3.使用更加灵活
迭代器
什么是迭代器?
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
l=[1,2,3,4]
it = iter(l) # 创建迭代器对象
for x in it:
print (x, end=" ")
#输出1 2 3 4
```#next()用法
l=[1,2,3,4]
it = iter(l) # 创建迭代器对象
print(next(it))
print(next(it))
print(next(it))
print(next(it))
生成器与迭代器的区别
生成器是一种特殊的迭代器,生成器能做迭代器能做的所有事,使用生成器表达式取代列表解析可以同时节省内存资源。生成器终结时还会抛出StopIteration异常。
实例、静态、类方法
实例方法
实例方法:()里面的第一个参数必须是实例对象,一般约定为self通过它来传递实例属性和方法。
class student:
def __init__(self,name,age):
self.name = name
self.age = age
def info(self): #实例方法
print('{}已经{}岁了!'.format(self.name,self.age))
a = student('csdn',100) #传参
a.info()
静态方法
使用装饰器@staticmethod,它在其中只是起到帮助的信息,存放逻辑代码,它是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。()内不用加self或者cls!!
class student:
@staticmethod
def info(): #静态方法
print('帮助理解')
a = student()
a.info()
#输出 帮助理解
'''
这里只是简单的介绍一下,不要太注重细节,哈哈
'''
注意:静态方法不能访问类属性!!
类方法
使用装饰器@classmethod,()内的参数与实例方法参数self不一样,类方法的是cls。
class student:
r = '这是类方法'
@classmethod
def info(cls): #类方法
print(cls.r)
a = student() #创建对象
a.info()
#输出 这是类方法
注意:类方法可以访问类属性。
单例模式
什么是单例模式?
创建的对象使用的是同一地址。
题目
写出至少两种以上的单例模式!
基于__new__(推荐)
class student:
__instance = None #私有化,设置__instance为空
def __init__(self):
pass
def __new__(cls):
if cls.__instance is None: #判断是否为空
cls.__instance = object.__new__(cls) #使用__new__开辟一个新地址
return cls.__instance
else: #若不为空
return cls.__instance #直接返回已有的地址
s = student() #先调用__new__再调用__init__。
s1 = student()
print(s)
print(s1)
'''输出
<__main__.student object at 0x00000187885A7D48>
<__main__.student object at 0x00000187885A7D48>
'''
一下是多线程使用的单例模式👇方法就和上面👆所说的一样,只是加了多线程
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
def task(args):
obj = Singleton()
print(obj)
for i in range(4):
t = threading.Thread(target=task,args=[i,])
t.start()
基于类方法
import threading
class Mysingle(object):
_instance_lock = threading.Lock()
def __init__(self):
pass
@classmethod
def instance(cls,*args,**kwargs):
if not hasattr(Mysingle,'_instance'):
with Mysingle._instance_lock:
if not hasattr(Mysingle,'_instance'):
Mysingle._instance = Mysingle(*args,**kwargs)
return Mysingle._instance
def task(args):
single = Mysingle.instance()
print(single)
for i in range(4):
t = threading.Thread(target=task,args=[i,])
t.start()
工厂模式
什么是工厂模式?
工程模式主要用来实例化有共同方法的类,它可以动态决定应该实例化哪一个类,不必事先知道每次要实例化哪一个类。
例如在编写一个应用程序时,用户可能会选择连接各种各样的数据库,但开发者不能预知用户会使用哪一个数据库,于是提供一个通用的方法,里面包含了各个数据库的连接方案,用户在使用过程中,只需要传入数据库的名字并给出连接所需要的信息即可。
class Operation(object):
def connect(self):
pass
class MYSQL(Operation):
def connect(self):
print('连接MYSQL成功')
class SQLite(Operation):
def connect(self):
print('连接SQLite成功')
class DB(object):
@staticmethod
def create(name):
name = name.lower()
if name == 'mysql':
return MYSQL()
elif name == 'sqlite':
return SQLite()
else:
print('不支持其他数据库连接')
db1 = DB.create('MYSQL')
db1.connect()
db2 = DB.create('SQLite')
db2.connect()
DB类定义了一个静态方法create(),该方法的参数为类名,可以根据类名创建对应的对象,因此称为工厂方法。
小结
这是作者目前面试所遇到的一些题目,仅供参考,当然还有其他的,例如之前写过的基础算法(可以去看之前写过的python基础算法文章)。这些都是基础的,走开发方向的话,单例模式,多线程这些一定要弄明白。
面试官会经常问:你还有什么要问的吗?
根据自己的情况如实回答,包括薪资、住宿、生活方面的都可以问(表明的你诚意,是想要去的,也防止后面因为某些原因!)。还需加上一点,我能学到什么?能有什么发展?(表明你有上进心)或者可以说公司对人才培养方面有什么计划呢?就是之类的。
面试需要运气:
面试也是需要运气的,为什么这么说呢?就拿一个简单的例子,面试官会问你 "你需要多少薪资呢?"侧面来说你觉得你的能力能值多少?能为公司创收多少价值?说少了面试官又觉得你能力不行,说多了吧,面试官又觉得太高。按网上说:“我相信贵公司有一套完整的新人体系,我愿意接收这一套体系”。又觉得假。那怎么办?运气,面试官心情,个人决定。再比如,面试官问的问题,刚好涉及你的知识盲区,那岂不是凉了,作者就被面试官问到了基础不常用的知识盲区,就凉了,当时是早上一场面试,下午一场面试,早上的知识盲区了,下午问的,哎!就是我懂的,都能回答上来——scrapy的运行机制、你什么怎么爬取网站过程的,遇到过哪些问题?如何解决?老板!我会啊!这就是运气了!关于上面这几个问题大家可以上网搜一下,作者后续也可能会发相关的文章。仅仅一点点经验,也还是分享一下,大佬路过方便的话也希望留下一些东西,路在脚下,我在成长。遇到挫折不要退缩,面试题涉及到你的知识盲区,就去学习!