Python从基础到精通day8
程序员文章站
2022-06-15 20:18:49
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
推荐阅读
-
零基础写python爬虫之抓取百度贴吧并存储到本地txt文件改进版
-
测试代码的练习——python编程从入门到实践
-
MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询
-
MyBatis从入门到精通(八):MyBatis动态Sql之foreach标签的用法
-
python从入门到放弃
-
京东涅槃 从零售到以零售为基础的技术和服务战略贯彻
-
MyBatis从入门到精通(十一):MyBatis高级结果映射之一对多映射
-
小白学 Python 爬虫:自动化测试框架 Selenium 从入门到实战
-
Oracle数据库从入门到精通 单行函数问题
-
Python编程 从入门到实践 练习6-1~练习6-3