初识面向对象
class Human:
'''
此类主要是用于创建人类
'''
mind = '有思想'
language = 'CN'
dic = {}
l1 = []
def __init__(self,name,sex,age,hobby):
self.n = name
self.s = sex
self.a = age
self.h = hobby
print(123)
print(self)
def work(self):
print('人类需要工作')
def tools(self):
print('人类会使用工具')
类名操作静态属性
1 类名.__dict__ 只能用来查询 不能增删改 查询类中所有的内容
2 万能的点 可以进行增删改查操作 操作单个属性
类名操作动态方法
前提 除了两个特殊方法 静态方法和类方法以外 一般不会通过类名操作一个类的方法
实例化对象发生了三件事:
1 在内存中开辟一个对象空间
2 自动执行类中 __init__ 方法 并将这个对象空间(内存地址)传递给__init__方法的第一个位置参数self
3 在__init__方法中通过self给对象空间添加属性
对象操作对象空间属性
1 对象查询对象中的所有属性 对象.__dict__
2 对象查询对象中的单个属性 对象.属性 增删改查
对象查看类中的属性
1 万能.
对象操作类中的方法
1 万能.
类中的方法一般都是通过对象执行的(除去类方法 静态方法) 并且对象执行这些方法都会自动将对象空间传给
方法中的一个参数self
self是什么?
self其实就是类中方法(函数)的第一个位置参数 只不过解释器会自动调用这个函数的对象传给self
所以把类中的方法的第一个参数约定俗成设置为self 代表这个就是对象
1 添加对象属性
对象的属性不仅可以在__init__ 中添加 还可以在类的其他方法或者类外添加
2 添加类的静态属性
类外或者类内都可以添加
类与类的关系
1 依赖
将一个类的对象或者类名传给另一个类的方法中使用 我使用你 但是你不属于我
2 关联
两种事物必须是相互关联的 但是在某些特殊情况下是可以更改和更换的
A需要B B也属于A 失去一个 另一个无法执行
3 组合
属于关联关系中的一种特列 组合关系比聚合还要亲密
将一个类的对象封装到另一个类的对象的属性中
4 聚合
属于关联关系中的一种特例 侧重点是xx和xx聚合成xxx 各自有各自的生命周期
5 实现
6 继承
依赖关系代码
class Elphant:
def __init__(self,name):
self.name = name
def open(self,obj1):
'''
开门
:return:
'''
print('大象开门 默念三声 开门')
obj1.open_door()
def close(self,obj1):
'''
关门
:return:
'''
print('大象关门 默念三声 关门')
obj1.close_door()
class Refrigerator:
def open_door(self):
print('冰箱门被打开了')
def close_door(self):
print('冰箱门被关上了')
elephant1 = Elphant('大象')
haier = Refrigerator()
elephant1.open(haier)
elephant1.close(haier)
关联关系代码
class Boy:
def __init__(self,name,girlFriend=None):
self.name = name
self.girlFriend = girlFriend
def have_a_dinner(self):
if self.girlFriend:
print(f'{self.name}和{self.girlFriend.name}一起吃晚饭')
else:
print('单身狗 吃什么吃')
class Gril:
def __init__(self,name):
self.name = name
组合关系代码
class Gamerole:
def __init__(self,name,ad,hp):
self.name = name
self.ad = ad
self.hp = hp
def attack(self,p1):
p1.hp -= self.ad
print(f'{self.name}攻击{p1.name} {p1.name} 掉了 {self.ad}血 还剩{p1.hp}血')
def equip_weapon(self,wea):
self.wea = wea
class Weapon:
def __init__(self,name,ad):
self.name = name
self.ad = ad
def weapon_attack(self,p1,p2):
p2.hp = p2.hp - self.ad - p1.ad
print(f'{p1.name}利用{self.name}攻击了{p2.name} {p2.name}还剩{p2.hp}血')
barry = Gamerole('bb',10,200)
panky = Gamerole('pp',20,100)
pillow = Weapon('xx',2)
barry.equip_weapon(pillow)
barry.wea.weapon_attack(barry,panky)
封装 继承 多态
继承代码
class Animal(object):
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
class Person(Animal):
pass
class Cat(Animal):
pass
class Dog(Animal):
pass
继承的优点:
1 增加了类的耦合性(耦合性不宜多 宜精
2 减少了重复代码
3 使得代码更加规范化 合理化
继承的分类
Animal 父类 基类 超类
Person Cat Dog 子类 派生类
继承可以分为单继承和多继承
Python3 中使用的使新式类 如果基类谁都不继承 那么这个类会默认继承object类
子类同时执行父类方法以及子类方法
方式一 父类.func(对象,其他参数)
class Animal(object):
type_name = '动物类'
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def eat(self):
print('吃东西')
class Person(Animal):
def __init__(self,name,sex,age,mind):
Animal.__init__(self,name,sex,age)
self.mind = mind
def eat(self):
super().eat()
print(f'{self.name} 吃饭')
p1 = Person('alex','male',24,'思想')
print(p1.__dict__)
方式二 super().func(参数)
class Animal(object):
type_name = '动物类'
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def eat(self):
print('吃东西')
class Person(Animal):
def __init__(self,name,sex,age,mind):
super(Person, self).__init__(name,sex,age)
self.mind = mind
def eat(self):
super(Person, self).eat()
print(f'{self.name} 吃饭')
p1 = Person('alex','male',24,'思想')
p1.eat()
新式类多继承
新式类的多继承
1 mro序列
mro是一个有序列表 在类被创建时就计算出来
计算公式 mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
Child继承Base1 Base2
2 表头和表尾
表头: 列表的第一个元素
表尾: 列表中表头以外的元素集合(可以为空
3 列表之间的 +操作
[A] + [B] = [A,B]
merge操作示例
如计算merge( [E,O], [C,E,F,O], [C] )
有三个列表 : ① ② ③
1 merge不为空,取出第一个列表列表①的表头E,进行判断
各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
2 取出列表②的表头C,进行判断
C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除
merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
3 进行下一次新的merge操作 ......
计算mro(A)方式
mro(A) = mro( A(B,C) )
原式= [A] + merge( mro(B),mro(C),[B,C] )
mro(B) = mro( B(D,E) )
= [B] + merge( mro(D), mro(E), [D,E] )
= [B] + merge( [D,O] , [E,O] , [D,E] )
= [B,D] + merge( [O] , [E,O] , [E] )
= [B,D,E] + merge([O] , [O])
= [B,D,E,O]
mro(C) = mro( C(E,F) )
= [C] + merge( mro(E), mro(F), [E,F] )
= [C] + merge( [E,O] , [F,O] , [E,F] )
= [C,E] + merge( [O] , [F,O] , [F] )
= [C,E,F] + merge([O] , [O])
= [C,E,F,O]
原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])
= [A,B] + merge( [D,E,O], [C,E,F,O], [C])
= [A,B,D] + merge( [E,O], [C,E,F,O], [C])
= [A,B,D,C] + merge([E,O], [E,F,O])
= [A,B,D,C,E] + merge([O], [F,O])
= [A,B,D,C,E,F] + merge([O], [O])
= [A,B,D,C,E,F,O]
封装和多态
封装
class Foo:
def __init__(self,name,sex):
self.name = name
self.sex = sex
obj1 = Foo('a',24)
obj2 = Foo('l',23)
print(obj1.name)
print(obj1.sex)
print(obj2.name)
print(obj2.sex)
多态
类的约束
类的约束
1 提取父类 在父类中定义好方法 这个方法什么都不用干 只需要抛出一个异常 所有的子类必须重写这个方法 不然报错
2 使用元类描述父类 在元类中给出一个抽象方法 这样子类就不得不给出抽象方法的具体实现 也可以起到约束效果
class Payment:
"""此类什么都不做 只是指定一个标准 谁继承 必须要定义我里面的方法"""
def pay(self,money):
raise Exception("请实现Pay方法")
class QQpay(Payment):
def pay(self,money):
print(f'使用QQ支付{money}元')
class WeChatpay(Payment):
def pay(self,money):
print(f'使用微信支付{money}元')
class Alipay(Payment):
def pay(self,money):
print(f'使用支付宝支付{money}元')
def pay(obj,money):
obj.pay(money)
a = Alipay()
b = QQpay()
c = WeChatpay()
pay(a,100)
pay(b,200)
pay(c,300)
from abc import ABCMeta
from abc import abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money):
pass
class Alipay(Payment):
def pay(self,money):
print('使用支付宝支付了%s元'%money)
class QQpay(Payment):
def pay(self,money):
print('使用qq支付了%s元'%money)
class Wechatpay(Payment):
def recharge(self):pass
def pay(a,money):
a.pay(money)
a = Alipay()
pay(a,100)
q = QQpay()
pay(q,111)
w = Wechatpay()
pay(w,123)
类的成员
类的成员
公有成员 在任何地方都能访问
私有成员 只有在类的内部才能访问
静态字段
公有 类 类内部 派生类
私有 类内部
普通字段
公有 对象 类内部 派生类
私有 类内部
方法
公有 对象 类内部 派生类
私有 类内部
四种方法
类方法
1 实例方法 第一参数必须使实例对象self 用它来传递实例的属性和方法 也可以传递类的属性方法
只能通过实例对象调用
2 类方法 使用装饰器@classmethod 第一个参数必须是当前类对象 cls 用来传递类的属性方法(不可实例
实例对象和类对象都可以调用
3 静态方法 使用装饰器@staticmethod 参数随意 方法中不能使用类或者实例的任何属性以及方法
实例对象或者类对象都可以调用
4 双下方法 是特殊方法 __方法__
不用的双下方法有着不同的出发方式
class Student:
__num = 0
def __init__(self,name,age):
self.name = name
self.age = age
Student.addNum()
@classmethod
def addNum(cls):
cls.__num += 1
@classmethod
def getNum(cls):
return cls.__num
import time
class TimeTest(object):
def __init__(self,hour,minute,second):
self.hour = hour
self.minute = minute
self.second = second
@staticmethod
def showTime():
return time.strftime("%H:%M:%S", time.localtime())
class Human:
def __init__(self,name,weight,height):
self.name = name
self.weight = weight
self.height = height
@property
def bmi(self):
return self.weight/pow(self.height,2)
为什么要使用property
将一个类的函数定义成特性后 对象再去使用obj.name 根本无法察觉name是执行了一个函数然后进行了
计算 这种特性的使用方式遵循了统一访问原则
class Goods(object):
def __init__(self):
self.original_price = 100
self.discount = 0.8
def get_price(self):
new_price = self.original_price * self.discount
return new_price
def set_price(self,value):
self.original_price = value
def del_price(self):
del self.original_price
price = property(get_price,set_price,del_price)
isinstance(a,b):判断a是否是b类(或者b类的派生类)实例化的对象
issubclass(a,b): 判断a类是否是b类(或者b的派生类)的派生类
这些可迭代的数据类型,list str tuple dict等 都是 Iterable的子类。
反射
反射: 通过字符串的形式操作对象相关的属性 Python中的一切事物都是对象(都可以使用反射
四个自省函数:
1 对对象的反射
2 对类的反射
3 当前模块的反射
4 其他模块的反射
反射的作用:
class User:
def login(self):
print('欢迎来到登录页面')
def register(self):
print('欢迎来到注册页面')
def save(self):
print('欢迎来到存储页面')
user = User()
while 1 :
choose = input('>>>').strip()
if hasattr(user,choose):
func = getattr(user,choose)
func()
else:
print('输入错误')
函数vs方法
def func():
pass
print(func)
class A:
def func(self):
pass
print(A.func)
obj = A()
print(obj.func)
from types import FunctionType
from types import MethodType
def func():
pass
class A:
def func(self):
pass
obj = A()
print(isinstance(func,FunctionType))
print(isinstance(A.func,FunctionType))
print(isinstance(obj.func,FunctionType))
print(isinstance(obj.func,MethodType))
from types import FunctionType
from types import MethodType
class A:
def func(self):
pass
@classmethod
def func1(cls):
pass
@staticmethod
def func2():
pass
obj = A()
print(isinstance(A.func2,FunctionType))
print(isinstance(obj.func2,FunctionType))
print(isinstance(obj.func2,MethodType))
1 函数是显示传递数据的 比如我们使用len()函数传递处理一些数据
2 函数与对象无关
3 方法中的数据是隐式传递的
4 方法可以操作类的内部数据
5 方法跟对象是关联的 s.strip() strip() 方法需要str调用
6 Java中只有方法 C中只有函数 C++ 却决于是否在类中
双下方法
定义:
双下方法是特殊方法,他是解释器提供的由双下划线加方法名加双下划线的具有
特殊意义的方法 不常用
调用:
不同的双下方法有不同的触发方式 __init__() 在实例化对象的时候自动调用
异常处理
怎样进行异常处理?
1 if 判断式
1 id判断式的异常处理只能针对某一段代码 对于不同的代码的相同类型的错误需要写重复的if处理
2 在程序中频繁的写与本程序无关的代码 与异常处理有关的if 会是代码的可读性变得很差
3 if是可以解决异常的 只是存在1 2 的问题
2 Python异常处理的私人定制
Python为每一种异常定制了一个类型 然后提供了一种特定的语法结构来进行异常处理
1 基本语法
try:
被检测的代码块
except 异常类型:
try一旦检测异常 执行此位置的逻辑
2 异常类只能用来处理指定的异常情况
3 多分支
4 万能异常 Exception
5 其他结构
6 主动触发异常
7 自定义异常
8 断言
3 try exception vs if
1 不牺牲可读性的前提下增强健壮性以及容错性
2 把错误处理和真正的工作分开
3 代码更加容易组织 更清晰 复杂的工作更容易实现
4 更安全 不至于由于小错误使程序崩溃
4 什么时候使用异常处理
在一些异常无法预知的情况下 使用try except 其他逻辑错误应尽量修正
5 常用异常
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
s1 = 'alex'
try:
int(s1)
except Exception as e:
print(e)