Python开发面试题(一)

一、深信服python开发工程师

1.python浅拷贝和深拷贝

无论是哪种拷贝都是对原对象的拷贝,其本质区别是对原对象的地址拷贝还是值的拷贝。

深拷贝就是对原对象的地址拷贝,生成了一份与原对象不同的地址的对象,修改原对象中的任何值都不会影响深拷贝的对象的值。

浅拷贝就是对原对象的值拷贝,地址仍是一个指针指向原对象的地址,浅拷贝或者原对象的值发生改变,那原对象和浅拷贝对象的值都会随着被改变。

浅拷贝——copy.copy   深拷贝——copy.deepcopy

    1.2 补充概念

可变对象:一个对象在不改变其所指向的地址前提下,可以修改其执行的地址中的值

不可变对象:一个对象指向的地址上的值是不能修改的,如果修改了就是它执行的地址就改变了,相当于将对象的值复制出来一份,然后做了修改后存到另一个地址上了。

区别:可变对象修改了值,不会新建一个内存地址的对象,而不可变对象修改了值,是复制了一份新的内存地址,原始地址的值不会被改变。

不可变元素——int,float,complex,long,str,unicode,tuple    可变原生——list

例题:

import copy

a = [1, 2, 3, 4, ['a', 'b']]

b = a #赋值,传对象的引用

c = copy.copy(a) #浅拷贝,对象拷贝

d = copy.deepcopy(a) #深拷贝,对象拷贝

a.append(5) #修改对象a,列表末尾添加数字5

a[4].append('c') #修改对象a中的列表['a', 'b']

print('a= ', a)

print('b= ', b)

print('c= ', c)

print('d= ', d)

输出结果:

a = [1, 2, 3, 4, ['a', 'b', 'c'], 5] #修改了原始对象,变为修改后的列表

b = [1, 2, 3, 4, ['a', 'b', 'c'], 5] #对象的引用,对象的任何值变化都随着变化

c = [1, 2, 3, 4, ['a', 'b', 'c']] #浅拷贝,不可变元素不能改变,可变元素随着原始对的变化而变化了

d = [1, 2, 3, 4, ['a', 'b']] #深拷贝,原始对象的值发生任何变化,深拷贝新的对象内存地址不会发生任何变化

2.django的生命周期

前端请求->nginx->uwsgi.->中间件->url路由->view视图->orm->拿到数据返回给view->

试图将数据渲染到模板中拿到字符串->中间件->uwsgi->nginx->前端渲染

中间件:可以处理所有的请求内容,即是一个类,共有5个方法:

            ①process_request

            ②process_response

            ③process_view

            ④process_exception

            ⑤process_render_template

    执行顺序:

    1. process_request:在请求到达视图函数之前调用。

    2. process_view:在调用视图函数之前调用。

    3. 视图函数运行。

    4. 如果视图函数运行过程中出现异常,则调用process_exception。

    5. 如果视图函数返回一个TemplateResponse或其子类实例,则调用       process_template_response。

    6. process_response:在响应返回给客户端之前调用。

3.进程和线程的区别

    ①进程是操作系统资源分配的最小单位,而线程是处理器任务调度和执行的最小单位。

    ②一个进程可以包含多个线程,线程之间共享进程的资源,但每个线程都有自己的栈空间和寄存器。

    ③线程共享本进程的地址空间,而进程之间是独立的地址空间。

    ④线程共享本进程的资源如内存、I/O、cpu等,不利于资源的管理和保护,而进程之间的资源是独立的,能很好地进行资源管理和保护。

    ⑤多进程要比多线程健壮,一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。

    ⑥每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口,执行开销大。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,执行开销小。

   

4.知道哪些设计模式

    ①简单工厂模式结构

        Factory:工厂角色-负责实现创建所有实例的内部逻辑.

        Product:抽象产品角色-是所创建的所有对象的父类,负责描述所有实例所共有的公共接口。

        ConcreteProduct:具体产品角色-是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。

        结构图:

         时序图:

        工厂模式总结:

            (1)适用场景

            输出的产品是标准品,谁来做都可以。

            (2)举例

            常见的数据库连接工厂,SqlSessionFactory,产品是一个数据库连接,至于是oracle提供的,还是mysql提供的,都能让通过sql来操作数据。

            (3)注意事项

            项目初期,软件结构和需求都没有稳定下来时,不建议使用此模式,因为其劣势也很明显,增加了代码的复杂度,增加了调用层次,增加了内存负担。所以要注意防止模式的滥用。

            (4)简单实现

​
package FactoryMethod;
public class FactoryPattern
{
    public static void main(String[] args)
{
        Factory factory = new ConcreteFactoryA();
        Product product = factory.createProduct();
        product.use();
    }
}
//抽象产品:提供了产品的接口
interface Product
{
    public void use;
}
//具体产品A:实现抽象产品中的抽象方法
class ConcreteProductA implements Product
{
    public void use()
{
        System.out.println("具体产品A显示...");
    }
}
//具体产品B:实现抽象产品中的抽象方法
class ConcreteProductB implements Product
{
    public void use()
{
        System.out.println("具体产品B显示...");
    }
}
//抽象工厂:提供了厂品的生成方法
interface Factory
{
    public Product createProduct();
}
//具体工厂A:实现了厂品的生成方法
class ConcreteFactoryA implements AbstractFactory
{
    public Product createProduct()
{
        System.out.println("具体工厂A生成-->具体产品A.");
        return new ConcreteProductA();
    }
}
//具体工厂B:实现了厂品的生成方法
class ConcreteFactoryB implements AbstractFactory
{
    public Product createProduct()
{
        System.out.println("具体工厂B生成-->具体产品B.");
        return new ConcreteProductB();
    }
}

         

        ②单例模式——Singleton

        结构图:

        时序图:

        (1)优缺点

            优点:全局只有一个实例,便于统一控制,同时减少了系统资源开销。

            缺点:没有抽象层,扩展困难。

        (2)应用场景

            适合需要做全局统一控制的场景,例如:全局唯一的编码生成器

        (3)注意事项

            只对外提供公共的getlnstance方法,不提供任何公共构造函数

        (4)简单实现

public class Singleton
{
    private static volatile Singleton instance=null;    //保证 instance 在所有线程中同步
    private Singleton(){}    //private 避免类在外部被实例化
    public static synchronized Singleton getInstance()
{
        //getInstance 方法前加同步
        if(instance == null)
        {
            instance = new Singleton();
        }
        return instance;
    }
}

        ③装饰模式——decorator 

                Component:抽象构件

                ConcreteComponent:具体构件

                Decorator:抽象装饰类

                ConcreteDecorator:具体装饰类

        结构图:

        时序图:

        (1)优缺点

            优点: 比继承更加灵活(继承是合度很大的静态关系),可以动态的为对象增加职责,可以通过使用不同的装饰器组合为对象扩展N个新功能,而不会影响到对象本身。缺点: 当一个对象的装饰器过多时,会产生很多的装饰类小对象和装饰组合策略,增加系统复杂度,增加代码的阅读理解成本

        (2)适用场景

            适合需要 (通过配置,如: diamond) 来动态增减对象功能的场景。适合一个对象需要N种功能排列组合的场景 (如果用继承,会使子类数量爆炸式增长)

        (3)注意事项

            一个装饰类的接口必须与被装饰类的接口保持相同,对于客户端来说无论是装饰之前的对象还是装饰之后的对象都可以一致对待。

            尽量保持具体构件类Component作为一个“轻”类,也就是说不要把太多的逻辑和状态放在具体构件类中,可以通过装饰类。

        (4)简单实现

package decorator;
public class DecoratorPattern
{
    public static void main(String[] args)
{
        Component component = new ConcreteComponent();
        component.operation();
        System.out.println("---------------------------------");
        Component decorator = new ConcreteDecorator(component);
        decorator.operation();
    }
}
//抽象构件角色
interface  Component
{
    public void operation();
}
//具体构件角色
class ConcreteComponent implements Component
{
    public ConcreteComponent()
{
        System.out.println("创建具体构件角色");       
    }   
    public void operation()
{
        System.out.println("调用具体构件角色的方法operation()");           
    }
}
//抽象装饰角色
class Decorator implements Component
{
    private Component component;   
    public Decorator(Component component)
{
        this.component=component;
    }   
    public void operation()
{
        component.operation();
    }
}
//具体装饰角色
class ConcreteDecorator extends Decorator
{
    public ConcreteDecorator(Component component)
{
        super(component);
    }   
    public void operation()
{
        super.operation();
        addBehavior();
    }
    public void addBehavior()
{
        System.out.println("为具体构件角色增加额外的功能addBehavior()");           
    }
}

        ④策略模式——strategy

                Context: 环境类

                Strategy: 抽象策略类

                ConcreteStrategy: 具体策略类

        结构图:

        时序图:

        (1)优缺点

            优点: 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为。干掉复杂难看的if-else。

            缺点: 调用时,必须提前知道都有哪些策略模式类,才能自行决定当前场景该使用何种策略。

        (2)试用场景

            一个系统需要动态地在几种可替换算法中选择一种。不希望使用者关心算法细节,将具体算法封装进策略类中。

        (3)注意事项

            一定要在策略类的注释中说明该策略的用途和适用场景。

        (4)简单实现

package strategy;
public class StrategyPattern
{
    public static void main(String[] args)
{
        Context context = new Context();
        Strategy strategyA = new ConcreteStrategyA();
        context.setStrategy(strategyA);
        context.algorithm();
        System.out.println("-----------------");
        Strategy strategyB = new ConcreteStrategyB();
        context.setStrategy(strategyB);
        context.algorithm();
    }
}
//抽象策略类
interface Strategy
{   
    public void algorithm();    //策略方法
}
//具体策略类A
class ConcreteStrategyA implements Strategy
{
    public void algorithm()
{
        System.out.println("具体策略A的策略方法被访问!");
    }
}
//具体策略类B
class ConcreteStrategyB implements Strategy
{
  public void algorithm()
{
      System.out.println("具体策略B的策略方法被访问!");
  }
}
//环境类
class Context
{
    private Strategy strategy;
    public Strategy getStrategy()
{
        return strategy;
    }
    public void setStrategy(Strategy strategy)
{
        this.strategy=strategy;
    }
    public void algorithm()
{
        strategy.algorithm();
    }

        ⑤代理模式——proxy

                Subject: 抽象主题角色

                Proxy: 代理主题角色

                RealSubject: 真实主题角色

        结构图:

        时序图:

        (1)优缺点

            优点:代理可以协调调用方与被调用方,降低了系统的耦合度。根据代理类型和场景的不同,可以起到控制安全性、减小系统开销等作用。

            缺点: 增加了一层代理处理,增加了系统的复杂度,同时可能会降低系统的相应速度。

        (2)试用场景

            理论上可以代理任何对象,常见的代理模式有:

                远程(Remote)代理: 为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又叫做大使Ambassador).

                虚拟(Virtual)代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。

                Copy-on-Write代理: 它是虚拟代理的一种,把复制(克隆) 操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。

                保护(Protect or Acess)代理: 控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。

                缓冲(Cache)代理: 为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。

                防火墙(Firewal)代理: 保护目标不让恶意用户接近.同步化(Svnchronization)代理: 使几个用户能够同时使用一个对象而没有冲突智能引用(Smart Reference)代理: 当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等.

        (3)简单实现

package proxy;
public class ProxyPattern
{
    public static void main(String[] args)
{
        Proxy proxy = new Proxy();
        proxy.request();
    }
}
//抽象主题
interface Subject
{
    void request();
}
//真实主题
class RealSubject implements Subject
{
    public void request()
{
        System.out.println("访问真实主题方法...");
    }
}
//代理
class Proxy implements Subject
{
    private RealSubject realSubject;
    public void request()
{
        if (realSubject==null)
        {
            realSubject=new RealSubject();
        }
        preRequest();
        realSubject.request();
        afterRequest();
    }
    public void preRequest()
{
        System.out.println("访问真实主题之前的预处理。");
    }
    public void afterRequest()
{
        System.out.println("访问真实主题之后的后续处理。");
    }
}

         ⑥观察者模式——observer

                        Subject:目标

                        ConcreteSubject:具体目标

                        Observer:观察者

                        ConcreteObserver:具体观察者

        结构图:

        时序图:

        (1)优缺点

            优点: 将复杂的串行处理逻变为单元化的独立处理逻辑,被观察者只是按照自己的逻辑发出消息,不用关心谁来消费消息,每个观察者只处理自己关心的内容。逻辑相互隔离带来简单清爽的代码结构。

            缺点: 观察者较多时,可能会花费一定的开销来发消息,但这个消息可能仅一个观察者消费

        (2)适用场景

            适用于一对多的的业务场景一个对象发生变更,会触发N个对象做相应处理的场景。例如: 订单调度通知,任务状态变化等

        (3)注意事项

            避免观察者与被观察者之间形成循环依赖,可能会因此导致系统崩溃

        (4)简单实现

package observer;
import java.util.*;
public class ObserverPattern
{
    public static void main(String[] args)
    {
        Subject subject = new ConcreteSubject();
        Observer obsA = new ConcreteObserverA();
        Observer obsb = new ConcreteObserverB();
        subject.add(obsA);
        subject.add(obsB);
        subject.setState(0);
    }
}
//抽象目标
abstract class Subject
{
    protected List<Observer> observerList = new ArrayList<Observer>();   
    //增加观察者方法
    public void add(Observer observer)
    {
        observers.add(observer);
    }    
    //删除观察者方法
    public void remove(Observer observer)
    {
        observers.remove(observer);
    }   
    public abstract void notify(); //通知观察者方法
}
//具体目标
class ConcreteSubject extends Subject
{
   private Integer state;
   public void setState(Integer state){
        this.state = state;

        // 状态改变通知观察者
        notify();
    }
    public void notify()
    {
        System.out.println("具体目标状态发生改变...");
        System.out.println("--------------");       

        for(Observer obs:observers)
        {
            obs.process();
        }

    }          
}
//抽象观察者
interface Observer
{
    void process(); //具体的处理
}
//具体观察者A
class ConcreteObserverA implements Observer
{
    public void process()
    {
        System.out.println("具体观察者A处理!");
    }
}
//具体观察者B
class ConcreteObserverB implements Observer
{
    public void process()
    {
        System.out.println("具体观察者B处理!");
    }
}

版权声明:文章有些内容是搬运他人的,至于源头是谁,我也不是很清楚。如果您发现有侵权行为,请联系本人的邮箱:1986643513@qq.com

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值