python

本文深入探讨Python编程的多个核心方面,包括函数与闭包、文件操作、编辑距离算法、时间函数、多进程与多线程的区别及联系、数据库连接、内建属性、多线程编程、全局解释器锁(GIL)的解析、函数包装、JSON操作、协程概念、字体映射、列表转字典以及变量继承关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.函数及子函数
def func1():
    def sub_func1(filename_t):
        filename_t = "symbol"
        return filename_t
    print sub_func1.__closure__
    ret_func1 = sub_func1
    print "done"
    return ret_func1

mainfunc = func1()
ret = mainfunc("args")
print ret

None
done
symbol

2.函数及其闭包
  • 闭包:内部函数包含对外部作用域而非全局作用域名字的引用,该内部函数称为闭包函数
name = 'closure'
def func1():
    def inner():
       print(name)
    print(inner.__closure__)
    return inner 
f1 = func1()
f1()

def func2():
       name = 'closure'
       def inner():
           print(name)
       print(inner.__closure__)
       return inner()
func2()

None
closure
(<cell at 0x1044d7558: str object at 0x1044d89c0>,)
closure

3.操作文件
import codecs
count = 0
with codecs.open('00001-01000.txt','rb','utf-8') as fp:
    while 1:
        line1 = fp.readline()
        line2 = next(fp)
        if not line1:
            break
4.编辑距离(levenshtein_distance)
#-*-coding:utf-8-*-
import numpy as np 
def _levenshtein_distance(ref, hyp):
    
    m = len(ref)
    n = len(hyp)

    # special case
    if ref == hyp:
        return 0
    if m == 0:
        return n
    if n == 0:
        return m

    if m < n:
        ref, hyp = hyp, ref
        m, n = n, m

    # use O(min(m, n)) space
    distance = np.zeros((2, n + 1), dtype=np.int32)

    # initialize distance matrix
    for j in xrange(n + 1):
        distance[0][j] = j

    # calculate levenshtein distance
    for i in xrange(1, m + 1):
        prev_row_idx = (i - 1) % 2
        cur_row_idx = i % 2
        distance[cur_row_idx][0] = i
        for j in xrange(1, n + 1):
            if ref[i - 1] == hyp[j - 1]:
                distance[cur_row_idx][j] = distance[prev_row_idx][j - 1]
            else:
                s_num = distance[prev_row_idx][j - 1] + 1
                i_num = distance[cur_row_idx][j - 1] + 1
                d_num = distance[prev_row_idx][j] + 1
                distance[cur_row_idx][j] = min(s_num, i_num, d_num)

    return distance[m % 2][n]

a = u"2019年开始语音识别的项目"
b = u"2018年语音识别的项目"
print _levenshtein_distance(a,b)
5.时间函数
import datetime
print datetime.datetime.now().strftime("%B-%d-%Y_%I+%M%p")

April-09-2019_05+03PM

6.多进程和多线程之间的联系与区别
进程:进程时计算机程序一次执行的实例,由 程序段 数据段 PCB组成,是计算机资源分配和调度的基本单位,也是线程的容器
  线程:线程也叫作轻量级进程,是程序执行的最小单位,他本身只拥有少部分执行必须的资源。
  进程和线程的VS(创建,通信,稳定性): 
    (1)线程共享内存空间;进程的内存是独立的
    (2)同一个进程的线程之间可以直接交流;两个进程想通信,必须通过一个中间代理来实现
      (3)创建新线程很简单; 创建新进程需要对其父进程进行一次克隆
    (4)一个线程可以控制和操作同一进程里的其他线程;但是进程只能操作子进程
    (5)改变主线程(如优先权),可能会影响其它线程;多进程的稳定性好,改变父进程,不影响子进程

多进程和多线程:
因为GIL的问题导致系统中同一时间点只能有一个线程被解释器解释,这就导致了线程无法实现并行,无法充分的利用我们计算机的多核资源,python所谓的多线程编程就类似于单核CPU情况下的多进程编程。
相比之下多进程下每个进程执行的时候都会创建一个解释器,所以就能够比较好的计算机的多和资源实现并行。
那么,我们改如何解决GIL锁的问题呢?

  1.更换cpython为jpython(不建议)
  2.使用多进程完成多线程的任务
  3.在使用多线程可以使用c语言去实现

问题1: 什么时候会释放Gil锁,
  1 遇到像 i/o操作这种 会有时间空闲情况 造成cpu闲置的情况会释放Gil
  2 会有一个专门ticks进行计数 一旦ticks数值达到100 这个时候释放Gil锁 线程之间开始竞争Gil锁(说明:
      ticks这个数值可以进行设置来延长或者缩减获得Gil锁的线程使用cpu的时间)
问题2: 互斥锁和Gil锁的关系
Gil锁  : 保证同一时刻只有一个线程能使用到cpu
互斥锁 : 多线程时,保证修改共享数据时有序的修改,不会产生数据修改混乱

https://www.cnblogs.com/shunge/p/8120047.html
https://blog.youkuaiyun.com/IAlexanderI/article/details/70168318
http://python.jobbole.com/85231/

协程
协程又叫微线程,简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.
Python里最常见的yield就是协程的思想!

补充
进程间通信方式
1.管道   
1.它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。 
2.它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。 
3.它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。

2.消息队列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取

3.信号量
 信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而		不是用于存储进程间通信数据。
   信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
   信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
   每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
   支持信号量组。

4. 共享内存
共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
因为多个进程可以同时操作,所以需要进行同步。
信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
7.连接mysql
from sshtunnel import SSHTunnelForwarder
with SSHTunnelForwarder(
         ("x.x.x.x", 22),
         ssh_password="xxxx",
         ssh_username="root",
         remote_bind_address=('127.0.0.1', 3306)) as server:

     db = MySQLdb.connect(host='127.0.0.1',
                          port=server.local_bind_port,
                          user='root',
                          passwd="xxxx",
                          db='db',
                          charset="utf8",
                          cursorclass=MySQLdb.cursors.DictCursor)
 db = MySQLdb.connect(host=host,port=port,user=user,passwd=passwd,charset='utf8',autocommit=True)
 cursor = db.cursor()
 cursor.execute("use {}".format("db"))
8. 输出所有汉字
#-*-codng:utf-8-*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
Chinese_character=""
for i in range(0x4e00,0x9fa5):
    print unichr(i)
9. 内建属性
# -*- coding:utf-8 -*-
class attribute:
    def __getattr__(self, item):
        return item + ' is not exits'

    def __setattr__(self, key, value):
        self.__dict__[key] = value

    def __getitem__(self, item):
        return self.__dict__[item]

    def __setitem__(self, key, value):
        self.__dict__[key] = value


s = attribute()
print(s.name)  # 调用__getattr__方法 输出'name is not exits'
s.age = 1  # 调用__setattr__ 方法
print(s.age)  # 输出 1
print(s['age'])  # 调用 __getitem__方法 输出1
s['name'] = 'csdn'  # 调用 __setitem__ 方法
print(s['name'])  # 调用 __getitem__ 方法 输出 'tom'

name is not exits
1
1
csdn

在访问对象的某个属性的时候,如果对象并没有这个相应的属性,方法,那么将会调用这个方法来处理,这里要注意的时,当他有一个属性,那么在访问时候因为当前对象有这个属性,那么将不会调用__getattr__()方法,而是直接返回了拥有的属性了

10. 多线程
from threading import Thread
class AsrThread(Thread):
    def __init__(self, func, args=()):
        super(AsrThread, self).__init__()
        self.func = func
        self.args = args

    def run(self):
        self.result = self.func(*self.args)

    def get_result(self):
        try:
            return self.result
        except Exception:
            return ""
AsrThread(func=translate, args=(i,))
t.get_result()

11. GIL
在扩展模块中对python的GIL进行解锁
在多线程环境下,python虚拟机按照以下方式运行:
设置GIL(全局解释器锁)
切换到一个线程中去
运行:指定数量的字节码的指令,或者线程主动让出控制(可以条用time.sleep(0) )
把线程设置为睡眠模式
解锁GIL
再次重复以上步骤
调用C/C++扩展函数的时候,GIL会被锁定,直到这个函数结束。由于这期间没有python的字节码被运行,所以线程不会切换。
如果我在扩展模块中调用阻塞式地I/O函数,那么就会发生比较糟糕的事情。
比如说,我在扩展模块中接受网络数据,如果对端机器没有发送数据,那么我的整个Python程序就会阻塞到这一点,而且不会进行线程的切换。
如果发生这样的事情,python中的多线程机制就形同虚设了。 
static PyObject Foo_bar(Foo *self, PyObject *args, PyObject *kwargs)
{
    int i = 0;

    if (!PyArg_ParseTuple(args, "i", &i)) {
        return NULL;
    }

    Py_BEGIN_ALLOW_THREADS
    some_pure_c_non_io_func(i);
    Py_END_ALLOW_THREADS

    Py_RETURN_NONE;
}
12. 包装函数在框架里应用细节测试
g_config_funcs = {}
g_layer_type_map = {}
def config_layer(layer_type):
    def wrap1(cls):
        g_config_funcs[cls.__name__] = cls
        g_layer_type_map[layer_type] = cls
        return cls

    return wrap1
class B(object):
    def __init__(self,B):
        print(B)
        print("--")
        self.BB = B

@config_layer("m")
class A(B):
    def __init__(self,s):
        print(s)
        self.AA = 2
        super(A,self).__init__(333)
if __name__ == '__main__':
    a = A("m")
    print(g_config_funcs,g_layer_type_map)

m
333

({‘A’: <class ‘main.A’>}, {‘m’: <class ‘main.A’>})

13. json包dumps和load使用
import json
def strip(s):
    return s.strip("\n")
with open("vocab.txt",'r') as fp:
    lines = fp.read().split("\n")
lines.insert(0,"_")#lines is list
with open("vocab.json",'w') as fp1:
    aa = json.dumps(lines, indent=2, ensure_ascii=False)
    fp1.write(aa)
with open(args.labels_path) as label_file:
    labels = json.load(label_file)
14. functools
import functools
class AA(object):
    def __init__(self,*args, **kwargs):
        print("--------")
        print(*args)
        print("--------")
        print(kwargs)
        print("--------")
    def __call__(self,func):
        print(func)
tf_export = functools.partial(AA,api_name="v1")
@tf_export
def wrapper_func():
    print("tensorflow func")
wrapper_func("e")
15. unicode

print(unichr(9312))

unichr(9312)

u’\u2460’

ord(u'①')

9312

16. cmap
def check_font(font_path,font_name):
    fonts_alphabet = {}
    ttf = TTFont(font_path, ignoreDecompileErrors=True)
    unicodes = list()
    for cmap in ttf['cmap'].tables:
        if cmap.isUnicode():
            try:
                for _, c in enumerate(cmap.cmap):
                    unicodes.append(c)
            except Exception as e:
                print('exveption:{}'.format(str(e)))
                pass
    print('font {} {}'.format(font_name, len(unicodes)))
    # print(u''.join([unichr(i) for i in unicodes]))
    fonts_alphabet[font_name] = unicodes
    return fonts_alphabet

def is_text_in_font(text, font_name,fonts_alphabet):
    unicodes = fonts_alphabet[font_name]
    for ch in text:
        print(ch)
        if ord(ch) in unicodes:
            continue
        return False
    return True

a = check_font("./fonts/14.ttf",'14.ttf')
is_text_in_font(u"膁蘄誇氈輊預龕辮瀠璣整張",u"14.ttf",a)
17. list 生成 dict
b = ['a','b','c']
dict(zip(b, range(len(b))))

{‘a’: 0, ‘b’: 1, ‘c’: 2}

18. 继承变量关系
class aa:
    def __init__(self):
        self.a = 1
        self.b = 0

class bb(aa):
    def __init__(self,b):
        self.b = b
        print(self.b)
        super().__init__()
        print(self.b)

s = bb(2)
print(s.b)

2
0
0

  1. warps
# -*- coding: UTF-8 -*-
import functools
def cache(func):
    cached_dict = {}
    @functools.wraps(func)
    def inner(*args, **kwargs):
        key = repr(*args, **kwargs)
        try:
            return cached_dict[key]
        except KeyError:
            cached_dict[key] = func(*args, **kwargs)
            return cached_dict[key]
    inner.csrf_exempt = True
    functools.update_wrapper(inner, func)
    return inner


@cache
def execute_query(sql):
    """ 从执行数据库查询 """
    print('hit db')  # 插播一条,刚才有人在群里问如何判断是否缓存了,看这个就行了
    return  'result'  # conn.execute(sql)  # 假设拿到了结果


print(execute_query)
# 输出 <function inner at 0x1025de6e0>
print(execute_query('select xx'))
# 输出 hit db
# 输出 result
print(execute_query('select xx'))
# 输出 result
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值