python面试题

python面试题

python基础

  1. Python的函数参数传递

    类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。

  2. staticmethod classmethod 区别

    类方法有类变量cls传入,从而可以用cls做一些相关的处理。并且有子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类。 对于类方法,可以通过类来调用。如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。

  3. python元类与对象实例化

* Foo(*args, **kwargs) 等价于 Foo.__call__(*args, **kwargs)。
* 因为 Foo 是 type 的对象,所以 Foo.__call__(*args, **kwargs)调用的是 type.__call__(Foo, *args, **kwargs)。
* type.__call__(Foo, *args, **kwargs) 调用的是type.__new__(Foo, *args, **kwargs),然后返回了 obj。
* obj 被 obj.__init__(*args, **kwargs) 初始化, 最后 obj 就被返回了
  1. 怎么实现一个单例

    • 一个利用 new 方法的很强大的示例就是实现 Singleton 类:
    class Singleton(object):
      def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance
    
    • 共享属性: 创建实例时把所有实例的dict指向同一个字典,这样它们具有相同的属性和方法.
    class Borg(object):
      _state = {}
      def __new__(cls, *args, **kw):
        ob = super(Borg, cls).__new__(cls, *args, **kw)
        ob.__dict__ = cls._state
        return ob
    
    • 装饰器版本
    def singleton(cls, *args, **kw):
       instances = {}
       def getinstance():
         if cls not in instances:
             instances[cls] = cls(*args, **kw)
         return instances[cls]
     return getinstance
    

- import方法: 作为python的模块是天然的单例模式

```PYTHON
  # mysingleton.py
  class My_Singleton(object):
      def foo(self):
          pass
  
  my_singleton = My_Singleton()
  
  # to use
  from mysingleton import my_singleton
  
  my_singleton.foo()
  1. yield 和 generator, 协程

    http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/1/README.html

    yield实现一个生产者消费者模型:

    import time
    
    def consumer():
        r = ''
        while True:
            n = yield r
            if not n:
                return
            print('[CONSUMER] Consuming %s...' % n)
            time.sleep(1)
            r = '200 OK'
    
    def produce(c):
        c.next()
        n = 0
        while n < 5:
            n = n + 1
            print('[PRODUCER] Producing %s...' % n)
            r = c.send(n)
            print('[PRODUCER] Consumer return: %s' % r)
        c.close()
    
    if __name__=='__main__':
        c = consumer()
        produce(c)
    

    跟多线程不同的是,协程是非抢占式的。协程的实现跟多线程没什么关系,主要还是通过类似保存栈的上下文环境(或者类似的技术)来实现的。

    python中可以通过多进程+协程来充分利用多核优势,而且避免了多线程之间切换的开销。

    注意到consumer函数是一个generator(生成器),把一个consumer传入produce后:

    1. 首先调用c.next()启动生成器;

    2. 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;

    3. consumer通过yield拿到消息,处理,又通过yield把结果传回;

    4. produce拿到consumer处理的结果,继续生产下一条消息;

    5. produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

    整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。

    最后套用Donald Knuth的一句话总结协程的特点:

    “子程序就是协程的一种特例。”

  2. gevent

    from gevent import monkey; monkey.patch_all()
    import gevent
    import urllib2
    
    def f(url):
        print('GET: %s' % url)
        resp = urllib2.urlopen(url)
        data = resp.read()
        print('%d bytes received from %s.' % (len(data), url))
    
    gevent.joinall([
            gevent.spawn(f, 'https://www.python.org/'),
            gevent.spawn(f, 'https://www.yahoo.com/'),
            gevent.spawn(f, 'https://github.com/'),
    ])
    
  3. 面向切面编程AOP和装饰器

  4. 鸭子类型

  5. GIL线程全局锁

服务器系统

  1. tornado单线程怎么实现非阻塞异步的web服务器系统

你可能感兴趣的:(python面试题)