-
python的语言特性
- python是动态语言。动态还是静态指的是编译期还是运行期确定的类型,动态语言在编译时变量的数据类型即可确定。多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求。编译期是指编译期把源代码翻译成计算机能够识别的代码。而运行期就是代码跑起来了,被装载到内存中去了。
- 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库等,性能优化