zoukankan      html  css  js  c++  java
  • 第一章 1.17 内存管理, 拷贝,正则表达式

    一. 内存管理

    1. C语言中内存管理的概念

    • 内存分为堆区间和栈区间
    • C的栈区间的内存是系统自动申请和释放(自动管理)
    • C的堆区间的内存需要调用malloc函数申请,调用free函数释放

    其他高级语言中的垃圾管理机制是针对堆区间的内存进行管理的

    2. python的内存管理机制

    1) 内存的申请

    python中所有的数据都是存在堆中的,变量是保存在栈区间的,变量中保存的是保存在堆中的数据的地址。
    重新给变量赋值,会先在内存开辟新的内存保存新的数据,然后将新的数据的地址重新保存到变量
    但是如果使用数字或者字符串给变量赋值,不会直接开辟新的内存,而是先检查内存有没有这个数据,如果有直接将原来的数据的地址给变量

    2)内存的释放(垃圾回收机制)

    在python中一个数据对应的内存空间是否释放,就看这个数据的引用计数是否为0;如果引用计数为0,数据对应的内存就会被自动释放
    循环引用问题: python的垃圾回收机制会自动处理循环引用问题

    增加引用计数: 增加数据的引用(让更多的变量来保存数据的地址)
    减少引用计数: 删除引用,或者让引用去保存新的数据

    3)查看引用次数

    导入sys模块中的getrefcount
    print(getrefcount(list2))
    getrefcount函数在调用时会给形参赋值,所以打印的值会比我们需要的值多1

    3.循环引用

    • 堆中的数据相互间的引用,数据计数不为零,不被释放
    • python的垃圾回收机制会自动解决循环引用的问题


    二. 拷贝(需要导入copy模块)

    1. 直接赋值

    一个变量给另外一个变量赋值时,两个变量的数据是同一个值

    2.浅拷贝

    拷贝之后产生新的相同的数据,新的地址.但是若数据内有引用其他的数据,则其他数据的地址还是原来的地址,(相当于一个人的类,有一个狗的属性,浅拷贝之后,多个人对象拥有同一条狗(拷贝之后狗对象的地址不变,只是多了几次引用))

    3.深拷贝

    (多个人都拥有各自的狗)

    from copy import copy, deepcopy
    
    
    class Dog:
        def __init__(self, name, color='黄色'):
            self.name = name
            self.color = color
    
        def __repr__(self):
            return '<%s __id: %s>' % (str(self.__dict__)[1:-1], id(self))
    
    
    class Person:
        def __init__(self, name, age=10, gender='男', dog=None):
            self.name = name
            self.age = age
            self.gender = gender
            self.dog = dog
    
        def __repr__(self):
            return '<%s __id: %s>' % (str(self.__dict__)[1:-1], id(self))
    
    
    # 直接赋值
    print('直接赋值')
    p1 = Person('小明', dog=Dog('大黄'))
    p2 = p1    # 赋值后p1和p2指向是同一个Person对象
    print('p1:', p1)
    print('p2:', p2)
    p1.gender = '女'
    p1.dog.color = '白色'
    print('p1:', p1)
    print('p2:', p2)
    
    print('=============浅拷贝==============')
    p1 = Person('小明', dog=Dog('大黄'))
    p2 = copy(p1)
    print(p1)
    print(p2)
    p1.gender = '女'
    p1.dog.color = '白色'
    print('p1:', p1)
    print('p2:', p2)
    
    print('=============深拷贝===========')
    p1 = Person('小花', dog=Dog('大黄'))
    p2 = deepcopy(p1)
    print('p1:', p1)
    print('p2:', p2)
    p1.gender = '女'
    p1.dog.color = '白色'
    print('p1:', p1)
    print('p2:', p2)
    

    魔法方法(__repr__):自定义打印结果的显示
    def repr(self):
    return '<%s __id: %s>' % (str(self.dict)[1:-1], id(self))



    三. 正则表达式

    1.正则表达式

    用正则符号来描述字符串规则让字符串匹配更简单(计算机语言基本支持正则,python通过re模块支持正则)

    2. 正则符号

    (一) 匹配符号

    1).普通字符:在正则中没有特殊功能和意义的字符
    2).特殊字符:
    ①:点(.) - 代表任意字符

    print(re.fullmatch(r'a..b', 'au9b'))
    

    ②:(w) - ASCII码表中只能匹配字母、数字或者下划线;ASCII码表以外的都可以匹配

    print(re.fullmatch(r'awb', 'a8b'))
    

    ③:(d) - 匹配任意一个数字字符

    print(re.fullmatch(r'addb', 'a33b'))
    

    ④:(s) - 匹配任意一个空白字符(空格,缩进,换行...)

    print(re.fullmatch(r'asb', 'a	b'))
    print(re.fullmatch(r'asb', 'a
    b'))
    

    ⑤:(W D S) -> 功能和小写的相反
    W - 匹配ASCII码表任意非字母数字下划线
    D - 匹配任意非数字字符
    S - 匹配任意非空白字符

    print(re.fullmatch(r'aDbScWd', 'aZb=c+d'))
    

    ⑥:[字符集] - 匹配字符集中的任意一个字符(一个中括号只能匹配一个字符集)
    注意:前一个字符的编码值一定要比后一个字符的编码值要大
    当字符集中有减号时,减号不能放中间

    •  [1-9] - 匹配123456789中的任意一个字符
    •  [0-9] - d
    •  [a-z] - 匹配任意一个小写字母
    •  [A-Z] - 匹配任意一个大写字母
    •  [a-zA-Z] - 匹配任意一个字母
    •  [u4e00-u9fa5] - 匹配任意一个中文字符
    •  [1-9abc] - 匹配1~9或者abc中的任意一个字符
    •  [a-zA-Z0-9_] - 匹配字母数字下划线
    •  [dxyz] - 任意数字或者x、y、z
    print(re.fullmatch(r'a[xyz89?]b', 'azb'))
    print(re.fullmatch(r'a[xyz]b', 'anb'))
    print(re.fullmatch(r'a[23456789]b', r'a7b'))
    print(re.fullmatch(r'a[1-9abc]b', 'aab'))
    print(re.fullmatch(r'a[abc1-9]b', 'aab'))
    print(re.fullmatch(r'a[ac1-9b]b', 'aab'))
    print(re.fullmatch(r'a[+*-]b', 'a-b'))
    print(re.fullmatch(r'a[dxyz]b', 'axb'))
    print(re.fullmatch(r'a[\dxyz]b', 'a\b'))
    

    ⑦:[^字符集] - 匹配除了字符集以外的其他任意字符
    注意:符号^只能放在最前面!

    print(re.fullmatch(r'a[xyz^]b', 'a^b'))
    
    (二) 检测符号

    ①:  - 检测是否是单词结尾
    单词结尾-所有可以区分出两个不同单词的符号都是单词结尾,其中字符串开头和字符串结尾
    用法:检测所在的位置是否是单词结尾;不影响匹配的时候的字符串长度

    re_str = r'adb'
    print(re.fullmatch(re_str, 'a7b'))
    

    ②:^ - 检测是否是字符开头

    re_str = r'^ddd'
    print(re.fullmatch(re_str, '123'))
    print(re.search(re_str, 'k898ahs237khhj'))
    

    ③:$ - 检测是否是字符结尾

    re_str = r'ddd$'
    print(re.search(re_str, '123k898ahs237khhj990'))
    
    (三) 匹配次数

    ①:? - 匹配0次或1次
    例: x? - x出现0次或1次
    d? - 数字出现0次或1次
    ②:* - 任意次数,0次也可以
    ③:+ - 1次或多次

    print(re.fullmatch(r'ax?b', 'axb'))
    print(re.fullmatch(r'ad*b', 'a12b'))
    print(re.fullmatch(r'ad+b', 'a1272937928329b'))
    

    ④:{}
    a: {N} - 匹配N次
    b: {M,N} - 匹配M到N次
    b: {M,} - 至少匹配M次
    b: {,N} - 最多匹配N次

    re_str = r'ad{3,5}b'
    print(re.fullmatch(re_str, 'a78988b'))
    print(re.fullmatch(re_str, 'a7898b'))
    print(re.fullmatch(re_str, 'a789880b'))   # None
    

    练习

    # 练习: 写一个正则表达式判断输入的内容是否是整数
    # 123 -> 成功!  123a -> 失败!   -123  -> 成功!   --123 -> 失败!   +123 -> 成功
    re_str = r'[+-]?[1-9]d*'
    

    贪婪和非贪婪

    匹配次数不确定的时候有贪婪和非贪婪状态
    ? * + {M,} {M,N} {,N} 默认贪婪
    在能匹配成功的前提下,尽可能多的匹配
    ?? *? +? {M,}? {M,N}? {,N}? 非贪婪
    在能匹配成功的前提下,尽可能少的匹配

    3. 分支和分组

    1).分支

    正则1 | 正则2 - 先让正则1匹配,再让正则2匹配;只要有一个匹配就能成功

    # 匹配一个字符串: abc前是3个数字或者3个字母
    # 123abc, uJhabc
    re_str = r'd{3}abc|[a-zA-Z]{3}abc'
    
    2).分组

    ①:整体控制次数: ()匹配次数
    ②:将正则表达式作为一个整体操作

    重复:带分组的正则表达式M - 在M的位置重前面第M个分组匹配到的内容

    re_str = r'(d{3}|[a-z]{3})abc'
    print(re.fullmatch(re_str, 'mskabc'))
    re_str = r'(d+)([a-z]+)=2'
    print(re.fullmatch(re_str, '6kh=kh'))
    
  • 相关阅读:
    【转】Windows守护进程的一种简单实现
    vim 文本会在末尾自动添加换行 md5文件和数据只不对应
    指向指针的指针的理解和应用
    TinyXML C++解析XML
    加密解密 AES RSA MD5 SHA
    微信支付 php兼容问题
    sublime text 2 php 语法错误检查
    微信支付宝支付
    MySql安装和基本管理
    验证码处理
  • 原文地址:https://www.cnblogs.com/anjhon/p/11944716.html
Copyright © 2011-2022 走看看