OOP基础 OOP进阶

19 篇文章 2 订阅
OOP基础
OOP简介
基本概念
创建类
创建实例
绑定方法
构造器方法
其他绑定方法

OOP基础

OOP简介

基本概念

• 类(Class):用来描述具有相同的属性和方法的对象的 集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 
• 实例化:创建一个类的实例,类的具体对象。 
• 方法:类中定义的函数。 
• 对象:通过类定义的数据结构实例。对象包括两个数 据成员(类变量和实例变量)和方法。

创建类

• 使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾 
• 类名建议使用驼峰形式
class BearToy:
	pass
# 练习
lvbu = {'name': '吕布', 'weapon': '方天画戟', 'sex': '男'}
def walk():
    pass
def attack():
    pass

创建实例

• 类是蓝图,实例是根据蓝图创建出来的具体对象
tidy = BearToy()

绑定方法

构造器方法

• 当实例化类的对象是,构造器方法默认自动调用 
• 实例本身作为第一个参数,传递给self
class BearToy:
	def __init__(self, size, color):
		self.size =	size
		slef.color = color
        
if __name__=='__main__':
    tidy = BearToy('small', 'orange')

其他绑定方法

• 类中定义的方法需要绑定在具体的实例,由实例调用 
• 实例方法需要明确调用
class BearToy:
	def __init__(self, size, color):
		self.size =	size
		self.color = color
        
    def speak(self):
    	print('hahaha')
        
if __name__ ==	'__main__':
    tidy = BearToy('small',	'orange')
    tidy.speak()
# 练习
• OOP的思想,是将现实世界的物体抽象成一个类class,这个类中有属性和行为,将数据和行为融合到一起。相当于创建了一个蓝图,然后再根据蓝图创建出具体的实例。
class GameCharacter:
    def __init__(self, name, weapon):
        self.name = name
        self.weapon = weapon
    def speak(self, word):
        print('我是%s, %s' % (self.name, word))

>>> lvbu = GameCharacter('吕布', '方天画戟')
>>> lvbu.name
'吕布'
>>> lvbu.weapon
'方天画戟'
>>> lvbu.speak('人在塔在')
我是吕布, 人在塔在
>>> guanyu = GameCharacter('关羽', '青龙偃月刀')
>>> guanyu.name
'关羽'
>>> guanyu.weapon
'青龙偃月刀'
>>> guanyu.speak('呵呵')
我是关羽, 呵呵
# 练习
class GameCharacter:
    def __init__(self, name, weapon):
        self.name = name
        self.weapon = weapon

    def speak(self, word):
        print('我是%s, %s' % (self.name, word))

    def walk(self):
        print('我有%s,我能走' % self.weapon)


if __name__ == '__main__':
    lvbu = GameCharacter('吕布', '方天画戟')
    print(lvbu.name)
    print(lvbu.weapon)
    lvbu.speak('人在塔在')
    lvbu.walk()
    guanyu = GameCharacter('关羽', '青龙偃月刀')
    print(guanyu.name)
    print(guanyu.weapon)
    guanyu.speak('呵呵')
# 练习
class Weapon:
    def __init__(self, wname, strength, type):
        self.name = wname
        self.strength = strength
        self.type = type

class GameCharacter:
    def __init__(self, name, weapon):
        self.name = name
        self.weapon = weapon

    def speak(self, word):
        print('我是%s, %s' % (self.name, word))

if __name__ == '__main__':
    ji = Weapon('方天画戟', 100, '物理攻击')
    lvbu = GameCharacter('吕布', ji)
    print(lvbu.weapon.name)
    print(lvbu.weapon.type)
# 练习
class GameCharacter:
    def __init__(self, name, weapon):
        self.name = name
        self.weapon = weapon

    def speak(self, word):
        print('我是%s, %s' % (self.name, word))

class Warrior(GameCharacter):  # 括号中指定父类(基类)
    def attack(self):
        print('近身肉搏')

class Mage(GameCharacter):
    def attack(self):
        print('远程攻击')

if __name__ == '__main__':
    gl = Warrior('盖伦', '大刀')
    tm = Mage('提莫', '蘑菇')
    gl.speak('人在塔在')
    gl.attack()
    tm.speak('我去前面用脸探探路')
    tm.attack()

__init__方法一般用于为实例对象绑定属性。当创建实例的时候,__init__方法自动调用,实例(lvbu)会作为第一个参数传递。self不是关键字,java用this,但是都不是必须的名字,可以随意更换。一旦创建了实例,实例就会自动拥有类中定义的属性和方法(函数)。

self.属性 是绑定到某个实例上的属性,该属性在所有方法中均可见可用。没有绑定到对象上的,只是局部变量。

编写游戏人物

1. 创建游戏角色类
2. 游戏人物角色拥有名字、武器等属性
3. 游戏人物具有攻击和行走的方法
4. 武器通过武器类实现
OOP进阶
组合和派生
什么是组合
组合应用
创建子类
继承
通过继承覆盖方法
多重继承
特殊方法
__init__方法
__str__方法
__call__方法

OOP进阶

组合和派生

什么是组合

• 类被定义后,目标就是要把它当成一个模块来使用,并把这些对象嵌入到你的代码中去 
• 组合就是让不同的类混合并加入到其它类中来增加功能和代码重用性 
• 可以在一个大点的类中创建其它类的实例,实现一些其它属性和方法来增强对原来的类对象
• 当两个类完全不同,其中一个类是另一个类的组件时,使用组合

组合应用

• 两个类明显不同 
• 一个类是另一个类的组件
class Manufacture:
	def __init__ (self, phone, email):
        self.phone = phone
        self.email = email

创建子类

• 当类之间有显著的不同,并且较小的类是较大的类所 需要的组件时组合表现得很好;但当设计“相同的类但有一些不同的功能”时,派生就是一个更加合理的选择了 
• OOP 的更强大方面之一是能够使用一个已经定义好的类,扩展它或者对其进行修改,而不会影响系统中使用现存类的其它代码片段 
• OOD(面向对象设计)允许类特征在子孙类或子类中进行继承

创建子类(续1)

• 创建子类只需要在圆括号中写明从哪个父类继承即可
class BearToy:
def __init__ (self, size, color):
    self.size =	size
    self.color = color

继承

• 继承描述了基类的属性如何“遗传”给派生类 
• 子类可以继承它的基类的任何属性,不管是数据属性还是方法
class BearToy:
def __init__ (self, size, color):
    self.size =	size
    self.color = color
    
class NewBearToy(BearToy):
	pass
if __name__	== '__main__':
    tidy = NewBearToy('small', 'orange')
    tidy.speak()
• 当两个类有很多相似之处,只有一部分不同,使用继承。

• 子类可以有多个父类。当多个类有同名方法的时候,查找的顺序是自下向上,自左向右。

通过继承覆盖方法

• 如果子类中有和父类同名的方法,父类方法将被覆盖 
• 如果需要访问父类的方法,则要调用一个未绑定的父类方法,明确给出子类的实例
class BearToy:
    def __init__ (self, size, color, phone,	email):
        self.size =	size
        self.color = color
        self.vendor = Manufacture(phone, email)
        
class NewBearToy(BearToy):
def __init__ (self,	size, color, phone,	email, date):
    super(NewBearToy, self).__init__(size, color,phone, email)
    self.date =	date

多重继承

• python允许多重继承,即一个类可以是多个父类的 子类,子类可以拥有所有父类的属性
>>>	class A:
    def foo(self):
    	print('foo	method’)
>>>	class B:
    def bar(self):
    	print('bar method’)
>>>	class C(A, B):
	pass
>>>	c =	C()
>>>	c.foo()
foo	method
>>>	c.bar()
bar	method

特殊方法

__ init __方法

• 实例化类实例时默认会调用的方法
class BearToy:
    __init__(self, size, color):
        self.size =	size
        slef.color = color
        
if __name__	== '__main__':
	tidy = BearToy('small', 'orange')

__ str __方法

• 打印/显示实例时调用方法 
• 返回字符串
class BearToy:
    def	__init__(self, size, color):
        self.size =	size
        slef.color = color
        
    def __str__(self):
    	return '<Bear: %s %s>' % (self.size, self.color)
    
if __name__	== '__main__':
    tidy = BearToy('small',	'orange')
    print(tidy)

__ call __方法

• 用于创建可调用的实例
class BearToy:
    def __init__(self, size, color):
        self.size =	size
        slef.color = color

    def __call__(self):
        print('I am a %s bear' % self.size)
    
if __name__ == '__main__':
    tidy = BearToy('small',	'orange')
    print(tidy)

出版商程序

1. 为出版商编写一个Book类
2. Book类有书名、作者、页数等属性
3. 打印实例时,输出书名
4. 调用实例时,显示该书由哪个作者编写
re模块
正则表达式
匹配单个字符
匹配一组字符
其他元字符
核心函数和方法
match函数
search函数
group方法
findall函数
finditer函数
compile函数
split方法
sub方法

re模块

正则表达式

例:为mac地址加冒号

​ 1.定位到mac地址

​ 2.每2个mac地址分一组

​ 3.在组之间加冒号

192.168.1.1     00525412A3B4
192.168.1.2     000C29123456

:%s/\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)$/\1:\2:\3:\4:\5:\6/

匹配单个字符

记号说 明
.匹配任意字符(换行符除外)
[…x-y…]匹配字符组里的任意字符
[^…x-y…]匹配不在字符组里的任意字符
\d匹配任意数字,与[0-9]同义
\w匹配任意数字字母字符,与[0-9a-zA-Z_]同义
\s匹配空白字符,与[ \r\v\f\t\n]同义

匹配一组字符

记号说 明
literal匹配字符串的值
re1|re2匹配正则表达式re1或re2
*匹配前面出现的正则表达式零次或多次
+匹配前面出现的正则表达式一次或多次
?匹配前面出现的正则表达式零次或一次
{M, N}匹配前面出现的正则表达式至少M次最多N次

其他元字符

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

核心函数和方法

match函数

• 尝试用正则表达式模式从字符串的开头匹配,如果匹配成功,则返回一个匹配对象;否则返回None
>>>	import re
>>>	m = re.match('foo', 'food')	 #成功匹配
>>>	print(m)
<_sre.SRE_Match object;	span=(0, 3), match='foo'>
>>>	
>>>	m =	re.match(‘foo’,	‘seafood’) #未能匹配
>>>	print(m)
None
# 练习
>>> import re
# 在进行匹配的时候,如果匹配到了,返回匹配对象,否则返回None
>>> re.match('f..', 'food')
<_sre.SRE_Match object; span=(0, 3), match='foo'>
>>> re.match('f..', 'seafood')
>>> print(re.match('f..', 'seafood'))
None

search函数

• 在字符串中查找正则表达式模式的第一次出现,如果匹配成功,则返回一个匹配对象;否则返回None
>>>	import re
>>>	m =	re.search('foo', 'food')
>>>	print(m)
<_sre.SRE_Match object;	span=(0, 3), match='foo'> >>>	
>>>	m =	re.search(‘foo’, ‘seafood’) #可以匹配在字符中间的模式
>>>	print(m)
<_sre.SRE_Match object;	span=(3, 6), match='foo'>
# 练习
>>> re.search('f..', 'food')
<_sre.SRE_Match object; span=(0, 3), match='foo'>
>>> re.search('f..', 'seafood')
<_sre.SRE_Match object; span=(3, 6), match='foo'>
>>> m = re.search('f..', 'seafood')
>>> m.group()   # 返回匹配到的内容
'foo'

>>> re.search('f..', 'food')
<_sre.SRE_Match object; span=(0, 3), match='foo'>
>>> re.search('f..', 'seafood')
<_sre.SRE_Match object; span=(3, 6), match='foo'>
>>> m = re.search('f..', 'seafood')
>>> m.group()   # 返回匹配到的内容
'foo'

group方法

>>>	import re
>>>	m =	re.match('foo',	'food')
>>>	print(m.group())
foo

>>>	m =	re.search('foo', 'seafood')
>>>	m.group()
'foo'

findall函数

• 在字符串中查找正则表达式模式的所有(非重复)出现;返回一个匹配对象的列表
>>>	import re
>>>	m =	re.search('foo', 'seafood is food')
>>>	print(m.group()) #search只匹配模式的第一次出现
foo
>>>	
>>>	m =	re.findall(‘foo’, ‘seafood is food’) #获得全部的匹配项
>>>	print(m)
['foo',	'foo']

finditer函数

• 和findall()函数有相同的功能,但返回的不是列表而是迭代器;对于每个匹配,该迭代器返回一个匹配对象
>>>	import re
>>>	m =	re.finditer('foo', 'seafood	is food')
>>>	for	item in m:
...	print(item.group())
...	
foo
foo
# 练习
>>> list(re.finditer('f..', 'seafood is food'))
[<_sre.SRE_Match object; span=(3, 6), match='foo'>, <_sre.SRE_Match object; span=(11, 14), match='foo'>]
>>> for m in re.finditer('f..', 'seafood is food'):
...     print(m.group())
... 
foo
foo

split方法

• 根据正则表达式中的分隔符把字符分割为一个列表,并返回成功匹配的列表 
• 字符串也有类似的方法,但是正则表达式更加灵活
>>>	import re #使用 . 和 - 作为字符串的分隔符
>>>	mylist = re.split('\.|-', 'hello-world.data')
>>>	print(mylist)
['hello', 'world', 'data']
# 练习
>>> re.split('-|\.', 'hello-world.tar.gz')
['hello', 'world', 'tar', 'gz']

sub方法

• 把字符串中所有匹配正则表达式的地方替换成新的字符串
>>>	import re
>>>	m =	re.sub('X',	'Mr. Smith', 'attn:	X\nDear X')
>>>	print(m)
attn: Mr. Smith
Dear Mr. Smith
# 练习
>>> re.sub('X', 'tom', 'Hi X. Nice to meet you X.')
'Hi tom. Nice to meet you tom.'

compile函数

• 对正则表达式模式进行编译,返回一个正则表达式对象
• 不是必须要用这种方式,但是在大量匹配的情况下,可以提升效率
>>>	import re
>>>	patt = re.compile('foo')
>>>	m = patt.match('food')
>>>	print(m.group())
foo
# 练习
# 当有大量内容需要匹配的时候,先把正则表达式的模式编译一下,将会有更好的执行效率
>>> patt = re.compile('f..')
>>> patt.search('seafood')
<_sre.SRE_Match object; span=(3, 6), match='foo'>
>>> patt.findall('seafood is food')
['foo', 'foo']

分析apache访问日志

• 编写一个apche日志分析脚本
    1. 统计每个客户端访问apache服务器的次数
    2. 将统计信息通过字典的方式显示出来
    3. 分别统计客户端是Firefox和MSIE的访问次数
    4. 分别使用函数式编程和面向对象编程的方式实现
def coun_patt(fname, patt):


if __name__ == '__main__':
    fname = 'access_log'
    ip = '^(\d+\.){3}\d+'  # 192.168.199.23, 12345.67890.1.132234354
    br = 'Firefox|MSIE|Chrome'
    print(coun_patt(fname, ip))
    print(coun_patt(fname, br))

Counter对象

>>> from collections import Counter
>>> c = Counter()
>>> c.update('1.1.1.1')
>>> c
Counter({'1': 4, '.': 3})
>>> c1 = Counter()
>>> c1.update(['1.1.1.1'])
>>> c1
Counter({'1.1.1.1': 1})
>>> c1.update(['1.1.1.1'])
>>> c1.update(['1.1.1.1'])
>>> c1.update(['1.1.1.1'])
>>> c1.update(['1.1.1.2'])
>>> c1.update(['1.1.1.2'])
>>> c1.update(['1.1.1.2'])
>>> c1.update(['1.1.1.3'])
>>> c1.update(['1.1.1.3'])
>>> c1
Counter({'1.1.1.1': 4, '1.1.1.2': 3, '1.1.1.3': 2})
>>> c1.most_common(2)
[('1.1.1.1', 4), ('1.1.1.2', 3)]
import re
from collections import Counter

def count_patt(fname, patt):
    cpatt = re.compile(patt)  # 先编译模式
    c = Counter()  # 用于保存结果

    # 打开文件,从每一行中匹配,将匹配结果更新到c中
    with open(fname) as fobj:
        for line in fobj:
            m = cpatt.search(line)
            if m:  # 如果匹配到内容,才是真;None是False
                c.update([m.group()])

    return c

if __name__ == '__main__':
    fname = 'access_log'
    ip = '^(\d+\.){3}\d+'  # 192.168.199.23, 12345.67890.1.132234354
    br = 'Firefox|MSIE|Chrome'
    ips = count_patt(fname, ip)
    print(ips)
    print(ips.most_common(5))
    print(count_patt(fname, br))

2

import re
from collections import Counter

class CountPatt:
    def __init__(self, fname):
        self.fname = fname

    def count_patt(self, patt):
        cpatt = re.compile(patt)  # 先编译模式
        c = Counter()  # 用于保存结果

        # 打开文件,从每一行中匹配,将匹配结果更新到c中
        with open(self.fname) as fobj:
            for line in fobj:
                m = cpatt.search(line)
                if m:  # 如果匹配到内容,才是真;None是False
                    c.update([m.group()])

        return c

if __name__ == '__main__':
    ip = '^(\d+\.){3}\d+'  # 192.168.199.123, 12345.67890.1.132234354
    cp = CountPatt('access_log')
    result = cp.count_patt(ip)
    print(result)
    print(result.most_common(5))

    cp2 = CountPatt('/etc/passwd')
    shell = 'bash$|nologin$'
    print(cp2.count_patt(shell))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值