面向对象
面向对象语法
类的定义:
class 类名:
内容
语法说明:
示例:
# 定义类
class Person:
# 行为通过方法体现
# 吃饭
def eat(self):
print('红烧鸡腿我喜欢吃')
# 睡觉
def sleep(self):
print('睡觉也是一种生活态度')
# 定义对象
liang = Person()
# 调用方法
liang.eat()
liang.sleep()
# 属性时动态添加的
liang.name = '某某某'
# 获取属性
print(liang.name)
self使用
class Person:
def run(self):
# self表示当前对象:谁调用该方法就表示谁
print(’{}每天以2m/s的速度慢跑5km’.format(self.name))
def introduce(self):
# 不但可以访问成员属性
print('我叫{}'.format(self.name))
# 还可以调用成员方法
self.run()
fei = Person()
fei.name = '路人甲'
fei.run()
fei.introduce()
long = Person()
long.name = '路人乙'
long.introduce()
__str__方法
class Person:
# 使用print方法打印对象,默认打印 类名 + 地址
# 若想打印特定内容,重写该方法即可,要求返回一个字符串
def str(self):
return ‘我叫{},今年{}’.format(self.name, self.age)
james = Person()
james.name = '路人丙'
james.age = 33
print(james)
构造方法:创建对象后,初始化属性时,系统会自动调用该方法
class Cat:
def str(self):
return ‘name:{},age:{},color:{}’.format(self.name, self.age, self.color)
# 构造方法:创建对象后,初始化系统就会自动调用该方法
def __init__(self, name, age, color):
print('__init__')
self.name = name
self.age = age
self.color = color
# 这种形式比较繁琐
# tom = Cat()
# tom.name = 'Tom'
# tom.age = 3
# tom.color = '蓝色'
# 这种比较简洁
tom = Cat('Tom', 3, '蓝色')
print(tom)
析构方法:当对象释放时系统会自动调用,通常用于释放资源
class Pig:
# 析构方法:当对象释放时,系统会自动调用
# 若手动使用del删除,则会立即调用该方法
# 该方法一般做资源释放处理:数据库连接断开,文件关闭
def del(self):
print(‘大师兄,我不行了’)
bajie = Pig()
del bajie
print('八戒,一路走好!')
示例:小明手里有两张牌,左右♥K,右手♠A,小明交换两手的牌后,手里分别是什么?
思路:
代码:
class Poker:
def init(self, color, number):
self.color = color
self.number = number
def __str__(self):
return '{}{}'.format(self.color, self.number)
p1 = Poker(‘♥’, ‘K’)
p2 = Poker(‘♠’, ‘A’)
class Hand:
def init(self, poker):
self.poker = poker
def hold_poker(self, poker):
self.poker = poker
left_hand = Hand(p1)
right_hand = Hand(p2)
class Person:
def init(self, name, left_hand, right_hand):
self.name = name
self.left_hand = left_hand
self.right_hand = right_hand
# 展示手里的牌
def show(self):
print('{}张开手'.format(self.name), end=' ')
print('左手:{}'.format(self.left_hand.poker), end=',')
print('右手:{}'.format(self.right_hand.poker))
# 交换两手的牌
def swap(self):
self.left_hand.poker, self.right_hand.poker = self.right_hand.poker, self.left_hand.poker
print('{}交换两手的牌'.format(self.name))
xiaoming = Person(‘小明’, left_hand, right_hand)
xiaoming.show()
xiaoming.swap()
#再次展示
xiaoming.show()
常用内置函数
内置函数:在类的内部,特定时机自动触发的函数。
示例:setattr、getattr、delattr
class Person:
def init(self, name):
self.name = name
def __str__(self):
return '姓名:{}'.format(self.name)
def __del__(self):
print('对象即将销毁')
# 当获取不存在的属性时,会自动触发该方法
def __getattr__(self, item):
if item == 'age':
return 18
else:
return '你猜'
# 当设置不存在的属性时,会自动触发该方法
def __setattr__(self, key, value):
print(key, value)
self.__dict__[key] = value
# 销毁对象成员属性时,会自动触发该方法
def __delattr__(self, item):
print(item, '即将销毁')
xiaoming = Person('小明')
xiaoming.age = 20
print(xiaoming.age)
# 存放对象的所有属性
# print(xiaoming.__dict__)
# print(xiaoming)
del xiaoming.age
将对象当做字典操作,特定时机会自动触发的方法
class Person:
# 将对象当做字典操作,设置键值对时会触发该方法
def setitem(self, key, value):
# print(key, value)
self.dict[key] = value
# 将对象当做字典操作,根据键获取值时会触发该方法
def __getitem__(self, item):
# print(item)
return self.__dict__.get(item)
# 将对象当做字典操作,删除指定的键值对时自动触发
def __delitem__(self, key):
del self.__dict__[key]
xiaoming = Person()
xiaoming['name'] = '小明'
print(xiaoming.dict)
print(xiaoming['name'])
del xiaoming['name']
将对象当做函数调用时,会自动触发下面方法
class Person:
# 将对象当做函数调用时,会自动触发该方法
def call(self, *args, **kwargs):
# print(‘call’)
return sum(args)
xiaoming = Person()
# 这样操作,需要提供call方法
ret = xiaoming(1, 2, 3, name='小明')
print(ret)
函数判断
class A:
def call(self, *args, **kwargs):
pass
def test():
pass
a = A()
# 判断是否可调用
print(callable(test))
print(callable(a))
# 判断是否拥有'__call__'属性
print(hasattr(test, '__call__'))
print(hasattr(a, '__call__'))
# 判断是否是函数
from inspect import isfunction
print(isfunction(test))
print(isfunction(a))
面向对象三大特点
类的继承
相关概念
继承语法
# class Animal(object):
# 当没有指定父类时,默认继承object
class Animal:
def init(self, name):
self.name = name
def eat(self):
print('小动物喜欢一天到晚吃个不停')
# 继承自Animal
class Dog(Animal):
pass
d = Dog('旺财')
# 可以拥有父类的方法
d.eat()
# 也可以拥有父类的属性
print(d.name)
派生示例
class Animal:
def run(self):
print(‘小动物喜欢成天跑个不停’)
class Cat(Animal):
def eat(self):
print('猫喜欢吃老鼠')
tom = Cat()
tom.run()
# 多出来的行为
tom.eat()
# 多出来的属性
tom.color = '蓝色'
print(tom.color)
重写方法
若父类的方法完全不合适,可以进行覆盖重写
若父类的方法不够完善,可以添枝加叶进行完善
示例:
class Animal:
def eat(self):
print(‘小动物一天到晚的出个不停’)
def run(self):
print('小动物一天到晚的四处连跑')
class Cat(Animal):
# 父类的方法完全不合适,覆盖重写
def run(self):
print(‘俺走的时猫步’)
# 父类的方法部分合适,需要添加内容进行完善
def eat(self):
# 保留父类的内容,不建议使用此方式
# Animal.eat(self)
# super(Cat, self).eat()
# 类名及self可以不传
super().eat()
print('不过俺喜欢吃鱼')
jiafei = Cat()
jiafei.run()
jiafei.eat()
多继承:一个子类可以拥有多个父类
class A:
def eat(self):
print(‘eat func in class A’)
class B:
def eat(self):
print('eat func in class B')
class C(A, B):
def eat(self):
# 这种方案是默认的继承顺序进行选择的父类方法
# super().eat()
# 人为指定调用某个父类的方法
B.eat(self)
c = C()
c.eat()
访问权限
权限
示例:
class Person:
def init(self, name):
self.name = name
self.__age = 20
def eat(self):
print('民以食为天')
def __test(self):
print('__test')
xiaoming = Person('小明')
print(xiaoming.name)
xiaoming.eat()
#不能在类外使用
#print(xiaoming.__age)
xiaoming._Person__test()
print(xiaoming.dict)
#尽管可以这样访问私有属性,但是强烈建议不要这样使用
#print(xiaoming._Person__age)
class Man(Person):
def introduce(self):
# 不能在子类中使用
# print(self.__age)
print('我叫{}'.format(self.name))
self.eat()
m = Man('亮亮')
m.introduce()
类属性
说明:定义类时,写在方法外的属性,通常会写在类的开头,这样的属性称为类属性
示例:
class Person:
# 类属性,通过类名访问,属于整个类,而不是某个对象
# nation = ‘中国’
# 限制可以使用的属性,提高访问的效率
# 也可以提高访问速度,减少内存使用
__slots__ = ('name', 'age', 'nation')
def __init__(self, name):
self.name = name
self.nation = 'china'
p1 = Person('小明')
p2 = Person('小红')
print(p1.name, p2.name)
print(Person.nation)
#p1.nation = 'china'
print(p1.nation)
print(p2.nation)
#print(Person.nation)
p1.age = 20
#p1.height = 180
#特殊的类属性
#表示类名的字符串
print(Person.name)
#表示父类构成的元组
print(Person.bases)
#存储类的相关信息
print(Person.dict)
#限制可以使用的属性
print(Person.slots)
类方法
说明:
作用:
示例1:创建对象
class Person:
def eat(self):
print('我喜欢吃麻辣烫,不要麻椒和辣椒')
@classmethod
def test(cls):
print(cls)
print('类方法')
# 创建对象,或者简洁的创建对象
@classmethod
def create(cls):
p = cls()
p.age = 1
return p
p1 = Person()
p1.eat()
# 通过类名调用
Person.test()
# 创建或简洁的创建对象
p2 = Person.create()
print(type(p2))
示例2:提供接口
class Number:
def init(self, num1, num2):
self.num1 = num1
self.num2 = num2
def add(self):
return self.num1 + self.num2
def sub(self):
return self.num1 - self.num2
def mul(self):
return self.num1 * self.num2
def div(self):
if self.num2 == 0:
return None
return self.num1 / self.num2
# 对外提供简单易用的接口
@classmethod
def pingfanghe(cls, num1, num2):
n1 = cls(num1, num1)
n12 = n1.mul()
n2 = cls(num2, num2)
n22 = n2.mul()
n3 = cls(n12, n22)
return n3.add()
he = Number.pingfanghe(3, 4)
print(he)
静态方法
说明:
示例:
class Person:
@staticmethod
def test():
print(‘static method test’)
# 创建对象
@staticmethod
def create():
p = Person()
return p
#Person.test()
#p = Person.create()
#print(p)
、 class Animal:
def run(self):
pass
class Dog(Animal):
def run(self):
print(‘狗通常走S型’)
class Cat(Animal):
def run(self):
print(‘猫平时走猫步,偶尔突然加速’)
def test(obj):
obj.run()
d = Dog()
c = Cat()
test(d)
test©
属性函数
说明:将成员方法当做属性一样进行访问
作用:保护特定属性,或者对特定属性进行处理
示例:
class User:
def __init__(self, username, password):
self.username = username
self.__password = password
# 该方法可以像成员属性一样访问
@property
def password(self):
print('有人想查看密码')
return '想偷看密码,没门'
# return self.__password
# 在设置密码时,会自动调用
@password.setter
def password(self, password):
print('@password.setter', password)
self.__password = '加密' + password + '加密'
u = User('xiaoming', '111111')
# print(u.password())
print(u.password)
# 设置密码,会自动调用setter方法
u.password = 'abcde'
面向对象及异常处理
内置函数
总结:init、del、str、attr系列、item系列、call
str__与__repr
算术运算符重载
示例:
class Number:
def init(self, num):
self.num = num
# 对象出现在'+'左边时会自动触发
def __add__(self, other):
print('__add__')
return self.num + other
# 对象出现在'+'右边是会自动触发
def __radd__(self, other):
print('__radd__')
return self.num + other
# +=运算时会自动触发,没有时会触发 __add__
def __iadd__(self, other):
print('__iadd__')
return Number(self.num + other)
n = Number(100)
ret = n + 200
ret = 200 + n
print(ret)
n += 200 # n = n + 200
print(n)
自己测试
加法:add、radd、iadd
减法:sub、rsub、isub
乘法:mul、rmul、imul
除法:truediv、rtruediv、itruediv
求余:__mod、rmod、imod
关系运算符重载
>: gt
=: ge
<: lt
<=: le
==: eq
!=: ne
示例
class Number:
def init(self, num):
self.num = num
def __gt__(self, other):
print('__gt__')
return self.num > 200
def __lt__(self, other):
print('__lt__')
return self.num < other
def __eq__(self, other):
print('__eq__')
return self.num == other
# 当没有此方法时,使用!=也会触发__eq__方法
def __ne__(self, other):
print('__ne__')
return self.num != other
n = Number(100)
# print(n > 200)
# print(200 > n)
# print(200 == n)
print(200 != n)
深浅拷贝
引用计数
函数传参
深浅拷贝
class Person:
def del(self):
print(‘对象释放’)
p1 = Person()
p2 = p1
print(id(p1))
print(id(p2))
del p1
del p2
print('OVER')
def test(m):
# m += 1
m[0] = 300
# n = 100
n = [100, 200]
test(n)
print(n)
import copy
lt = [1, 2, [3, 4]]
# 浅拷贝,只拷贝对象本身,不拷贝对象中的元素
# lt2 = lt.copy()
# 浅拷贝
lt2 = copy.copy(lt)
# 深拷贝:不但拷贝对象本身,还拷贝对象中的元素
lt2 = copy.deepcopy(lt)
lt[0] = 100
lt2 = 300
print(id(lt))
print(id(lt2))
print(lt)
print(lt2)
数据持久化(pickle)
说明:数据持久化存储方案,普通文件、序列化、数据库
示例:
import pickle
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return 'name:{},age:{}'.format(self.name, self.age)
xiaoming = Person('xiaoming', 20)
# 转换为bytes类型
# s = pickle.dumps(xiaoming)
# print(s)
# 从字节流中提取对象
# xm = pickle.loads(s)
# print(xm)
# 保存到文件中
# fp = open('data.txt', 'wb')
# pickle.dump(xiaoming, fp)
# 从文件中获取对象
fp = open('data.txt', 'rb')
xm = pickle.load(fp)
print(xm)
异常处理
相关概念
异常处理
异常语法:
try:
print(‘正常代码’)
# print(a)
3/0
except Exception as e:
# Exception 是所有异常的基类,此处可以捕获所有的异常
print(‘出现异常’)
print(e)
print('其他内容')
多个异常
# 分类捕获异常
‘’’
try:
# print(a)
# 3/0
d = {}
print(d[‘name’])
except NameError as e:
print(‘NameError:’, e)
except ZeroDivisionError as e:
print(‘ZeroDivisionError:’, e)
except Exception as e:
print(‘OtherError:’, e)
‘’’
try:
# print(a)
# 3/0
fp = open('123.txt')
except (NameError, ZeroDivisionError) as e:
# 将某些异常进行统一处理,写在一个元组中即可
print(e)
except:
print('其他异常')
完整结构(else-finally)
try:
print(‘正常代码’)
print(a)
except:
# 出现异常时执行
print(‘出现异常’)
else:
# 正常结束(没有异常)时会执行
print(‘正常结束’)
finally:
# 无论有无异常,都会执行
print(‘最后执行’)
else:正常结束时执行else中的代码
finally:无论有无异常,最后都执行
抛出异常:raise
try:
print(‘正常代码’)
# 根据业务逻辑的需要,手动抛出异常
raise Exception(‘手动抛出的异常’)
except Exception as e:
print(‘异常:’, e)
print('OVER')
异常嵌套(try-except结构中再次使用try-except结构)
print(‘我要去上班,什么事也阻止不了我上班的脚步’)
try:
print(‘我准备骑电动车’)
raise Exception(‘昨天晚上不知道哪个缺德的家伙把我充电器拔了’)
print(‘骑车提前到达公司’)
except Exception as e:
print(e)
try:
print(‘我准备做公交车’)
raise Exception(‘等了20分钟一直没有公交车,果断放弃’)
print(‘坐公交车准时到达公司’)
except Exception as e:
print(e)
print(‘我准备打车’)
print(‘打车还是快,一会就到达公司’)
print('热情满满的开始一天的工作')
自定义异常类(需要继承自官方的异常基类Exception)
# 自定义异常类
class MyException(Exception):
def init(self, msg):
self.msg = msg
def __str__(self):
return self.msg
# 特定异常标准处理方案
def deal(self):
print('处理特定的自定义异常')
try:
print('正常执行')
# 手动抛出自定义异常
raise MyException('出现了自定义异常')
except MyException as e:
print(e)
# 调用方法,处理异常
e.deal()
特殊场景
# 中间无论有无异常,最后一定得关闭文件
# fp.close()
with open('test.txt', 'r') as fp:
content = fp.read(5)
print(content)
# 此处不要考虑文件的关闭问题,也不用是否有异常