Python面试基础(一)

列表排序

list0 = [31, 24, 6, 3, 10, 19, 2]
list0.sort()  # 升序排列
list0.sort(reverse=True)  # 降序排列
print(list0)

反转

如果是列表的话,可以直接用list.reverse()来实现,其他可以考虑range(len(list), -1, -1)

Magic Method

多重继承(菱形继承)

理解两个概念:
supper和mro(method resolution order)
super指的是 MRO 中的下一个类,而不是父类。 ## 这一点很重要

# -*- coding: utf-8 -*-

class A(object):
    def __init__(self):
        print('welcome class A')

class B(A):
    def __init__(self):
        print('welcome class B')
        super(B, self).__init__()

    def extral(self):
        print('welcome to extral B')

class C(A):
    def __init__(self):
        print('welcome class C')
        super(C, self).__init__()

    def extral(self):
        print('welcome to extral C')

class D(C, B):
    def __init__(self):
        super(D, self).__init__()

if __name__ == '__main__':
    # print(D.mro())
    class_a = A()
    class_b = B()
    class_c = C()
    class_D = D()
    class_D.extral()

输出:
welcome class A
welcome class B
welcome class A
welcome class C
welcome class A
welcome class C
welcome class B
welcome class A
welcome to extral C

如果把C类中super那一行注释掉,则输出变成:
welcome class A
welcome class B
welcome class A
welcome class C
welcome class C
welcome to extral C

最后,对于在子类中调用父类方法,要么直接使用父类名来调用方法,要么在子类中用super,保持一致,最好不要混用。

python单例模式的实现

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

在 Python 中,我们可以用多种方法来实现单例模式:

  1. 使用模块
  2. 使用 new
  3. 使用装饰器(decorator)
  4. 使用元类(metaclass)

模块

我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。

# my_singleton.py
class Singleton(object):
    def foo():
        pass

my_singleton = Singleton()

# 然后在其他模块中调用直接采用如下格式
from my_singleton import my_singleton
my_singleton.foo()

new

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  
        return cls._instance  

class MyClass(Singleton):  
    a = 1

装饰器

from functools import wraps
def singleton(cls):
    instances = {}
    @wraps(cls)
    def getinstance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return getinstance

@singleton
class MyClass(object):
    a = 1

metaclass

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]
# Python2
class MyClass(object):
    __metaclass__ = Singleton
# Python3
class MyClass(metaclass=Singleton):
    pass

copy.copy和copy.deepcopy

copy.copy: 只拷贝父对象,不会拷贝对象的内部的子对象
copy.deepcopy: 拷贝对象及其子对象

a = [1,2,3,4,['a','b']]
b = copy.copy(a)
c = copy.deepcopy(a)
a.append(5)
a[4].append('c')
print(b)
print(c)

# 输出
[1,2,3,4,['a','b','c']]
[1,2,3,4,['a','b']]

列表去重

# 方法一:转集合再转列表,会更改顺序
org_list = [81, 24, 25, 8, 39, 24, 35, 35, 1, 8]
return list(set(org_list))

# 方法二:字典的fromkeys,会更改顺序
org_list = [81, 24, 25, 8, 39, 24, 35, 35, 1, 8]
return {}.fromkeys(org_list).keys()  # python 2.x
# 如果是python 3.x版本,则换成return list({}.fromkeys(org_list).keys())

# 方法三:sort,保持顺序
org_list = [81, 24, 25, 8, 39, 24, 35, 35, 1, 8]
new_list = list(set(org_list))
new_list.sort(key=org_list.index)
return new_list

# 方法四:函数和列表推导,保持顺序
org_list = [81, 24, 25, 8, 39, 24, 35, 35, 1, 8]
new_list = []
for value in org_list:
    if value not in new_list:
        new_list.append(value)
return new_list
# 有一种列表推导的方法跟这个类似
org_list = [81, 24, 25, 8, 39, 24, 35, 35, 1, 8]
new_list = []
[new_list.append(i) for i in org_list if i not in new_list]
return new_list

# 方法五:reduce,保持顺序
org_list = [81, 24, 25, 8, 39, 24, 35, 35, 1, 8]
func = lambda x,y:x if y in x else x+[y]
return functools.reduce(func, [[]]+org_list)

append和extend的区别

append(object) —— object可以是str,list,dict等,把object作为一个整体追加在list的末尾
extend.(iterable) — 一个可迭代的对象,把这个对象的每个元素分别追加到list的末尾

org_list = ['welcome', 'to']
org_list.append(['my', 'home'])
print(org_list)  # ['welcome', 'to', ['my', 'home']]

org_list = ['welcome', 'to']
org_list.extend(['my', 'home'])
print(org_list)  # ['welcome', 'to', 'my', 'home']

global和nonlocal

global关键字用来在函数或其他局部作用域中使用全局变量。但是如果不修改全局变量也可以不使用global关键字

  1. 声明全局变量,如果在局部要对全局变量修改,需要在局部也要先声明该全局变量
# -*- coding: utf-8 -*-

gcount = 1

def global_test():
    global gcount
    gcount += 2
    print(gcount)

global_test()

上面的例子如果在函数不声明全局变量,则会报错。

  1. 在局部如果不声明全局变量,并且不修改全局变量。则可以正常使用全局变量
gcount = 0

def global_test():
    print(gcount)

global_test()

而nonlocal这个关键字是python3新引入的,之前如果要更改外部作用域里的变量,最简单的办法就是将其放入全局作用域,用global关键字引入该变量。
现在只要在闭包内用nonlocal声明变量,就可以让解释器在外层函数中查找变量名了。

def a():
    x = 1
    def b():
        nonlocal x
        x += 1
        print(x)
    return b

a()()

你可能感兴趣的:(Python面试基础(一))