top-questions-python

1.python2 编码问题

  • python代码内部请全部使用unicode编码,在获取外部内容时,先decode为unicode,向外输出时再encode为Str
  • 在定义变量或者正则时,也定义unicode字符,如a=u”中文”;res=r””+u”正则”。
a="\\u8fdd\\u6cd5\\u8fdd\u89c4" #变量a的内容为unicode编码,变量a为string编码(""前不要加u)
b=a.decode('unicode-escape')
print b

a="\\xe5\\x85\\xb3\\xe4\\xba\\x8e\\xe4" #变量a的内容为string编码,变量a为string编码(""前不要加u)
b=a.decode('string-escape')
print b

2.多线程问题

python带有GIL解释器锁的概念,同一时刻只能有一个线程在运行,遇到IO操作才会释放切换。

协程不同于线程的地方在于协程不是操作系统进行切换,而是由程序员编码进行切换的,也就是说切换是由程序员控制的,这样就没有了线程所谓的安全问题。

这也就是常选的gevent 方案

cpu 密集 多进程
io密集 多线程 或者协程

3.协程

4.闭包

全局变量降低了函数或模块之间的通用性,不同的函数或模块都要依赖于全局变量。同样,全局变量降低了代码的可读性,阅读者可能并不知道调用的某个变量是全局变量。

# 原始情况
time = 0

def insert_time(min):
    time = time + min
    return  time

print(insert_time(2))
print(insert_time(10))


# 闭包
time = 0


def study_time(time):
    def insert_time(min):
        nonlocal  time
        time = time + min
        return time

    return insert_time


f = study_time(time)
print(f(2))
print(time)
print(f(10))
print(time)

这里最直接的表现就是全局变量 time 至此至终都没有修改过,这里还是用了 nonlocal 关键字,表示在函数或其他作用域中使用外层(非全局)变量。

这种内部函数的局部作用域中可以访问外部函数局部作用域中变量的行为,我们称为: 闭包。更加直接的表达方式就是,当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。k

闭包避免了使用全局变量,此外,闭包允许将函数与其所操作的某些数据(环境)关连起来。而且使用闭包,可以使代码变得更加的优雅。装饰器,是基于闭包实现的。

所有函数都有一个 __closure__ 属性,如果函数是闭包的话,那么它返回的是一个由 cell 组成的元组对象。cell 对象的 cell_contents 属性就是存储在闭包中的变量。

5.装饰器问题

6.爬虫问题

7.魔法方法

一个类创建的过程是怎样的,先是调用了 __new方法来创建一个对象,把参数传给 \init__ 方法进行实例化。

其实在实际开发中,很少会用到 __new 方法,除非你希望能够控制类的创建。通常讲到 \new__ ,都是牵扯到 metaclass(元类)的。

当然当一个对象的生命周期结束的时候,析构函数 __del__ 方法会被调用。但是这个方法是 Python 自己对对象进行垃圾回收的。

Python 没有真正意义上的私有属性。然后这就导致了对 Python 类的封装性比较差。我们有时候会希望 Python 能够定义私有属性,然后提供公共可访问的 get 方法和 set 方法。Python 其实可以通过魔术方法来实现封装。

方法说明

__getattr__(self, name)该方法定义了你试图访问一个不存在的属性时的行为。因此,重载该方法可以实现捕获错误拼写然后进行重定向, 或者对一些废弃的属性进行警告。

__setattr(self, name, value)定义了对属性进行赋值和修改操作时的行为。不管对象的某个属性是否存在,都允许为该属性进行赋值.有一点需要注意,实现 \setattr__ 时要避免”无限递归”的错误,

__delattr(self, name) \delattr 与 \setattr 很像,只是它定义的是你删除属性时的行为, 实现 \delattr__ 是同时要避免”无限递归”的错误

__getattribute(self, name) \getattribute 定义了你的属性被访问时的行为,相比较,\getattr__ 只有该属性不存在时才会起作用。

因此,在支持 __getattribute的 Python 版本,调用\getattr 前必定会调用 \getattribute__

__getattribute__ 同样要避免”无限递归”的错误。

8.差异

Python3.x 中 input() 函数接受一个标准输入数据,返回为 string 类型。

Python2.x 中 input() 相等于 eval(raw_input(prompt)) ,用来获取控制台的输入。