Python高级编程

模块重新导入

import moduleName 的时候,python是通过sys.path 来查找的。可以使用sys.path.append('newPath') 可以添加搜索路径。
当import了一个module之后,修改了module的代码,那么在当前运行时不会更新module修改后的功能。需要重新导入:

form imp import *
reload(moduleName)
  • 循环导入:
    a import b ,b import a ,导致循环导入,发生错误。解决思路是建一个主模块,建多个子模块,让主模块调用子模块,避免循环导入。

is 和 ==

==是判断两个对象值是否相等
is是判断两个是否指向同一个对象(引用比较)

深拷贝 浅拷贝

浅拷贝:给变量赋值,只将自己的引用赋值给变量,没有赋值。
深拷贝:import copy b = copy.deepcopy(a)

import copy  
b = copy.copy(a)
copy.copy指深拷贝本身变量的值,而不会深拷贝变量里面元素的值;而copy.deepcopy会深拷贝里面的值

copy.copy如果拷贝的是不可变类型,则是浅拷贝。

property

class Test(object):
    def __init__(self):
       self.__num = 100

    def setNum(self, newNum):
        print("----setter----")
        self.__num = newNum

    def getNum(self):
        print("----getter----")
        return self.__num

    num = property(getNum, setNum)
    #t.num = 200 #相当于调用了 t.setNum(200)
    #print(t.num) #相当于调用了 t.getNum()

或者

class Test(object):
    def __init__(self):
       self.__num = 100

    @property
    def num(self):
        print("----getter----")
        return self.__num

    @num.setter
    def num(self, newNum):
        print("----setter----")
        self.__num = newNum

t = Test()
#t.num = 200 #相当于调用了 t.setNum(200)
#print(t.num) #相当于调用了 t.getNum()

迭代器

  • 可迭代对象Iterable

    • 一类是集合数据类型:list,tuple,dict,set str
    • 一类是generator,包括生成器和带yield的generator function
  • 判断对象是否可以迭代

from collections import Iterable
isinstance(Obj,Iterable)
  • 迭代器。可以用next()返回下一个值的对象。Iterator
from collections import Iterable
isinstance(Obj,Iterable)
  • iter()函数,可以将可迭代对象转成迭代器。

闭包

在函数内部定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包。

def func(var):
    def func_closure():
        print(var*2)
    return func_closure

f = func(123)
f()

装饰器

原理:

def auth(func):
    def inner():
        print('验证权限...')
        func()
    return inner

def f1():
    pass

def f2():
    pass

f1 = auth(f1)
f1()

应用:语法糖简化调用

def auth(func):
    print('装饰1...')
    def inner():
        print('验证权限1...')
        func()
        return inner

def auth2(func):
    print('装饰2...')
    def inner():
        print('验证权限2...')
        func()
        return inner

@auth   #相当于 f1 = auth(f1)  ->注意装饰器的执行时间
@auth2
def f1():
    pass

@auth
def f2():
    pass

f1()
#@语法糖可以加多个
执行结果:
装饰2...
装饰1...
验证权限1...
验证权限2...

通用的的装饰器

def decorate(functionName):
    def funcIn(*args,**kwargs):
        ret = functionName(*args,**kwargs)
        return ret
    return funcIn

装饰器带参数
作用:在运行时起到有不同的功能。

def decorateArgs(pre="hello"):
    def decorate(functionName):
        def funcIn(*args,**kwargs):
            ret = functionName(*args,**kwargs)
            return ret
        return funcIn
    return decorate

@decorateArgs("bendeng")
def test():
    pass

作用域

globals() 查看当前命名空间所有的全局变量。
localls() 查看当前命名空间所有的局部变量。
LEGB 原则:local->enclosing->global->buildins
dir(__buildin__) 查看所有内嵌

动态语言

在运行时给对象(类)绑定(添加)属性(方法)。

class Test:
    pass

def test(self):
    pass

#动态添加属性可以直接添加
#动态添加方法使用types的MethodType方法
import types
t.test() = types.MethodType(test,t)#或者xxx = types.MethodType(test,t)
t.test()

静态方法和类方法直接添加

@staticmethod
def staticMethod():
    pass

@classmethod
def classMethod():
    pass

class Test:
    pass
Test.test = staticMethod
Test.test = classMethod

__slots__可以限制class实例能添加的属性

class Person:
    __slots__ = ("name","age")

生成器

python中一边循环一边计算的机制,叫generator,生成器。
产生原因:生成列表时,如果很大(比如10000000),那么会占用很大的储存空间。根据列表生成规则只生成前面几个,就产生了生成器。

  • 生成器创建方法1:a = (x for x in range(10))
  • 生成器创建方法2: 存在yield 的函数称为生成器
def generator():
    b = 0
    for i in range(10):
        yield b   #next()一次就执行到这里停顿,b会更新值
        b = i * 2
a =  generator()
next(a)  <==>  a.__next__()  #两种方式等价
for c in a:  #生成器可以放在for循环里执行
    pass

send:

def test():
    i = 0
    while i < 5:
        temp = yield i
        print(temp)
        i += 1

t = test()
t.__next__()  #temp 为None
t.send('hello')  #temp为hello。send可以为temp赋值,相当于yield i的值为'hello'并赋值给temp

#第一次调用t.send(None)不会报错

yield作用:多任务。三种多任务方法之一:协程

def test1():
    while True:
        print('1')
        yield None

def test2():
    while True:
        print('2')
        yield None
t1 = test1()
t2 = test2()
while True:
    t1.__next__()
    t2.__next__()

垃圾回收

  • 小整数[5,257)共享对象,常驻内存
  • 单个字符共享对象,常驻内存
  • 单个单词不可修改,默认开启intern机制,共用对象,引用计数为0,则销毁。
  • 字符串(含有空格),不可修改,不开启intern机制,不共用对象,引用计数为0,销毁。
  • 大整数不共用内存,引用计数为0,销毁。
  • 数值类型和字符串类型在python中是不可变的,即无法修改一个对象的值,每次对对象的修改,实际上是创建一个新对象。

python采用引用计数为主,标记-清除分代收集两种机制为辅的策略。

引用计数

  • 优点:
    • 简单
    • 实时性:一旦没有引用,内存就直接被释放。不用像其它机制等到特定时机。实时性还带来一个好处,处理回收内存的时间分摊到了平时。
  • 缺点
    • 维护引用计数消耗资源
    • 循环引用
  • 导致引用计数+1 的情况
    • 对象被创建,a = “hello”
    • 对象被引用,b = a
    • 对象被当做参数传入一个函数,func(a)
    • 对象作为一个元素,储存在容器中,list=[a,b]
  • 导致引用计数-1的情况
    • 对象的别名被显示销毁,del a
    • 对象的别名被赋予新的对象,a = “world”
    • 一个对象离开它的作用域,如局部对象
    • 对象所在的容器被销毁,或从容器中删除对象
  • 查看一个对象的引用计数
import sys
a = "hello world"
sys.getrefcount(a)

这里查看a对象的引用计数,会比正常计数大1。

垃圾回收

  • 垃圾回收的对象会存放在gc.garbage列表里面
  • gc.collect()会返回不可达的对象数目。
  • 三种情况会触发垃圾回收
    • 调用gc.collect()
    • 当gc模块的计数器达到阈值的时候
    • 程序退出的时候
  • gc模块常用功能
    • 1、gc.set_debug(flag).一般设置为gc.DEBUG_LEAK
    • 2、gc.collect()。显示进行垃圾回收
    • 3、gc.get_threshould()获取gc模块中自动执行垃圾回收的频率。如(700,10,10)
    • 4、gc.set_threshould(threshould0,[threshould1,[threshould2])设置自动执行垃圾回收的频率
    • gc.get_count()获取当前自动执行垃圾回收的计数器,返回一个长度为3的列表。例如(465,7,6),465表示距离上一次一代垃圾检查Python分配内存的数目减去释放内存的数目;7指距离上一次二代检查,一代垃圾检查的次数;6是指距离上一次三代垃圾检查,二代垃圾检查的次数。

在Python中,采用分代收集的方法。把对象分为三代,一开始,对象在创建的时候,放在一代中,如果在一次一代的检查中,该对象存活下来,就会被放到二代中,同理在一次二代的检查中,该对象存活下来,就会放到三代中。

gc模块唯一处理不了的是循环引用的类都有__del__方法,所以项目中尽量避免定义__del__方法。

内建属性

Python高级编程_第1张图片

class Test(object):
    def __init__(self,subject1):
        self.subject1 = subject1
        self.subject2 = 'python'

    #属性访问拦截器
    def __getattribute__(self,obj):
        if(obj == 'subject1'):
            print('access property subject1')
            return 'back custom subject1 value'
        else:
            #return self.show()  发生递归调用,程序崩溃
            return object.__getattribute__(self,obj)

    def show(self):
        pass

t = Test('p')
print(t.subject1)
print(t.subject2)

强调内容

不要在__getattribute__ 中调用self.xxxx。

内建函数

输入dir(__buildin__)可以看到很多python解释器启动后默认加载的属性和函数。
常用的内建函数:

  • range()
  • map():map(func,sequence,[sequence,]),,返回值是list
m = map(lambda x:x*x,[1,2,3])
print(list(m))   #结果为[1,4,9]
  • filter():对指定序列执行过滤操作。返回值的类型和参数sequence的类型相同
f = filter(lambda x:x%2,[2,3])
print(list(f))  #结果为[3]
  • reduce():对参数序列中的元素进行累积。
reduce(lambda x,y:x+y,[1,2,3,4])

在python3中,reduce函数从全局名字空间移除了,现在放置在functools模块里。from functools import reduce

  • sorted()
sorted([2,1,3,4])  #[1,2,3,4]
sorted([2,1,3,4],reverse=1)   #[4,3,2,1]

集合Set

集合与列表、元组类似,可以储存多个数据,但是这些数据是不重复的。
集合对象支持union(联合)、difference(差)和sysmmetric_difference(对称差集)等数学运算。

x = set([1,2,3,4])    #{1,2,3,4}
y = set([2,3,5,6,2])  #{2,3,5,6}
x & y  #交集{2, 3}
x | y  #并集{1, 2, 3, 4, 5, 6}
x ^ y  #差集{1, 4, 5, 6}

functools

functools是python2.5引入的。一些工具函数放在此包中。python3中增加了更多的函数,但很多不常用到。下面是常用的两个函数 :

  • particial函数(偏函数):把一些函数的某些参数设置成默认值,返回一个新的函数,调用新函数会更简单。
import functools
def showValue(*args,**kwargs):
    print(args)
    print(kwargs)

#p = showValue
#p(1,2,3)

p = functools.partial(showValue,1,2,3)
p()  #(1, 2, 3)  {}

p(id=123)  #(1,2,3)  {'id':123}
  • wraps函数
    使用装饰器时,需要注意被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会改变)。
    由于函数名和__doc__变化,对测试结果会有一些影响。
import functools

def note(func):
    '''note function'''
    #@functools.wraps(func)
    def wrapper():
        '''wrapper function'''
        print('note something')
        return func
    return wrapper


@note
def test():
    '''test function'''
    print('test ~')

print(test.__name__) #wrapper
print(test.__doc__)  #wrapper function

使用@functools.wraps(func)后,print(test.__doc__)会返回test function

模块进阶

Python高级编程_第2张图片
这里写图片描述

  • hashlib
import hashlib
m = hashlib.md5()
m.update('bendeng')
m.hexdigest()   #45ac4274cad82274abcfce45f494eea4   

常用的扩展库:
Python高级编程_第3张图片
Python2中,python -m SimpleHTTPServer PORT,python3中,python3 -m http.server PORT。可运行起来静态服务, 用于预览和下载文件。

  • 读写Exce文件
    1、安装个easy_install工具
sudo apt-get install python-setuptools

2、安装模块

sudo easy_install xlrd
sudo easy_install xlwt

调试

pdb是基于命令行的 调试工具,非常类似于GNU的gdb。
Python高级编程_第4张图片

  • 执行时调试python -m pdb some.py
  • 交互调试,进入pythoo或者ipython:
import pdb
pdb.run('testfun(args)')
  • 程序里埋点
import pdb
pdb.set_trace()
  • 日志调试 print

正则表达式

正则表达式是所有语言通用的字符串匹配方式。
python中使用正则表达式:

import re

#使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)
#提取数据
result.group()

match方法返回匹配对象Match Object;否则返回None

表示单个字符串

Python高级编程_第5张图片

\d = [0-9]
\D = [^0-9]
\w = [a-zA-Z0-9_]
\W = [^a-zA-Z0-9_]

表示匹配数量的表达式

Python高级编程_第6张图片

*     {0,}
+     {1,}
?     {0,1}

Python中使用字符r表示字符使用原始字符。

表示边界:

Python高级编程_第7张图片

re.match(r'.{3}\b','ben deng')   #ben
re.match(r'.+\B','bendeng')      #benden

匹配分组

Python高级编程_第8张图片
匹配任意一个0-100的数字r'[1-9]\d?$|0$|100$'
r'[1-9]?\d?$|100$'
分组匹配

r = re.match(r'

(.*)

(.*)

','

网页标题

H2文本

')
r.group|r.group(0) #'

网页标题

H2文本

'
r.group(1) #网页标题 r.group(2) #H2文本 r.groups() #('网页标题', 'H2文本')

分组别名示例:

#coding=utf-8
import re
r = re.match(r'<(?P.+)>.*<(?P.+)>.*','

h1文本

H2文本

'
) print(r.groups()) #('h1','h2')

高级用法

  • search
    从左向右搜索拿到第一个结果则停止
import re
re.search(r'h\d','

h1文本

H2文本

'
) # h1
  • findall
    找到所有匹配的结果
import re
re.findall(r'h\d','

h1文本

H2文本

'
) #['h1', 'h1', 'h1', 'h2', 'h2']
  • sub
    正则替换
import re
re.sub(r'h\d','m','

h1文本

H2文本

'
) #'m文本H2文本'
  • split
    分割字符串
import re
re.split(r'<.+?>','

h1文本

H2文本

'
) #['', 'h1文本', '', 'H2文本', '']

贪婪和非贪婪模式

正则表达式默认是贪婪模式,使用?使用非贪婪模式。

你可能感兴趣的:(Python)