python 特性和方法同名_Python语言特性的梳理

对python的语言特性,多线程机制,以及性能局限的梳理

运行环境

由于Python不同版本,尤其是Python2与Pyhton3之间差异明显,所以运行不同项目时往往需要不同版本的运行环境,这种情况下,就需要能快速切换版本的运行环境

现在存在着virtualenv pyenv conda anaconda等虚拟环境

Anaconda 一个科学计算环境,Python的发行版本 :包括了Conda

Conda --包和虚拟环境管理工具

virtualenv 轻量级第三方虚拟环境管理工具,没有Anaconda好用

pyenv   python版本管理工具

PythonicPythonic就是以Python的方式写出简洁优美的代码

上下文管理器

上下文管理器就算在想要执行的目标代码前做一些预处理工作,然后再目标代码执行后,做一些后续扫尾工作 在上下文管理协议中,有两个方法enter和exit,分别实现上述两个功能。 使用with语句,以及一个支持上下文协议的对象,就可以使用上下文管理器装饰器contextmanager 将一个函数中yield语句之前的代码当做enter方法执行,yield语句之后的代码当做exit方法执行。同时yield返回值赋值给as后的变量。

@contextlib.contextmanager

def open_func(file_name):

# __enter__方法

print('open file:', file_name, 'in __enter__')

file_handler = open(file_name, 'r')

yield file_handler

# __exit__方法

print('close file:', file_name, 'in __exit__')

file_handler.close()

return

with open_func('python_base.py') as file_in:

for line in file_in:

print(line)

装饰器

装饰器实际上就是给其他函数和类附加额外功能 值得注意的是使用装饰器后代码的执行顺序装饰器的逻辑是,将被装饰的函数传入装饰器,返回一个装饰器的函数对象。在这个对象里面猜实际执行被装饰的方法

下面的例子,把foo函数传入的装饰器函数中去,装饰器函数返回一个可执行的wrapper函数,wrapper函数里面再执行foo函数

import logging

def use_logging(func):

def wrapper(*args, **kwargs):

logging.warn("%sis running" % func.__name__)

return func(*args, **kwargs) # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()

return wrapper

@use_logging # 装饰器的逻辑是,把foo函数传入的装饰器函数中去,装饰器函数返回一个可执行的wrapper函数,wrapper函数里面再执行foo函数

def foo():

print("i am foo")

foo()

生成器

生成器与列表推导有点类似,区别在于,列表推导一开始就执行完计算,返回的就是一个列表,而生成器返回的是一个生成器对象,里面保存的是生产数据的算法,可以步进的执行里面的逻辑

>>> L = [x * x for x in range(10)] # 列表

>>> L

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> g = (x * x for x in range(10)) # 生成器对象

>>> g

at 0x7fbea411e9a8>

可以用next(g)来获得生成器的下一次结果,但一般使用迭代,generator也是可迭代对象

>>> g = (x * x for x in range(10))

>>> for n in g:

... print(n)

...

0

1

4

...

可以使用yield将函数变成生成器

def fib(max):

n, a, b = 0, 0, 1

while n < max:

yield b

a, b = b, a + b

n = n + 1

return 'done'

>>> f = fib(6)

>>> f

描述符使用描述符的类中,多次实例化描述,不同变量保存的描述符是独立的,但是类被多次实例化的话,不同实例的同名描述符变量之间是共享实例的 下面的例子说明,对描述符变量的读写都会被转接到对象内部的get与set方法

from weakref import WeakKeyDictionary

class NonNegative(object):

def __init__(self, default):

self.default = default

self.data = WeakKeyDictionary()

self.value = default

def __get__(self, instance, owner):

return self.data.get(instance, self.default)

def __set__(self, instance, value):

if value < 0:

raise ValueError("Negative value not allowed:%s" % value)

self.data[instance] = value

class Movie(object):

View = NonNegative(0)

def __init__(self, View):

self.View = View

def profit(self):

return self.View +1

m = Movie(9)

#

print(m.View) # calls Movie.View.__get__(m, Movie)

m.View = 100 # calls Movie.View.__set__(m, 100)

元类

python中类不但可以创建对象,而且本身就是一个对象 (python这种类的实现方式,感觉有点想javascirpt)可以像操作普通对象一样操作类对象

>>> class ObjectCreator(object):

... pass

...

>>> ObjectCreator

>>> ObjectCreator.new_attribute = 'foo' # 添加属性

>>> print(ObjectCreator.new_attribute)

foo

>>> ObjectCreatorMirror = ObjectCreator # 赋值给其他变量

>>> print(ObjectCreatorMirror)

动态地创建类 type有一种完全不同的能力,它也能动态的创建类。type可以接受一个类的描述作为参数,然后返回一个类

# 使用方式

type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))

例如这样的类定义

>>> class MyShinyClass(object):

… bar = True

可以用type来实现,type 接受一个字典来为类定义属性

>>> MyShinyClass = type('MyShinyClass', (), {'bar':True}) # 返回一个类对象

>>> print MyShinyClass

>>> print MyShinyClass() # 创建一个该类的实例

<__main__.MyShinyClass object at 0x8997cec>元类可以理解为创建类的类,主要目的是为了当创建类时能够自动地改变类。

Python中所有的东西都是对象。包括整数、字符串、函数以及类。而且它们都是从元类type衍生而来

>>> language = 'Python'

>>> language.__class__

>>> language.__class__.__class__

元类的实际应用 metaclass属性 metaclass属性 可以指定使用什么元类来创建当前类对象,它可以设置在类中,也可以在设置在模块这一层级上

class Foo(object):

__metaclass__ = something…自定义元类

# 元类会自动将你通常传给‘type’的参数作为自己的参数传入

def upper_attr(future_class_name, future_class_parents, future_class_attr):

'''返回一个类对象,将属性都转为大写形式'''

# 选择所有不以'__'开头的属性

attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))

# 将它们转为大写形式

uppercase_attr = dict((name.upper(), value) for name, value in attrs)

# 通过'type'来做类对象的创建

return type(future_class_name, future_class_parents, uppercase_attr)

__metaclass__ = upper_attr # 这会作用到这个模块中的所有类

class Foo(object):

# 我们也可以只在这里定义__metaclass__,这样就只会作用于这个类中

bar = 'bip'

print hasattr(Foo, 'bar')

# 输出: False

print hasattr(Foo, 'BAR')

# 输出:True

f = Foo()

print f.BAR

# 输出:'bip'

其他python的特殊语法:变量交换

a, b = b, a # 快速交换变量值列表推导 这个其实类似于生成器了,只是会直接进行计算,返回计算结果

[ i*i for i in range(30, 41) if i% 2 == 0 ]

代码组织与包管理机制

Python工程目录结构python 引入模块要注意避免循环引用

包 :只要一个文件夹下面有个 init.py 文件,那么这个文件夹就可以看做是一个包

python使用pip进行包管理,包下载后,当前版本的执行环境下都可以进行引用,这区别与php comporsor 将包引入项目内部TODO 与go,php composor的包管理机制的对比

数据结构

python中的元组 tuple,可以认为是一种特殊的列表,只是一经创建,内容不可修改

tup1 = ('physics', 'chemistry', 1997, 2000)

不过对于tuple中的引用类型数据(借用静态语言的概念),在不修改引用本身的情况下,是可以对这个引用内部的数据进行修改的 tuple中相当于保存的是指针,无需改变指针,就可以对指向的数据进行修改

>>> t = ('a', 'b', ['A', 'B'])

>>> t[2][0] = 'X'

>>> t[2][1] = 'Y'

>>> t

('a', 'b', ['X', 'Y'])

多线程编程

python的多线程编程会用到一些内置特性来进行线程间通信,与并发安全控制(虽然默认的CPython不会真正的并行,但是在多个线程间切换执行,仍绕会面临并发安全问题) 线程间通信 event与queue,锁 线程安全 -锁机制子线程启动后,

有join,主线程阻塞在join的位置

没有join,主线程与子线程并发执行,主线程执行完所有逻辑后,子线程仍然能继续执行(主线程执行完退出) 下面的例子,在多个线程操作同一变量时使用锁来保证线程安全

import time, threading

from threading import Thread

num = 0

lock = threading.Lock() #使用锁来协调线程的并发执行

class tWork(Thread):

def __init__(self,step=0):

Thread.__init__(self)

self.step = step

def run(self):

global num

for i in range(10):

lock.acquire() # 先要获取锁:

print(str(num) + '+'+str(self.step))

num = num+self.step

print(str(num) + '-' + str(self.step))

num = num-self.step

lock.release()

threadSer = tWork(5)

threadSer2 = tWork(8)

threadSer.start()

threadSer2.start()

解释器,多线程GIL 与性能优化

python的性能一直挺受诟病,一个是默认的cpyton解释器的执行效率确实不高,另外一个就是鼎鼎大名的GIL全局锁导致python的多线程直接是互斥执行的,同一时间只会有一个线程在执行解释器慢的问题,有 Pypy, Jython等第三方解释器 其中pypy的性能优化做的挺不错,使用了JIT,我的实测对比,pypy的速度大致是cpython的5倍,另外由于使用了JIT,对一个变量不停的追加内容,会导致明显的性能下降 Jython则是在jvm中执行python,看到一些测评,性能并不如意

CPython 使用带condition的互斥锁来实现GIL,并且在线程执行碰到阻塞时,会释放锁,交给其他线程继续支持

针对CPython解释器GIL的问题 Jython与IronPython中实现了真正的多线程并发,PyPy也有独立的分支版本PyPy-stm来支持多线程 从单核性能来看,首选pypy来执行,考虑多线程的时候,可以使用PyPy-stm更多实例代码可以我的github项目 wosiwo/pythonic

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值