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

补充:

  1. __new__至少要有一个参数cls,代表当前类,此参数在实例化时由 Python 解释器自动识别

  2. __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过 super(当前类名, cls))__new__出来的实例,或者直接是 object 的__new__出来的实例

  3. __init__有一个参数self,就是这个__new__返回的实例,__init____new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

  4. 如果__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. 正则小试牛刀

中国\,用正则匹配出标签里面的内容(“中国”),其中 class 的类名是不确定的
import re

string = '<div class="nam">中国</div>'

res = re.findall(r'<div class=".*">(.*?)</div>', string)

print(res)

out:

['中国']

知识点:

  1. .表示匹配单字符(万能匹配,什么都可以匹配),但是不能匹配\n
  2. *表示匹配 0 或任意个前面的字符(+是匹配 1 或任意个;是匹配 0 或 1 个)
  3. 表示非贪婪
  4. 括号是提取文本的

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 个

  1. Python3 使用 print 必须要以小括号包裹打印内容,比如 print('hi')

    Python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容,比如 print 'hi'

  2. python2 range(1,10)返回列表,python3 中返回迭代器,节约内存

  3. python2 中使用 ascii 编码,python 中使用 utf-8 编码

  4. python2 中 unicode 表示字符串序列,str 表示字节序列

    python3 中 str 表示字符串序列,byte 表示字节序列

  5. python2 中为正常显示中文,引入 coding 声明,python3 中不需要

  6. python2 中是 raw_input()函数,python3 中是 input()函数