Py001_02_02Python列表

列表

一个数据的集合,集合里可以放置任何数据类型,可对集合方便的进行增删改查操作

  • 创建
  • 查询
  • 切片
  • 增加
  • 修改
  • 删除
  • 循环
  • 排序

创建

1
2
3
4
5
6
7
# 方法一
a1 = [] # 定义空列表
a2 = [1,2,3,4] # 存4个值 索引0-3
a3 = [1,[2,3,4]] # 嵌套列表

# 方法二(不推荐)
b1 = list() # 空列表

查询

1
2
3
4
5
6
a = ['a','b','c','d','e','a','a',1,2]

a[2] # 通过索引 'c'
a[-1] # 通过索引从右开始取值 2
a.index('b') # 查找元素(从左往右)对应的索引 1
a.count('a') # 返回元素的个数 3

切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a = ['a','b','c','d','e','f','aa','bb','cc']

# 取前三个
a[0:3] # 包头不包尾

# 取最后四个
a[-1:-4] # []
a[-4:] # ['f','aa','bb','cc']

# 取前三
a[:3]

# 取所有
a[:]

# 跳指定步子取值
a[::2]

增加

1
2
3
4
5
6
7
a = [1,2,3,4,5]
a.append('peiqi')
print(a) # [1,2,3,4,5,'peiqi']

# 指定位置插入
a.insert(0,'a')
print(a) # ['a',1,2,3,4,5,'peiqi']

修改

1
2
3
a = [1,2,3,4,5]
a[2] = 'a'
print(a) # [1,2,'a',4,5]

删除

  • pop
  • remove
  • del
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a = [1,2,3,4,5,6,7,8,9,10]
a.pop() # 删除最后一个
print(a) # [1,2,3,4,5,6,7,8,9]


b = [1,2,3,4,'a',4,'b']
b.remove(4) # 删除指定元素 从左往右匹配的第一个
print(b) # [1,2,3,'a',4,'b']

c = [1,2,3,4,5,6,7,8,9]
del c[2]
print(c) # [1,2,4,5,6,7,8,9]

del c[0:3] # 切片删

del c # 删除整个数组
print(c) # 报错

循环

1
2
3
a = [1,2,3,4,5,5]
for i in a:
print(i)

排序

  • sort
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
n = ['a','e','b','c',34,23]
n.sort() # 报错 不支持 int和 str一起排


m = ['a','e','A','b','c','z','h']
m.sort() # ['A','a','b','c','e','h','z']
m.insert(3,'#')
m.insert(3,'*')
m.insert(1,'!')
m.sort() # ['!','#','*','A','a','b','c','e','h','z']
# 字符按ascⅡ排序

m.reverse() # 翻转


# 列表拼接
[1,2,3] + [4,5,6] ==> [1,2,3,4,5,6]

# n.extent(n2)

a = [1,2,3]
a.clear() # []

b = [1,2,3]
c = b.copy() # b 和 c是完全独立的

练习

  1. 将一个列表的索引打印出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
a = ['a','b','c']

count = 0;
for i in a:
print(i,count)
count += 1

方法二 enumerate 枚举

for i in enumerate(a):
print(i)

'''
{0:'a'}
{1:'b'}
{2:'c'}
'''

for index,value in enumerate(a):
print(index,value)

元组

特性

  • 不可变
  • 元组本身不可变,如果元组里还包含其他可变元素(嵌套列表),这些元素可以变

功能

  • index
  • count
  • 切片

使用场景

  • 显示的告诉别人,数据不可改变
  • 数据库连接配置信息

Py001_02_01Python进制转换和字符编码and浮点数

计算机基础(进制转换)

我觉得这个只要你会开机关机就差不多了,如果不方便理解给你举个例子:

  1. 计算机主要就是二进制,二进制就是0/1 逢二进一
    (实在不好理解你就想现实中的电线插头 左零右火)
  2. 计算机通过电信号来判断是0还是1 比如电压低于50%就代表0 高于50%代表 1
  3. 于是这些 01组成的东西就被机器所认识也叫 机器语言
    但是这很反人类啊!多么复杂的大脑才能识别这个啊!
    于是出现了汇编,还是不够好,于是 C / C++ /JAVA等高级语言横空出世
  4. 8位 0、1组成的序列代表1字节
    • 1B(byte) = 8位(bit)
    • 1KB = 1024B
    • 1MB = 1024KB
    • 1GB = 1024MB
    • 1T = 1024GB

买手机可千万注意别被那些卖家忽悠了,老说啥机身内存大运行速度快啥的!大错特错 如果你买手机建议运行内存买高点

  • 电脑和手机这些设备分为 内存(RAM随机存储) 和 外存(ROM只读存储)
  • 内存就是 01这堆组成的电信号 没电了只要你编辑的word文档没保存就丢了
  • 外存就是 电脑上存的小说啊 mp3 短视频等 只要你不手动删除怎么开关机都在

如下是一些进制转换:

口诀:逢二进一 逢八进一 逢十进一 逢十六进一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
如:
二进制 十进制 八进制 十六进制
0000 0000 0 0 0
0000 0001 1 1 1
0000 0010 2 2 2
0000 0011 3 3 3
0000 0100 4 4 4
0000 0101 5 5 5
0000 0110 6 6 6
0000 0111 7 7 7
0000 1000 8 10 8
0000 1001 9 11 9
0000 1010 10 12 a
0000 1011 11 13 b
0000 1100 12 14 c
0000 1101 13 15 d
0000 1110 14 16 e
0000 1111 15 17 f

计算机表示数字到汉字的过程

  1. 内存里如何存0和1
  2. 如何存数字
  3. 存字符
  4. 存中文 GB2312 GBK GB18030
  5. 存所有字符(所有国家的字符Unicode万国码)
  6. 将Unicode存到计算机里(utf-8编码变长存储)

可以参考我之前写的文章 计算机是如何存数据的

windows系统中文版默认是gbk

mac\linux系统默认编码是utf-8

python里使用字符编码

python3和 python2最大的区别就是字符编码改了

  • python2 默认编码ascⅡ(默认不支持中文)
  • python3 默认编码utf-8

如果python2想支持中文呢?

1
2
3
4
5
6
7
8
9
.py文件程序首行声明编码

第一种 官方推荐的
#! -*-coding: utf-8 -*-

第二种
#!encoding:utf-8

python3里默认支持中文

浮点数

科学记数法:以10为基数

1
print(1.399e3) # 1399.0

复数

1
2
# 可以用来做量子力学(编程基本用不到)
print(-5+4j)

精确度

  • 浮点数占据的存储空间远大于整数的
  • python里能精确的存储17位超过就不准了可能有四舍五入的误差

如果你就想计算高精度的浮点数

1
借助 decimal 模块的 getcontext 和 Decimal方法(自行百度吧!)

Py001_01_04Python逻辑运算和分支语句和循环

逻辑运算

  • 算数运算
1
2
3
4
5
6
7
+
-
*
/
% 取余
** 幂运算 2的三次方 ==> 2**3
// 整除 11//2 ==>5
  • 比较运算
1
2
3
4
5
6
7
== 等于
!= 不等于
<> 不等于 类似 != 在python3里废除了
>
<
>=
<=
  • 赋值运算
1
2
3
4
5
6
7
8
=
+=
-=
*=
/=
%=
**=
//=
  • 逻辑运算
1
2
3
and 且
or 或
not 非

分支语句

单分支

1
2
3
4
5
6
7
8
9
10
11
if 条件 :
满足条件后执行的代码

age = 56
if age > 50:
print('岁数太大不要')
print('haha')

结果:
'岁数太大不要'
'haha'

双分支

1
2
3
4
if 条件 :
满足条件后执行的代码
else:
不满足条件执行的代码

多分支

1
2
3
4
5
6
7
8
9
10
if 条件1 :
print('条件1合适')
elif 条件2 :
print('条件2合适')
elif 条件3 :
print('条件3合适')
elif 条件4 :
print('条件4合适')
else :
print('都不合适')

循环

  • while
1
2
while 条件:
执行代码

打印0-100的数字

1
2
3
4
5
count = 0
while count<=100:
print(count)
count += 1
print('loop is end')

打印0-100的偶数

1
2
3
4
5
count = 0
while count<=100:
if count % 2 == 0:
print("loop",count)
count += 1

打印0-100,第50次不打印,第60-80打印对应平方

1
2
3
4
5
6
7
8
9
count = 0
while count<=100:
if count == 50:
pass # 代表过
elif count>=60 and count<=80:
print(count*count)
else:
print(count)
count += 1

deal loop(死循环)

1
2
3
4
# 就是条件永远都满足,就会触发死循环

while True:
print('xxx')

continue 和 break

  • break 用于完全结束一个循环,跳出循环体执行后面的语句
  • continue 终止本次循环,接着还执行后面的循环
1
2
3
4
5
6
7
8
9
10
11
12
count = 0
while count < 100:
print(count)
if count == 5:
break
count += 1

count = 5的时候结束循环

但是如果把break 换成continue就会造成死循环

因为 count +=1 得不到执行 count一直等于5

你没见过的while … else …

while后面还有个else

意思是:当while没有被break终止的话,就会执行else里的语句

1
2
3
4
5
6
7
8
count = 0
while count < 100:
count += 1
print(count)
if count == 5:
break
else:
print('程序被break中断过')

Py001_01_03Python基本数据类型

与其他语言一样python也有一些数据类型,但是它不会像java那样强制你声明好数据的类型

python解释器会自己识别你的数据类型

1
2
3
4
5
6
//java
int age = 12
char x = 'a'

# python
age = 12

判断数据类型

  • type函数输出变量的数据类型
1
2
3
4
5
a = 1
b = 'aa'

type(a) # int
type(b) # str

基本数据类型

  • 数字
  • 字符串
  • 布尔

数字类型

int(整型)

1
2
在32位机器上,整数的位数为32,取值范围为-2**31至2**31-1
在64位机器上,整数的位数为64,取值范围为-2**63至2**63-1

long(长整型)

1
跟C语言不同,python没有指定长整型的位宽,即没有限制长整型数值的大小,但实际上由于机器内存有限,我们使用的长整型也不可能无限大。

从python2.2起,如果整数溢出,python会自动将整数数据转换为长整数。所以现在在长整数后面加不加L也不会导致严重后果了

注意

  • 在python3里不再有long类型了,全是int
  • 除了int,long还有float浮点数,复数,但今天先不涉及

字符串

加引号的就被认为是字符串

1
2
3
name = 'hjx'
name2 = "alex"
msg = '''My name is Alex,I am 22 years old '''

如果想使用单引号作为字符呢?

1
msg = "My name is Alex,I'am 22 years old"

多引号的作用:就是多行的时候必须使用它

1
2
3
4
msg = '''
一二三四五
上山打老虎
'''

字符串拼接

python不仅支持「+」 还支持 「*」

1
2
3
4
5
name = 'alex'
age = '22'
print(name+age) # alex22

print(name*3) # alexalexalex

布尔类型

主要用来逻辑判断。

  • True
  • False
1
2
3
a = 12
b = 5
print( a > b ) # True

几个falsy值

  • ‘’
  • 0
  • []
  • ()
  • {}
  • None
  • False

格式化输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
name = input('name')
age = input('age')
job = input('job')
city = input('city')


info = '''
----------info of %s
Name: %s
Age : %s
Job : %s
City: %s
''' % (name,age,job,city)

print(info)

占位符

  • %s 就是string
  • %d 就是数字
  • %f 就是float

修改Age的占位符为 %d

1
2
3
4
5
6
7
程序报错

因为input方法接收的任何输入都是字符串

你应该这样,将输入的结果转换为数字

age = int(input('age'))

Py001_01_02Python变量_用户交互_注释

hello world

1
print('hello world')

变量

存储数据的中间结果,以备程序后续调用。

定义规范

  • 字母数字下划线的任意组合
  • 第一个字符不能是数字
  • 不能使用python的关键字做变量名(print,pass,or,not,and…)

命名习惯

驼峰

1
2
CattleId
FarmId

下划线

1
2
cattle_id
farm_id

特别low的方式

  • 变量名为中文、拼音 张三的年龄 = 22
  • 变量名过长 the_name_of_oldboy_girlfriend = ‘Lisa’
  • 变量名词不达意 name = ‘hjx’

常量

在你的程序运行中不变的量就是常量

很可惜在python中没有常量的定义。所以程序员约定俗成的把全部大写声明的变量定义为常量

1
CATTLE_AGE = 10

与用户交互

  • input
1
2
3
4
name = input("请输入你的名字")
print("hello" , name)
# 也可以这样,效果一样
print("hello" + name)

注释

python里注释使用 “#”

1
2
# 本行是注释
print("hello")

Py001_01_01编程语言介绍

机器语言

就是机器能看懂的语言,形如010101010010101010101010010101。

  • 优点:最底层,速度最快
  • 缺点:复杂,开发效率最低

汇编语言

  • 优点:比较底层,速度低于机器语言
  • 缺点:复杂,开发效率仅仅高于机器语言

高级语言

编译型

C,C++

  • 优点:如C++等语言在运行前必须经过编译后才能运行,编译后是机器可直接运行的二进制的代码。
  • 缺点:每次改动必须经过重新编译,跨平台性差

解释型

Python,JavaScript,Php

类似日常生活中的“同声翻译”,边翻译边运行,因此运行效率低.而且不能生成二进制文件,应用程序不能脱离解释器。

但是mac或linux上默认有python解释器。

  • 优点:跨平台开发,开发效率高
  • 缺点:运行效率低,依赖解释器(为什么效率低还如此火爆,因为现在的硬件水平上去了。)
    比如C语言执行一段程序0.001秒 如果python比它慢10倍那就是0.01秒(人类的最快反应时间是0.3s所以几乎感受不到)

MJ_001_01前端面经

由于公司宣布倒闭

所以不得不开始找工作,下面开始每场的面试经验分享,自我介绍略过。

面试是可以从中来感受企业的文化。有的令人怒不可遏,有的让人感受到礼仪。如果你被面的怒不可遏我建议直接走人。这样的公司就算你去了,你也迟早被同化。

注:如果写的有问题,请及时发邮件怼我trustfor@sina.cn

180807第一天(电面一家,约面2家)

1.先说电面的那家

  1. 什么是jsonp,什么是ajax
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
jsonp就是
1请求方创建一个script标签src指向响应方,并传递callback =回调函数名xxx
2响应方根据callback查询参数构造一个 xxx.call(undefined,传递的内容)
3浏览器接到响应,就会执行 xxx.call(undefined,传递的内容)
4请求方得到他想要的数据

ajax
实现原理就是使用XMLHttpRequest对象通过它来发请求
let request = new XMLHttpRequest();
request.open('get','/xxx');
request.send();
request.onreadystatechange = function(){
if(request.readyState === 4){
if(request.status >= 200 && request.status <300){
console.log(request.responseText);
}else{
console.log(request.status);
}
}
}
  1. promise用了吗?用来干啥的 async/await用过吗?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
promise就是解决 回调地域问题的,比如一些操作的校验 必须逐步成功才能往下走提交
window.ajax = function({url,method,body,headers}){
return new Promise(function(resolve,reject){
//ES6解构赋值
let request = new XMLHttpRequest();
request.open(method,url);
for(let key in headers){
let value = headers[key];
request.setRequestHeader(key,value);
}
request.send(body);
request.onreadystatechange = function(){
if(request.readyState === 4){
if(request.status >= 200 && request.status <300){
resolve.call(undefined,request.responseText)
}else{
reject.call(undefined,request.status)
}
}
}
});
}

async和await用法:简单说来就是 异步代码同步执行
function xxx(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}

async function f1() {
var x = await xxx(10);
console.log(x); // 10
}
f1();
  1. js继承是什么?es6的继承了解吗
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
其实我认为js是没有继承的,它是用function模拟的,继承的原理是基于原型链的。

1.我们知道大部分编程语言应该都有Object类型,一般都称为所有类型的基类(也就是类型的顶端)
2.每种类型都有一个共有属性 prototype也就是浏览器里的双下proto 这个属性里放置了一些属性或方法。它被称为原型
3.每个类型都有自己的原型(共有属性)prototype 比如Number有 toFixed
4.此时如果你构造一个类型他就会天生有toString() valueOf()
5.这就是原型链继承,它会逐级向上查找,如果自己本身有这个方法则使用,没有则继续查找,如果顶端Object的prototype上都没有,是属性就undefined调用方法就报错

es6的继承:虽然它有关键字 class让你看起来像java的继承
但是依然是假的,不信你可以查看浏览器里打印 依然是基于prototype的
此时就有一个问题如果我想要一个 共有属性 class怎么办?
如果是prototype 可以很方便的
// ES5
Human.prototype.s = '人类'

// ES6 对不起,不支持,有一种变通的写法
class Human{
constructor(name){
this.name = name
}
//麻烦不????
//麻烦不????
//麻烦不????
get s(){
return '人类'
}
}
  1. vue用过吗?能简单说下双向绑定的原理吗?

原文参考没有比这个更简单的了,如果只是为了面试请看第一章节,如果深入了解看后面我是没看。。。

  1. vue-router用过吗?原理是什么

就是前端路由,通过#分割前后端,详情请看文档比我全多了文档

原理是H5的History

  1. vue组件间通信?

我之前的总结

1
2
3
4
5
父-->子  props
子-->父 子组件emit触发事件xx 父组件 监听xx事件

如果是祖孙三代,孙子给爷爷发消息
就是两个父子关系 emit 非常麻烦所以有了vuex
  1. vuex用过吗?原理是什么

vuex

原理就是一个全局变量,反正就一份,你怎么改都是改的一份

  1. vue的v-if和v-show的区别
1
2
3
4
5
6
v-if 是决定html结构里是否有这个元素
v-show是切换元素的display属性

有性能问题
频繁切换用v-show
如果仅初始化一次的用v-if
  1. vue生命周期方法?

看官网吧!https://cn.vuejs.org/v2/guide/

  1. vue angular react区别
1
2
3
4
5
6
7
8
vue和angular都是双向绑定的
react是单项数据流

angular 从语法书写上可以明显看出MVC思想,它大而全,关键的是官方宣布半年进行一次版本迭代,需要持续跟进学习,适合于大型项目,但是学习成本高

vue 简单快速上手,小而美,渐进式的更新各个功能,对初学者友好,因为作者是中国的,而且据统计 外国用react的多,中国用vue的多。

react facebook的自己造的轮子,单项的数据流,vue也慢慢转向单项数据流,支持jsx语法。可以用class的方式定义组件。通过render渲染,学习路径陡峭
  1. 什么是闭包
1
2
3
4
5
6
7
8
function wrapper(){
var a = 1
function inner(){
a+=1
}
return inner
}
这就是闭包

2.直面的一个外派性质的公司

  1. 邮箱验证
1
2
3
4
5
6
7
var str = 'trustfor@sina.cn'
var reg = /^\w+@[a-z0-9]+\.[a-z]+$/i;
if(reg.test(str)){
//合法
}else{
//你丫写错了
}

如果你想了解正则

  1. 移动端页面怎么做适配
1
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  1. cookie是啥?前端数据存储了解吗?localStorage是啥?sessionStorage是啥区别呢?

cookie去看吧

session和持久化

  1. 了解数据解构吗?
1
2
3
4
5
6
7
队列(先进先出,请参考电影票是不是先买票的先走) 映射到数组就是 push() shift()

栈:后进先出,汉诺塔上面的盘子移走才能移动下面的盘子。映射到数组就是 push() pop()

树(二叉树/满二叉树/完全二叉树)

堆(最大堆/最小堆)
  1. 性能优化手段?
  • 后台设置gzip压缩
  • 后台设置cache-control 头指定过期时间(更详尽可以看)
  • 图片压缩合并(精灵图这是很久以前的了)
  • js压缩打包,css压缩打包,html压缩打包(webpack解决了这个问题)
  • dns预解析,减少同一域名解析时间
  • 图片懒加载,根据滚动距离高度来判断是否进行加载图片
  • 指定img的宽高,避免网速波动造成页面重排(腾地)
  • 异步加载组件vue

重复问题

  • 什么是闭包?
  • 手写ajax
  • promise
  • async/await
  • vue v-if和v-show区别
  • vue-router
  • vue组件传参
  • vue有哪些生命周期方法

3.直面的一个影视动漫相关的公司

  1. css import和link的区别

看去吧

  1. css隐藏元素的三种方式
  • 你可以将 opacity 设为 0
  • 将 visibility 设为 hidden
  • 将 display 设为 none
  • 将 position 设为 absolute 然后将位置设到不可见区域。
  1. vue适用于什么项目

单页面。开发周期短,项目成员少。看公司需求了。我觉得用啥都行

套用大志哥的送外卖例子:

在古代,你会选择飞毛腿
在有自行车的时候,你会选择骑车最快的
在现在买卖小哥都有了摩托,你会选择评论好的

结论就是:天下武功,唯快不破。你足够快就行

  1. less和sass的语法。写出你用的一些语法
  1. 移动页面1s加载的方案

看看别人的总结,肯定比我好

首屏优化

  1. 视频处理相关js了解吗? 太冷门了。。。
  • 放弃治疗

重复问题总结

  • jsonp
  • 手写ajax
  • v-if和v-show区别
  • 前端三大框架的区别
  • cookie和 持久化存储
  • 前端性能优化
  • 什么是闭包

180808第二天(约面2家)

1.一个大数据 小程序方向

  1. 主要问项目经验。实现原理,这个看具体项目

这个看你的项目了。用到啥就说啥

  1. 小程序生命周期

照着文档找呗!

重复问题总结

  • 闭包
  • vue基础知识点,组件传参 v-if v-show区别
  • ajax
  • promise
  • 前端性能优化

2.一个中厂sina你懂的

  1. display有哪些值
  • block
  • inline
  • inline-block
  • flex
  • table
  • none
  1. 定位相关
1
2
3
4
5
6
如果一个div有position:absolute是相对谁定位?

逐级向上的父元素
如果有position:absolute就相对它
如果有position:relative就相对它
都没有就相对顶级元素 body
  1. 左端固定右边自适应的布局

实现链接

  1. 各种居中方式 水平,垂直,水平垂直居中

各种布局

  1. css3动画有哪些属性

看文档。。。

  1. es6你都指定哪些新特性

请参考我总结的es6速学

重复问题总结

  • 闭包
  • ajax
  • promise
  • async/await
  • vue组件传参
  • 三大框架区别
  • cookie和持久化相关
  • 前端性能优化

180809第三天(约面3家)

1.一个中厂58你懂的

  1. css3 改变一个div的样子 transform有哪些方法

还是mdn全啊

  1. 左面图片右边汉字你有几种做法?
1
2
3
4
5
6
7
8
9
1. 一个div实现:背景图定位到左边加  padding-left
2. flex布局:最外层容器
display:flex;
justify-content:flex-start;
左面图片设置宽高,
右边flex-grow:1
3. 两个标签都左浮
4. position定位
5. table
  1. 正则过滤字符串里的 [“ ‘ 空格]
1
2
res = "aabbcc"
str = "\"\' aabbcc \'\""
  1. 给定一个字符串 aabcccddddcc 已知正则的实现请用replace输出为 2a1b3c4d2c的字符串

  2. vue子组件内有一个滚轮事件如何销毁

1
在生命周期的destroy里移除事件
  1. less/sass用过吗?
1
2
3
由于sass各种报错。我也不想死嗑在这种工具问题上。我用less,基于talkdata的iview就是用的less

答案是 sass通过配置是可以用的 需要装一个ruby的东西
  1. webpack了解吗?有哪些属性
1
2
3
4
5
6
entry 入口
output 输入路径
loads 加载器
plugs 插件

又问 用过什么!看你水平了。 当然是说你用的

重复问题总结

  • 双飞翼布局
  • 水平居中/垂直居中
  • vue组件通信
  • vuex
  • vue-router
  • v-if v-show
  • 双向绑定原理
  • promise
  • async/await
  • es6新特性有哪些

2.一个傲的像全球第一的不到30人的公司[好脉]果然是好卖

非常差的面试体验[中厂的新浪58人家也没像贵公司(不到30人的创业公司)这样]

  1. 开始「各种装」模式。垃圾回收的方式
1
2
3
4
可能真不会。我说把变量置空,移除事件。尽量用委托。事件里不要保存其他变量的引用。

还有呢?
又装了,这个一定是可以调的。(你可以回去看看。好吧!继续看你表演)
  1. 代码题
1
2
3
console.log(a)
var a = 1
答案 undefined 变量提升
  1. 代码题
1
2
3
4
5
6
7
8
9
console.log(a)
console.log(b)
{
var a = 1
let b = 2
}
答案
第一行undefined
第二行报错
  1. 代码题
1
2
3
4
5
6
7
8
9
{
var a = 1
let b = 2
}
console.log(a)
console.log(b)
答案
第一行 1
第二行报错
  1. 考察function传参。。。。无语了您是错的好吗?还让我自己浏览器试试。自己去试试再来面好吗?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function A(A){ console.log(1)}
function A(A,B,C){ console.log(2)}

A(1)
A(1,2,3)
A()
答案
2 同名函数会发生覆盖。

你传递多少个参数你不使用有意义?我真不知道啥区别!别逗我行吗?
无论先后调用A函数 都会执行第二个。您居然跟我说执行第一个?厉害

又开始嘲讽啦! 这个vue react angular变来变去都很简单。无外乎那么点东西。
(从没见过造轮子特别傲的人,但今天看见一个用别人轮子还那么傲的。vue作者都没那么狂。果然全球第一。)
  1. 函数传参的方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function a(x,y,z){}

a(x,y,z)
a.call(undefined,x,y,z)
a.apply(undefined,[x,y,z])

沉默了一小下,问call、apply区别
区别
call第一参数是this,第二个之后才是你实际传的参数
apply第一参数是this,第二个是你实际传的参数数组

他:嘲讽开始,还有其他方式吗?
我:不清楚。我就想看你说啥!
他:回去自己查查。
我:(我估计你自己都不知道)
  1. 如何实现css加载是怎样的
1
2
3
4
5
6
7
8
各浏览器表现不一致 
google是小姐姐 化了妆出门
ie是女汉子 出门在化妆

我就要加载了css在显示页面呢?

非要实现都一直你就隐藏呗。加载完了在display:block
又开始嘲讽啦 说这有5/6种呢 你自己回去查查。
  1. 又开始装啦! 问性能优化。怎么达到页面加载速度特快
1
2
3
我按之前的思路回答了,答的不好就不好呗!

又开始了,你回答的很范范。你可以去看看淘宝啊京东啊看他的页面结构抄他们的代码。
  1. 终于夸人了,我就觉得你这个问题回答的好(我醉了)

问埋点做过吗?如果细化到button级别怎么办。

1
事件委托呗。监听document 判断target.tagName是不是button

终于换了一个知书达理的面试官了,好的体验

  1. vue生命周期有几种(8种)
  2. v-if和 v-show区别
  3. js有几种数据类型(7)
  4. 如果实现vue的路由鉴权、菜单鉴权
1
2
3
4
5
6
7
第一种就是每次都发请求设置个cookie头

第二种
1. 登录的一瞬间后台返回 authList 存到sessionStorage里(加密一下,引个库肯定没问题)
authList = ["if0001","if0002","if0003"] 对应路由的name属性
2. 路由守卫里判断 to.name 是否在authList里
3. 分支处理
  1. 如何实现不用用户的不同菜单权限组
1
2
3
4
5
6
一、要么后天登录的时候给你生成

二、
1.在router定义的时候 自己定义个属性建议形如[if_authmenu] 公司前缀+权限名称 表示为这个路由是菜单
判断
2.生成路由菜单的时候说明已经登录了 权限数组在你这里 v-for的时候判断
  1. 路由有几种方式?什么是动态路由

看官网吧。

  1. H5有哪些新特性
  • worker 多线程的一个api
  • history 前端路由的实现
  • localStorage
  • sessionStorage
  1. 有没有对axios进行封装。也就是做统一的异常处理

然后面试着一半。就被需求会中断了。产品经理进来就占地。深刻的感受到啥叫野!

  1. axios发请求时为什么是两次
1
2
第一次是option方法  意思是询问 支持不支持我下面发送的方法
第二次是实际的get/put/post/delete等请求

重复问题总结

  • promise
  • async/await
  • v-router了解吗?有哪些方式
  • vuex原理
  • less/sass语法
  • webpack是否自己配置过?问我半天,咱公司自己配置的?我们也是vue-cli 厉害!

3.一个做区块链的挺厉害的公司包了三层办公。

也是非常好的体验!要求5-10年的,但我不够却说不在乎年限只要够优秀。

约的6点而且再三盛情邀请我去试试。cto面我先给我介绍公司现状。然后让我介绍。没有对比就没有伤害。 不知道比上家强多少倍

  1. 上来就算法。。。一紧张想错了整到快排了 50万个随机数的数组要求时间复杂度为O(n)求第三个最大的数
1
2
3
4
5
6
其实就是三次循环每次找最大值然后移除
第一次500,000 找到最大的 然后移除元素
第二次499,999 找到第二个最大的 然后移除元素
第三次499,998 找到第三个最大的 然后结束

时间复杂度 3n
  1. 找到匹配的右括号
1
2
3
4
5
6
7
8
str = '((()()(()(()()))((()))))'
起点为 index = 1 的左括号 找到对应的右括号索引

答案是利用堆栈知识
左括号代表进栈 x++
右括号代表出栈 x--

所以 x = 0 时 就是匹配的那个右括号对应的索引
  1. 隔行变色。同时变色的行是45度 斑马线的条纹
1
2
3
.xx:nth-child(2n){
线性渐变的代码。。。 我也不会
}
  1. 如何把表格里的数据给后台。数组形式
1
双重循环遍历成二维数组
  1. 如何添加参数发送一个请求
1
2
3
4
5
6
7
8
9
axios.post(url,param).then(
()=>{

}
).catch(
()=>{

}
)
  1. 如何实现一个树形组件,通过后台传递的格式如下内容
1
2
3
4
5
6
7
8
9
10
id      pid   cname
0100 null 北京
0101 0100 朝阳
0102 0100 海淀
0103 0100 昌平
0200 null 天津
0201 0200 和平
0202 0200 红桥
0203 0200 南开
又卡住了我。。。。
  1. 如何实现上下两部分。拖拽就可以改变上下两个div高度
1
又挂了。  iview-admin里有一个那么的组件

P020_02_python模块的导入

模块

很多时候,你发现你写的代码有很多重复内容这个时候你就要使用模块了

模块的导入

在同一目录下我们这样操作

  1. 新建模块文件 demo.py
1
2
3
4
5
6
7
内容如下:
print('in demo.py')

a = 'hello'

def read():
print('haha'+a)
  1. 新建调用模块的文件aa.py
1
2
3
4
5
6
7
8
9
10
11
import demo.py

#执行aa.py你会发现打印了 in demo.py

如果你多次导入demo模块呢?
import demo.py
import demo.py
import demo.py
import demo.py

# 依然只打印一次 in demo.py
  1. 如果调用demo.py里的方法
  • 找到模块
  • 创建这个模块的命名空间
  • 把文件中的内容放到命名空间里
1
2
3
import demo # 这句话的时候就是把demo.py的内容加载到内存里,同时demo里所有的内容只能通过demo这个命名空间来调用
demo.read() #
demo.a

为什么一个模块不会被重复导入

  • 当你导入一个模块的时候,会先去sys.modules里查看是否已经导入了这个模块
  • 如果没被导入,就依据sys.path路径去寻找模块找到了正常运行,没找到报错
  • 找到了就导入
  • 创建这个模块的命名空间
  • 把文件中的内容放到命名空间里
1
2
import sys
print(sys.modules.keys()) # 查看导入的模块

给模块其一个别名

1
2
import time as t
t.time()

导入多个模块

1
import sys,time,random,os

模块引入的一些编码规则

1
2
3
1. 先引入内置的
2. 扩展的如django
3. 自己实现的

from import的使用方式

1
2
3
4
5
6
7
之前是
import time
time.sleep()

你可以这样
from time import sleep
sleep()

回归之前的demo.py

1
2
3
4
5
6
7
8
from demo import read
# 此时无法访问demo.py里的 a变量 因为你单独导入了read方法
# 但是read方法里访问了 a变量 ,说明引入模块的时候会把a保存在内存里只是本模块访问不到


# 如果你在引入的地方定义同名read方法,那么导入的read方法就被覆盖
def read():
pass

另一种 from import *

但是这种非常不安全,不建议使用

1
2
3
4
import demo from *
# 相当于把里面的东西全部引入进来,可以不带命名空间之间使用
read()
print(a)

最后一种方式导入模块

  1. 我们又新建一个模块demo2.py
1
2
3
4
5
6
7
__all__ = ['a']
print('in demo2.py')

a = 'hello'

def read():
print('haha'+a)
  1. 引入新建的模块demo2
1
2
3
4
5
6
7
8
import demo2 from *
read() # 报错

# 因为在模块内部设置了 __all__
__all__是一个列表代表 import demo2 from *的形式导出的内容

因为刚刚只设置了 __all__ = ['a']
因此只有 a可用

双下all变量只跟 *关联

最后一个需求知识点

1
2
3
1.因为demo2.py里有一句 print('in demo2.py') 
2.所以在你导入demo2模块的时候 程序会打印 in demo2.py
3.需求就是 只在demo2.py里打印不在 被导入的文件里 打印这句话
  • 双下name

demo2.py里添加如下内容,并执行,发现打印

1
2
3
4
5
a = 'hello'
def read():
print('haha'+a)

print(__name__) # __main__

如果在别的地方导入demo2

1
2
3
import demo2

# 打印 demo2

完成需求只在本模块执行相关代码

1
2
3
4
5
6
a = 'hello'
def read():
print('haha'+a)

if __name__ == '__main__':
print('in demo2.py')

小结:

1
2
3
在模块xxx内部有一个变量 __name__
当我们直接运行这个模块xxx的时候 __name__ == '__main__'
当我们在其他文件内,引入这个模块xxx的时候,这个模块中的 __name__ =='模块的名字'

P020_01_python序列化模块

序列化模块

  • 序列化——转向一个字符串的数据类型
  • 序列——字符串

数据存储
网络上传输的时候

序列化:从数据类型==> 字符串的过程

反序列化:从字符串==>数据类型

重要的几个知识点 「*」代表重要程度

  • json *
  • pickle **
  • shelve ***
json通用序列化格式
  • 只有很少的一部分数据类型能够通过json转化成字符串
pickle
  • 所有python里的数据类型都可以转化成字符串格式
  • pickle序列化的内容只有python能理解
  • 且部分反序列化依赖代码

例如网游 魔兽世界你退出游戏了 但是下次登录你还会在原来的数据基础上。这些信息如血量蓝量背包的物品经验值都是对应一些数据类型并依赖一些模块存在服务器或者你本地

shelve
  • 序列化句柄
  • 使用句柄直接操作非常方便

json

内存相关

  • dumps 序列化方法
  • loads 反序列化方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import json

dic = {"k1":"v1"}

print(type(dic),dic)
# <class 'dict'> {'k1': 'v1'}

# 序列化
str_d = json.dumps(dic)
print(type(str_d),str_d)
# <class 'str'> {"k1": "v1"}

# 反序列化
dic_d = json.loads(str_d)
print(type(dic_d),dic_d)
# <class 'dict'> {'k1': 'v1'}

元组:序列化之后是列表,把元组序列号的内容反序列化后也是列表

set不能进行序列化:报错

文件相关:传递要序列话的内容,和文件句柄

  • dump
  • load
1
2
3
4
5
6
7
8
9
10
11
12
import json

dic = {"k1":"v1"}
f = open('fff','w',encoding='utf-8')
json.dump(dic,f) # 序列化后的字符串写入到文件里
f.close()


f = open('fff',encoding='utf-8')
res = json.load(f)
f.close()
print(res) # {'k1': 'v1'}

序列化的时候有中文咋办?

读取能正常但是你去看fff文件发现中文已经被转换了 {“k1”: “\u4e2d\u56fd”}

1
2
3
4
5
6
7
8
9
10
11
12
import json

dic = {"k1":"中国"}
f = open('fff','w',encoding='utf-8')
json.dump(dic,f) # 序列化后的字符串写入到文件里
f.close()


f = open('fff',encoding='utf-8')
res = json.load(f)
f.close()
print(res) # {'k1': '中国'}

解决dump时 中文会转换为byte编码的问题

  • ensure_ascii=False以指定的编码写入
1
2
3
4
5
6
7
8
9
10
11
12
import json

dic = {"k1":"中国"}
f = open('fff','w',encoding='utf-8')
json.dump(dic,f,ensure_ascii=False) # 序列化后的字符串写入到文件里
f.close()


f = open('fff',encoding='utf-8')
res = json.load(f)
f.close()
print(res)

注意如果你用json的demp和load只能一次性写入和读取

如果想要分次写入和读取就不能用dump和load

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 分次写入
import json
a = [{"k1":1},{"k2":22},{"k3":33}]
f = open('file','w')
for dic in a:
str_dic = json.dumps(dic)
f.write(str_dic+'\n')
f.close()

# 分次读取
b = []
f = open('file')
for line in f:
dic = json.loads(line.strip())
b.append(dic)
f.close()

pickle

  • pickle也有json模块里的 dump/dumps ,load/loads方法
  • pickle在dumps/dump的时候你是看不出来的(二进制内容)
  • 在调用dump/load 读写文件的时候要使用rb和wb模式
1
2
3
4
5
6
7
8
9
import pickle

dic = {"k1":"中国"}
str = pickle.dumps(dic)
print(str) # 一串二进制内容
# b'\x80\x03}q\x00X\x02\x00\x00\x00k1q\x01X\x06\x00\x00\x00\xe4\xb8\xad\xe5\x9b\xbdq\x02s.'
res = pickle.loads(str)
print(res)
# {'k1': '中国'}

由于pickle序列化之后是二进制内容所以读写的时候要rb和wb模式

1
2
3
4
5
6
7
8
9
10
11
import pickle
dic = {"k1":"中国"}
f = open('fff3','wb')
pickle.dump(dic,f) # 序列化后的字符串写入到文件里
f.close()


f = open('fff3','rb')
res = pickle.load(f)
f.close()
print(res)

pickle的dump和load可以分步序列化写入和读取 (json不行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pickle
dic = {"k1":"中国"}
dic2 = {"k2":"中国2"}
f = open('fff3','wb')
pickle.dump(dic,f) #
pickle.dump(dic2,f) #
f.close()


f = open('fff3','rb')
res = pickle.load(f)
res2 = pickle.load(f)
f.close()
print(res)
print(res2)

shelve

shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些。

shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。

1
2
3
4
5
6
7
8
9
10
import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'} #直接对文件句柄操作,就可以存入数据
f.close()

import shelve
f1 = shelve.open('shelve_file')
existing = f1['key'] #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)

这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB

1
2
3
4
5
import shelve
f = shelve.open('shelve_file', flag='r')
existing = f['key']
f.close()
print(existing)

由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。

1
2
3
4
5
6
7
8
9
10
import shelve
f1 = shelve.open('shelve_file')
print(f1['key'])
f1['key']['new_value'] = 'this was not here before'
f1.close()

f2 = shelve.open('shelve_file', writeback=True)
print(f2['key'])
f2['key']['new_value'] = 'this was not here before'
f2.close()

writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。

json补充知识 格式化输出

1
2
3
4
import json
data = {'username':['李华','二愣子'],'sex':'male','age':16}
json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False)
print(json_dic2)

P019_03_python常用模块三

os模块(不用背,用的时候查)

os模块是与操作系统交互的一个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2') 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","newname") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息
os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 运行shell命令,直接显示
os.popen("bash command).read() 运行shell命令,获取执行结果
os.environ 获取系统环境变量

os.path
os.path.abspath(path) 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。
即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小

注意:os.stat(‘path/filename’) 获取文件/目录信息 的结构说明

stat 结构:

1
2
3
4
5
6
7
8
9
10
st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。
st_uid: 所有者的用户ID。
st_gid: 所有者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。

sys模块

sys模块是与python解释器交互的一个接口

1
2
3
4
5
sys.argv           命令行参数List,第一个元素是程序本身路径(只能在命令行里执行,在ide里报错)
sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version 获取Python解释程序的版本信息
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称

异常处理和status

1
2
3
4
5
import sys
try:
sys.exit(1)
except SystemExit as e:
print(e)