欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python从基础到精通day8

程序员文章站 2021-12-29 11:56:37
OOP基础 、 OOP进阶 、 re模块OOP面向对象的编程在python中,一切皆对象对象有属性和方法,通过句点表示对象通过class生成类(class)用来描述具有相同属性和方法的对象的蓝图。对象(实例):通过class生成的具体的数据结构。方法:定义在class中的函数。绑定在实例上的属性,可以在class中的任何地方使用。没有绑定的数据就是函数的局部变量,只能在函数内使用。class Role: def __init__(self,name,weapon):...

OOP基础 、 OOP进阶 、 re模块

OOP

  • 面向对象的编程
  • 在python中,一切皆对象
  • 对象有属性和方法,通过句点表示
  • 对象通过class生成
  • 类(class)用来描述具有相同属性和方法的对象的蓝图。
  • 对象(实例):通过class生成的具体的数据结构。
  • 方法:定义在class中的函数。
  • 绑定在实例上的属性,可以在class中的任何地方使用。没有绑定的数据就是函数的局部变量,只能在函数内使用。
class Role:
    def __init__(self,name,weapon):

        self.name = name
        self.weapon = weapon

    def show_me(self):
            print('我是%s,善用%s' %(self.name,self.weapon))

if __name__ == '__main__':
    lb = Role('鲁班','炮')
    zf = Role('张飞','丈八蛇矛')
    print(lb.name,lb.weapon)
    print(zf.name,zf.weapon)
    lb.show_me()
    zf.show_me()

测试运行
[root@python day8]# python3 lianxi.py
鲁班 炮
张飞 丈八蛇矛
我是鲁班,善用炮
我是张飞,善用丈八蛇矛

组合和继承

  • 两个类明显不同,其中一个类是另一个类的组件,使用组合
  • 如果两个类有很多相似之处,但是仍有不同,可以使用继承
    • 子类可以有多个父类,子类继承所有父类的方法
    • 如果父子类有重名的方法,查找顺序是自下向上,自左向右
class Role:
    def __init__(self,name,weapon):
        #构造器方法,用于将属性绑定到实例
        self.name=name
        self.weapon=weapon

class Weapon:
    def __init__(self,wname,type,strength):
        self.wname = wname
        self.type = type
        self.strength = strength

if __name__ == '__main__':
    ji = Weapon('方天画戟','物理攻击','1000')
    print(ji.wname,ji.type,ji.strength)
    lb = Role('吕布',ji)
    print(lb.weapon.wname,lb.weapon.type,lb.weapon.strength)

一个子类可以有多个父类

当字类里有和父类里一样的函数,先调用子类在调用父类

class A:
    def func1(self):
        print('A func1')
class B:
    def func2(self):
        print('B func2')
class C(A,B):
    def func3(self):
        print('C func3')

if __name__ == '__main__':
    c1 = C()
    c1.func3()
    c1.func2()
    c1.func1()

子类和父类有同样的方法,如何执行子类

class User:
    def __init__(self,name,brith,sex,email,phone):
        self.name= name
        self.brith = brith
        self.sex = sex
        self.email = email
        self.phone = phone

class Student(User):
    def __init__(self,name,brith,sex,email,phone,qq):
        User.__init__(self,name,brith,sex,email,phone) #使用父类定义的属性
        self.qq = qq

if __name__ == '__main__':
    tom = Student('Tom','1999-1-2','bot','12352@qq.com','12345242','42135902402')
    print(tom.name,tom.qq)

特殊方法

  • 在oop中,以双下划线开头和结尾的方法被称作magic魔法方法。
  • 可以通过dir()函数查询对象属性
  • 大部分的魔法方法是为了实现对象自身的功能,用户编程时很少使用。
  • 常用的三种magic是:
    • __init__:构造函数
    • __str__ :显示、打印实例时自动调用
    • __call__:可以让实例像函数一样调用
class Book:
    def __init__(self, title, author):
        "构造器方法,实例化时自动调用"
        self.title = title
        self.author = author

    def __str__(self):
        "必须返回一个字符串"
        return "《%s》" % self.title

    def __call__(self):
        print("《%s》是%s编著的" % (self.title, self.author))

if __name__ == '__main__':
    # 实例化,自动调用__init__
    pybook = Book('A Byte Of Python', 'Swaroop, C. H.')
    print(pybook)  # 自动调用__str__方法
    pybook()   # 自动调用__call__方法

vim设置

>
> ```shell
> # vim ~/.vimrc
syntax on
 filetype plugin on
 set ai
>set et
 set ts=4
 set cursorline
 set scrolloff=7
 nnoremap <C-a> <Home>
 nnoremap <C-e> <End>
 nnoremap <F2> :set nu! nu?<CR>
 nnoremap ; :
 autocmd FileType yaml setlocal sw=2 ts=2 et ai

正则表达式:

. 匹配单个任意字符
[x-y] 匹配字符组里的任意字符
[ ^x-y] 取反
\d 匹配任意数字,与[0-9]同义,大写为取反,digest单词缩写
\w 匹配数字字母下划线,大写为取反
\s 配置空白字符,大写为取反 ,space单词缩写

re1|re2 匹配re1或者re2,管道需要用 \ 转译
‘*’ 匹配前面的正则表达式出现0次或多次
‘+’ 匹配前面的正则表达式出现1次以上的,需要用 \ 转译
‘?’ 匹配前面出现的正则表达式零次或一次的,需要用 \ 转译
{M,N} 配置前面出现的正则表达式至少M次到N次之间的

‘^’ 匹配字符串的开头
‘$’ 匹配字符串的结尾
‘\b’ 匹配单词的边界
() 对正则表达式分组
\nn 匹配已保存的子组

## 正则表达式

- 为MAC地址加冒号

```shell
192.168.1.1     000C29123456
192.168.1.2     525400AB32C8

:%s/\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)$/\1:\2:\3:\4:\5:\6/
% 表示全文	s表示替换	\1表示调用第一组()	在每组之间加上冒号
先找到十二位以$结尾的字符

re模块

>>> import re
# 在food开头匹配f..,匹配到返回匹配对象,匹配不到返回None
>>> m = re.match('f..', 'food')
>>> print(m)
<_sre.SRE_Match object; span=(0, 3), match='foo'>
>>> m1 = re.match('f..', 'seafood')
>>> print(m1)
None

# 从seafood中匹配f..
>>> m2 = re.search('f..', 'seafood')
>>> print(m2)
<_sre.SRE_Match object; span=(3, 6), match='foo'>
>>> m2.group()  # 匹配对象的group方法返回匹配值
'foo'

# 匹配所有的f..,返回列表
>>> re.findall('f..', 'seafood is food')
['foo', 'foo']

# finditer与findall类似,只不过它返回的是匹配对象的生成器
>>> for m in re.finditer('f..', 'seafood is food'):
...   print(m.group())

# 把字符串中的X换成zzg
>>> re.sub('X', 'zzg', 'Hi X, ni hao X')
'Hi zzg, ni hao zzg'

# 以-和.作为分隔符切分字符串
>>> re.split('-|\.', 'hello-world-ni-hao.teu.com.cn')
['hello', 'world', 'ni', 'hao', 'teu', 'com', 'cn']

# 如果有大量匹配,那么把正则表达式模式先编译,会有更好的执行效率
>>> patt = re.compile('f..')
>>> m = patt.search('seafood')
>>> m.group()
'foo'
>>> patt.findall('seafood is food')
['foo', 'foo']

案例:
匹配日志文件,将IP地址和客户使用的浏览器统计出来

import re

def count_patt(fname,patt):
    result = {}  #定义保存数据的变量
    cpatt = re.compile(patt)  #将模式先编译好,提高效率

    #打开文件利用for循环遍历文件
    with open(fname) as fobj:
        for line in fobj:
            m = cpatt.search(line)
            if m: #匹配到内容为真,匹配不到返回None
                key = m.group() #将匹配到的字符串传给变量key
                result[key] = result.get(key,0) + 1 #匹配到一样的字符串就加一

    return result

if __name__ == '__main__':
    fname = 'access_log'
    ip = '^(\d+\.){3}\d+' #\d表示匹配数字,{3}匹配三次,+表示匹配前面字符串出现1次或以上
    br = 'Firefox | MSIE| Chrome' #匹配浏览器
    result1 = count_patt(fname,ip)
    result2 = count_patt(fname,br)
    print(result1)
    print(result2)

将程序改写为OOP的格式:

import re

class CountPatt:
    def count_patt(self,fname,patt):
        result = {}  #定义保存数据的变量
        cpatt = re.compile(patt)  #将模式先编译好,提高效率

        #打开文件利用for循环遍历文件
        with open(fname) as fobj:
            for line in fobj:
                m = cpatt.search(line)
                if m: #匹配到内容为真,匹配不到返回None
                    key = m.group() #将匹配到的字符串传给变量key
                    result[key] = result.get(key,0) + 1 #匹配到一样的字符串就加一

        return result

if __name__ == '__main__':
    fname = 'access_log'
    ip = '^(\d+\.){3}\d+' #\d表示匹配数字,{3}匹配三次,+表示匹配前面字符串出现1次或以上
    br = 'Firefox | MSIE| Chrome' #匹配浏览器
    cp = CountPatt() #创建对象(实例),由于构造器没有_init_所以就写()不加东西
    result1 = cp.count_patt(fname,ip)   #创建实例调用方法,并将返回值赋给result
    result2 = cp.count_patt(fname,br)
    print(result1)
    print(result2)

代码优化三:

import re

class CountPatt:
    def __init__(self,fname):  #将属性绑定
        self.fname = fname

    def count_patt(self,patt):
        result = {}  #定义保存数据的变量
        cpatt = re.compile(patt)  #将模式先编译好,提高效率

        #打开文件利用for循环遍历文件
        with open(self.fname) as fobj:
            for line in fobj:
                m = cpatt.search(line)
                if m: #匹配到内容为真,匹配不到返回None
                    key = m.group() #将匹配到的字符串传给变量key
                    result[key] = result.get(key,0) + 1 #匹配到一样的字符串就加一

        return result

if __name__ == '__main__':
    fname = 'access_log'
    ip = '^(\d+\.){3}\d+' #\d表示匹配数字,{3}匹配三次,+表示匹配前面字符串出现1次或以上
    br = 'Firefox | MSIE| Chrome' #匹配浏览器
    cp = CountPatt(fname) #创建对象,
    result1 = cp.count_patt(ip)
    result2 = cp.count_patt(br)
    print(result1)
    print(result2)
    
    cp2 = CountPatt('/etc/passwd')  #创建实例2
    sh = 'bash$|nologin$'  #过滤以bash结尾或者以nologin结尾的行
    result3 = cp2.count_patt(sh)
    print(result3)

案例3,测试运行如下:

[root@python python]# python3 wenhao.py 
{'172.40.58.150': 10, '172.40.58.124': 6, '172.40.58.101': 10, '127.0.0.1': 121, '192.168.4.254': 103, '192.168.2.254': 110, '201.1.1.254': 173, '201.1.2.254': 119, '172.40.0.54': 391, '172.40.50.116': 244}
{' Chrome': 24, ' MSIE': 391}
{'bash': 7, 'nologin': 38}

复杂列表的排序

  • 字典不能排序,如果需要对字典排序,先将它转换成列表
  • 列表的sort()方法,接受一个名为key的参数。传递给key的,是一个函数作为排序依据。
>>> result = {'172.40.58.150': 10, '172.40.58.124': 6, '172.40.58.101': 10, '127.0.0.1': 121, '192.168.4.254': 103, '192.168.2.254': 110, '201.1.1.254': 173, '201.1.2.254': 119, '172.40.0.54': 391, '172.40.50.116': 244}
>>> l1 = list(result.items())
>>> l1
[('172.40.58.150', 10), ('172.40.58.124', 6), ('172.40.58.101', 10), ('127.0.0.1', 121), ('192.168.4.254', 103), ('192.168.2.254', 110), ('201.1.1.254', 173), ('201.1.2.254', 119), ('172.40.0.54', 391), ('172.40.50.116', 244)]

>>> def func1(seq):
...   return seq[-1]
... 
>>> l1.sort(key=func1)
>>> l1
[('172.40.58.124', 6), ('172.40.58.101', 10), ('172.40.58.150', 10), ('192.168.4.254', 103), ('192.168.2.254', 110), ('201.1.2.254', 119), ('127.0.0.1', 121), ('201.1.1.254', 173), ('172.40.50.116', 244), ('172.40.0.54', 391)]

 **使用匿名函数,并且降序排列**
>>> l1.sort(key=lambda seq: seq[-1], reverse=True)
>>> l1
[('172.40.0.54', 391), ('172.40.50.116', 244), ('201.1.1.254', 173), ('127.0.0.1', 121), ('201.1.2.254', 119), ('192.168.2.254', 110), ('192.168.4.254', 103), ('172.40.58.101', 10), ('172.40.58.150', 10), ('172.40.58.124', 6)]

本文地址:https://blog.csdn.net/m0_46588765/article/details/106890342