11. 简述面向对象中__new__和__init__区别
__init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值。__new__是在实例创建(__init__)之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法。用来申请内存的。
例子,使用 Python 实现单例模式(装饰器实现):
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class Cls(object):
def __init__(self):
pass
cls1 = Cls()
cls2 = Cls()
print(id(cls1) == id(cls2))
out:
True
这里的核心思想就是在__init__执行之前给他先判断一遍是否已经有了实例对象了。
那么,因为__new__就是在__init__之前执行的,所以可以直接使用__new__来实现。
代码如下:
class A(object):
instance = None
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = object.__new__(cls, *args, **kwargs)
return cls.instance
def __init__(self):
pass
A1 = A()
A2 = A()
print(id(A1) == id(A2))
out:
True
补充:
-
__new__至少要有一个参数cls,代表当前类,此参数在实例化时由 Python 解释器自动识别 -
__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过 super(当前类名, cls))__new__出来的实例,或者直接是 object 的__new__出来的实例 -
__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值 -
如果
__new__创建的是当前类的实例,会自动调用__init__函数,通过 return 语句里面调用的__new__函数的第一个参数是 cls 来保证是当前类实例,如果是其他类的类名,那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。
12. with 是个什么东西
上下文管理器:
帮助使用者完成一些代码
包括开始和结束的操作
使用者做执行的操作
一些常用的上下文管理的语句:with …… as ……
结合起来就是上下文管理器
如何自定义一个上下文管理器:
姿势 1:
class Resources():
def __enter__(self):
print("进入")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("离开")
def operate(self):
print('执行')
with Resources() as res:
res.operate()
res.operate()
print("执行结束")
print("结束")
out: 进入 执行 执行 执行结束 离开 结束
上面的那个太复杂了,居然要定义一个类!虽然看起来蛮清爽的。但是作为程序员怎么能不偷懒呢。
所以有人给我们写好了contextlib.contextmanager来偷懒了
姿势 2:
可以理解为就是在我们正式执行某个操作前的一些预先准备的动作。
显然,想到了装饰器,但是装饰器不能停下来啊。
所以我们又想到了 yield 生成器。
import contextlib
@contextlib.contextmanager
def open_file(filename,mode):
print("上文管理")
f = open(filename,mode)
try:
yield f
print("下文管理")
except Exception as e:
print(e)
finally:
f.close()
with open_file("demo.txt","r") as f:
text = f.read()
print(text)
print("全部执行结束")
out: 上文管理 文本内容 下文管理 全部执行结束
13. lambda 和列表推导式
需求:将 1-5 平方后,先使用map()打印出来,然后取比 10 大的数
lst = [1, 2, 3, 4, 5]
res = map(lambda x: x ** 2, lst)
print(res)
# for i in res:
# print(i)
print([i for i in res if i > 10])
out:
<map object at 0x00000164579EE608>> [16, 25]
如果放开注释,则下面的语句输出为空。
Python2 中 map 返回列表 Python3 中 map 返回迭代器
所以若放开注释,就输出空列表。
补充:
map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新==迭代器==。
14. 随机数
import random
import numpy as np
# [10,20]的随机整数,双闭区间
result = random.randint(10, 20)
# 5个随机小数(高斯分布)
res = np.random.randn(5)
# [0,1)的随机小数,左闭右开
ret = random.random()
print("[10,20]正整数:", result)
print("5个随机小数:", res)
print("[0,1)随机小数:", ret)
[10,20]正整数: 15 5 个随机小数: [ 0.74183062 -0.71999601 2.36063785 0.81164776 0.48217159] [0,1)随机小数: 0.9043009242501265
注意区间~~~
不记得就看看源码,哈哈。
15. 字符串不转义
先看几个常见的转义:
| 转义字符 | 作用描述 | 使用率 |
|---|---|---|
\ | 续行符 | * |
\\ | 反斜杠符号(\) | *** |
\' | 单引号 | ***** |
\" | 双引号 | ***** |
\n | 换行 | ***** |
\t | 横向制表符 | ***** |
\r | 回车 | ***** |
不要转义的话,就在字符串引号前面加 r 就可以了:
string1 = r'~!@#$?\'/'
string2 = '~!@#$?\'/'
print(string1)
print(string2)
out:
~!@#$?'/ ~!@#$?'/
补充:
关于 Python 的单引号和双引号:
如果想定义一个字符串中有单引号:
姿势 1:使用单引号和转义
my_str = 'I\'m a student'
姿势 2:不使用转义,使用双引号直接定义
my_str = "I'm a student"
如果想定义一个字符串包含双引号:
姿势 1:使用双引号和转义
my_str = "Jason said \"I like you\""
姿势 2:不使用转义字符,利用单引号直接进行定义
my_str = 'Jason said "I like you"'
综上所述:
要包含什么,就用另一个。。。
至于转义,随便用哪个就行了。
16. 正则小试牛刀
import re
string = '<div class="nam">中国</div>'
res = re.findall(r'<div class=".*">(.*?)</div>', string)
print(res)
out:
['中国']
知识点:
.表示匹配单字符(万能匹配,什么都可以匹配),但是不能匹配\n*表示匹配 0 或任意个前面的字符(+是匹配 1 或任意个;?是匹配 0 或 1 个)?表示非贪婪- 括号是提取文本的
17. 断言
assert()断言方法,
断言成功,则程序继续执行,断言失败,则程序报错
a = 3
assert (a > 1)
print("断言成功,继续执行")
b = 4
assert b == a
print("断言失败,报错")
out:
断言成功,继续执行 Traceback (most recent call last): File "D:/PyCharm Workspace/Python 爬坑/017-断言.py", line 6, in
assert b == a AssertionError
18. 数据库去重
数据表 student 有 id,name,score,city 字段,其中 name 中的名字可有重复,需要消除重复行,请写 sql 语句
select distinct name from student
19. 10 个 Linux 常用命令
ls pwd cd touch rm mkdir top cp mv cat more grep echo
-
grep 是 linux 系统中 grep 命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。grep 全称是 Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。
-
echo 命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。
20. python2 和 python3 区别?列举 5 个
-
Python3 使用 print 必须要以小括号包裹打印内容,比如 print('hi')
Python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容,比如 print 'hi'
-
python2 range(1,10)返回列表,python3 中返回迭代器,节约内存
-
python2 中使用 ascii 编码,python 中使用 utf-8 编码
-
python2 中 unicode 表示字符串序列,str 表示字节序列
python3 中 str 表示字符串序列,byte 表示字节序列
-
python2 中为正常显示中文,引入 coding 声明,python3 中不需要
-
python2 中是 raw_input()函数,python3 中是 input()函数