python基础知识

python常见面试题

1 基础知识

1.1 Python中的不可变数据类型和可变数据类型是什么意思?

数值类型,字符串,列表,字典,元组,集合
可变类型: 集合,列表,字典
不可变类型: 字符串,元组,数值

可变数据类型:当数据类型对应的变量的值发生改变的时候,其对应的内存地址不变
不可变数据类型:当该数据类型对应的变量的值发生改变的时候, 其所对应的内存地址发生改变

1.2 请简述Python中is和==的区别

is比较的是两个对象的地址值,也就是说两个对象是否为同一个实例对象;而==比较的是对象的值是否相等,其调用了对象的__eq__()方法。

1.3 function(args, **kwargs)中的args和**kwargs分别是什么意思?

*args:可选的位置参数
**kwargs: 可选的关键词参数
python中默认的函数参数顺序: 必选参数,默认参数,位置参数,关键词参数

1.4 面向对象中__new__和__init__的区别

__new__(): new的作用是创建一个类的实例化对象
__init__():对new创建的实例进行初始化

1.5 Python子类在继承多个父类时,如多个父类有同名方法,子类继承哪个方法?

默认继承第一个父类的同名方法

1.6 Python中如何避免死锁?

1 什么是锁?
    全局解释器锁(GIL),在同一个进程中只要有一个线程获得了全局解释器(cpu)的使用权限,那么其他的线程就必须等到该线程的全局解释器(cpu)的使用权小时候,才能使用全局解释器。
2 全局解释器锁的好处?
    a. 避免了大量的加锁解锁
    b. 是数据更加安全,解决多线程间数据完整性和状态同步
3 全局解释器锁的缺点
    多核处理器退化为单核处理器,只能并发不能并行
    (同一时刻的某个进程下的某个线程只能被一个cpu所处理,所以在GIL锁下的线程只能被并发,不能被并行)
4 出现死锁的原因?
    当多个线程同时获取多个锁的时候,容易造成资源的相互竞争,一个线程一直阻塞等待另一个线程释放锁,造成死锁。

1.6.1 多线程锁示例(互斥锁)

# coding:utf-8

import threading
import time

if __name__ == '__main__':

    x_lock = threading.Lock()
    y_lock = threading.Lock()

    # def thread_1():
    #     while True:
    #         with x_lock:
    #             print("thread_1 acquire x_lock, sleep: %s s" % 1)
    #             with y_lock:
    #                 print("thread_1 acquire y_lock...")
    #                 time.sleep(1)
    #
    # def thread_2():
    #     while True:
    #         with y_lock:
    #             print("thread_2 acquire y_lock, sleep: %s s" % 1)
    #             while x_lock:
    #                 print("thread_2 acquire x_lock...")
    #                 time.sleep(1)
    #
    #
    # t1 = threading.Thread(target=thread_1)
    # t1.start()
    # t2 = threading.Thread(target=thread_2)
    # t2.start()
    x_lock = threading.Lock()
    y_lock = threading.Lock()
    def thread_3():
        while True:
            x_lock.acquire()
            print("thread_3 acquire x_lock, sleep: %s s" % 1)
            time.sleep(1)
            y_lock.acquire()
            print("thread_3 acquire y_lock...")
            time.sleep(1)
            y_lock.acquire()
            x_lock.acquire()

    def thread_4():
        while True:

            y_lock.acquire()
            print("thread_4 acquire y_lock, sleep: %s s" % 1)
            x_lock.acquire()
            print("thread_4 acquire x_lock...")
            time.sleep(1)
            x_lock.acquire()
            y_lock.acquire()

    t3 = threading.Thread(target=thread_3)
    t3.start()
    t4 = threading.Thread(target=thread_4)
    t4.start()
    
####################################result#######################################
thread_3 acquire x_lock, sleep: 1 s
thread_4 acquire y_lock, sleep: 1 s
可以发现发生了死锁:
    thread_3在获取 y_lock 的锁的时候, 发现该锁已经被 thread_4 获取了, 造成 thread_3 一直在等待 y_lock.
    thread_4在获取 x_lock 的锁的时候, 发现该锁已经被 thread_3 获取了, 造成 thread_4 一直在等待 x_lock.

1.6.2 多线程可重入锁

1.6.3 如何避免死锁的发生?

1. 获取锁的时候加一个超时参数, 例如 lock.acquire(timeout=10)
2. 为程序中的每一个锁分配一个唯一的id
    方法: 使用上下文管理器
# coding: utf-8

import threading
import time
from contextlib import contextmanager

# Thread-local state to stored information on locks already acquired
_local = threading.local()


@contextmanager
def acquire(*locks):
    # Sort locks by object identifier
    locks = sorted(locks, key=lambda x :id(x))

    # Make sure lock order of previously acquired locks is not viloated
    acquired = getattr(_local, "acquired", [])
    if acquired and max(id(lock) for lock in acquired) >= id(locks[0]):
        raise RuntimeError('Lock Order Violation')

    # Acquire all of the locks
    acquired.extend(locks)
    _local.acquired = acquired
    print("acquired: %s" % acquired)
    try:
        for lock in locks:
            print("acquired lock: %s" % lock)
            lock.acquire()
        yield
    finally:
        # Release locks in reverse order of acquisition
        for lock in reversed(locks):
            lock.release()
        del acquired[-len(locks):]


if __name__ == '__main__':
    x_lock = threading.Lock()
    y_lock = threading.Lock()

    def thread_1():
        while True:
            try:
                with acquire(x_lock, y_lock):
                    print("thread_1 acquired x_lock, y_lock: ", getattr(_local, "acquired", []))
                    time.sleep(1)
            except:
                print("thread_1 lock error")
            # time.sleep(1)
    def thread_2():
        time.sleep(0.5)
        while True:
            try:
                with acquire(y_lock, x_lock):
                    print("thread_2 acquired y_lock, x_lock: ", getattr(_local, "acquired", []))
                    time.sleep(1)
            except:
                print("thread_2 lock error")
            # time.sleep(1)
            # print("_local acquired: %s" % getattr(_local, "acquired", []))
    t1 = threading.Thread(target=thread_1)
    t1.start()
    t2 = threading.Thread(target=thread_2)
    t2.start()



1.7 排序算法

1.7.1 常见的排序算法

  1. 冒泡排序
  2. 快速排序
  3. 归并排序
  4. 堆排序
  5. shell排序
  6. 二叉树排序

1.7.2 以上排序算法的时间/空间复杂度,稳定性如何?

2 字符串和数字

2.1 s=“hfkfdlsahfgdiuanvzx”, 对s去重并排序。adfghiklnsuvxz

s="hfkfdlsahfgdiuanvzx"

# 方法 1 
result = "".join(set(s)) 

# 方法 2
list1 = list(set(s))
result = sorted(list1, key=lambda x: ord(x)) # 或者 sorted(list1) 从小到大
result = sorted(list1, key=lambda x: -ord(x)) # 从大到小

2.2 试判定给定的字符串 s 和 t 知否满足 s 中所有字符都可以替换为 t 中的所有的字符?

换个问法: s 和 t 是否是同构的

ssss

你可能感兴趣的:(python,python)