python面试充电(1)基础

  • python的语言特性

  1. python是动态语言。动态还是静态指的是编译期还是运行期确定的类型,动态语言在编译时变量的数据类型即可确定。多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求。编译期是指编译期把源代码翻译成计算机能够识别的代码。而运行期就是代码跑起来了,被装载到内存中去了。
  2. python是强类型语言。强类型指的是不会发生隐式类型转换。
    1 + '1' # 弱类型语言不会报错(隐式转换),强类型报错

     

  • 鸭子类型 

         “当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

鸭子类型更关注的是接口也不是类型,即对象的类型不再由继承等方式决定,而由实际运行时所表现出的具体行为来决定。

以下参考这篇blog:python鸭子类型博客

       在Python中,面向对象的多态和抽象是通过把协议当作正式接口来实现的。想让这个类成为相对应的鸭子类型,就要实现相关的协议,即相关的__method__。例如基本序列协议: 实现__len__和__getitem__方法,就可以索引进行随机访问list[index]和通过len得到长度。Python中,通过对魔法函数的实现,从而获得Python原生的支持,其中对一元中缀表达式的覆盖,对常规加法操作、乘法操作等的覆盖,皆是鸭子类型的表现形式。

       鸭子类型的编程风格,在实际的应用场景中,发挥的是类似一种面向对象中多态的功能。例子可以看上面博客中,电子商务的应用场景。 

  • 猴子补丁

属性在运行时的动态替换,叫做猴子补丁(Monkey Patch)。在不修改程序原本代码的前提下,通过添加类或模块等方式在程序运行过程中加入代码,起到一个类似补丁的作用。但是添加模块用法比较复杂,添加类方法或者属性比较简单,可看以下例子:

class Foo(object):
  def bar(self):
    print 'Foo.bar'

def bar(self):
  print 'Modified bar'

 
Foo().bar()    # 输出Foo.bar
Foo.bar = bar  # 猴子补丁
Foo().bar()    # 输出Modified bar

一个实际应用的例子,首先要知道obj.gatattr()方法,类似还有setattr和hasattr

# 用于返回一个对象属性值
getattr(object, name[, default]) # obj对象,name对象属性名,第三个参考括号指可以木有
# default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。

# 如果对象有该属性返回 True,否则返回 False
hasattr(object, name)

# 给对面的属性设置值,这个属性可以不存在
setattr(object, name, value)

# 返回实例的类
obj.__class__

例子blog:猴子补丁实际例子blog 

  • 自省

在计算机编程中,自省是指这种能力:检查某些事物以确定它是什么(类型)、它知道什么(属性)以及它能做什么(方法)。自省向程序员提供了极大的灵活性和控制力。

关于类,最基础的一些自省语法

# isinstance函数来判断一个对象是否是一个已知的类型
isinstance(object, classinfo) # obj实例对象,classinfo类名或者它们组成的元祖

# case
isinstance (a,(str,int,list))    # 是元组中的一个返回 True

# isinstance考虑继承关系,与type有区别
# 如果要判断两个类型是否相同推荐使用 isinstance()
class A:
    pass
 
class B(A):
    pass
 
isinstance(A(), A)    # returns True
type(A()) == A        # returns True
isinstance(B(), A)    # returns True
type(B()) == A        # returns False

# 另外关于访问对象的属性 hasattr getattr setattr 可以看上面的case
id(obj)    # 返回一个地址

#  == 一般是值判断, is 一般是地址判断
class Book:
    def test(self):
        pass

book = Book()
print([] == None)
print([] == Flase)              # Flase,值并不相等!
print(book.test() == None)    # None 等于None , 值相等
print(book.test() is None)    # None只有一个,函数无返回时默认返回None
# 前两输出Flase, 后两输出都是Ture
# 跟Flase Ture None 判断都是用is最标准
# 一般的逻辑判断,并不代表就[]就是Flase,而是逻辑上是flase

详细自省:自省指南

  • 列表推导式与生成器

a = [1, 2, 3]
b = ['a', 'b', 'c']
# 生成dict
d = {k: v for k, v in zip(b, a)}    # zip成对迭代
d2 = {k: v for k in b for v in a}
# d 和 d2 一样生成了字典

a = [x for x in range(10)]    # 列表推导式
l = (x for x in range(10))    # 生成器
print(type(l))    # <class 'generator'>
# 值得注意的是生成器比列表推导式更节省内存
  • 生成器 

生成器就是可以生产值的函数,当一个函数有了yield关键字就成了生成器,生成器可以挂起执行并且保持当前执行的状态。在Flask应用里面,有一个很经典的应用场景。算了。

class SQLAlchemy(_SQLAlchemy):
    # 用contextmanager简化了每次commit的try和except的处理
    @contextmanager
    def auto_commit(self):
        try:
            yield   # yield 相当于一个中断返回点
            self.session.commit()       # db提交
        except Exception as e:
            self.session.rollback()     # db提交后防止出错需要回滚
            raise e

# 外面调用
with db.auto_commit():
    my_community = Community()
    my_community.set_attrs(form.data)
    db.session.add(my_community)
  • python单元测试

单元测试就是针对程序模块进行正确性检验,比如对一个函数,一个类进行验证,这样从底层向上(每一个小单元代码)保证了整体程序的正确性。测试影响设计,容易测试的代码一般是高内聚低耦合(就是好的意思..)。一般利用一些单元测试的库,如pytest

  • python3改进(与python2一些区别)

  • print成为函数
  • 编码问题。python3不再有unicode对象,默认str就是Unicode
  • 除法变化。python3除号返回浮点数
  • 类型注解(type hint)
  • 优化的super()方便直接调用父类函数
    class Base:
        def hello(self):
            print('base:hello')
    
    
    class A(Base):
        def hello(self):
            super(A, self).hello()  # py2
    
    
    class B(Base):
        def hello(self):
            super().hello()  # py3
  • 高级解包操作。a,b,*rest = range(10)
    a, b, *c = range(10)
    print(c)     # c是一个列表,包括了剩下所有元素
    c, d, *_ = range(10)    # *_舍弃剩下部分
  • 限定关键字参数       # 传入函数的参数app.run(debug=True)    debug就是关键字参数
  • 一切返回迭代器。没有xrange,只有range,而且py3的range不再返回list,而是一个懒加载可迭代对象,节省内存。
  • python3新增:新增了asynio异步编程的库,还有enmu库等,性能优化

猜你喜欢

转载自blog.csdn.net/weixin_37143690/article/details/90037713