面向对象编程
面向对象的三大特性
- 封装
- 根据目标的职责将属性和方法封装到一个抽象的类中是定义类的准则
- 继承
- 通过继承 实现代码的重用
- 子类针对特有的需求,编写特定的代码
- 多态
- 不同的子类对象 调用相同的父类方法,产生不同的结果
- 增加代码的灵活性
- 以继承和重写父类方法为前提
- 是调用方法的技巧,不会影响类的内部设计
类和实例
- 面向对象开发前要先分析需求,明确程序要包含那些类
- 类的设计可以用名词提炼法:分析业务流程中出现的名词
创建一个类
- 给类起名的时候用大驼峰命名法
class Man:
def eat(self):
print("吃")
def slpee(self):
print("睡")
# 创建一个实例
xm = Man()
xm.eat()
实例就是类创建出来的对象
dir 函数
- python中万物皆对象 ,使用dir 可以查看传入对象 所有的属性和方法
# dir
def demo():
'''test'''
print("这是一个函数")
print(dir(demo))
- print可以直接查询对象所属类和对象
print(xm) # <__main__.man object at 0x0000023A821C5BE0>
- 对象的赋值 是 引用
# man是一个类
xm = Man()
xh = xm
print(xh) #<__main__.man object at 0x0000013814155CC0>
print(xm) #<__main__.man object at 0x0000013814155CC0>
给对象添加属性、和方法
- 直接添加那么属性,简单粗暴但不推荐,破坏了封装性
xm.name = "小明"
__ init__ 方法:
- 功能:定义属性 和构造函数
- 在
__init__
函数内定义属性 - 类似构造函数,不过担任了定义属性的职责
class Man:
def __init__(self,name = ""):
# __init__内定义类的属性
self.name = name
__ del__方法
- 类似析构函数
class Man:
def __del__(self):
pass
__ str__方法
- print的时候会调用__ str__方法,功能是自定义要打印的内容
- 默认情况下print 是返回对象的所属类和地址
__ str__
必须的返回一个字符串
class Man:
def __str__(self):
return self.name
访问权限
Python本身没有任何机制阻止你干坏事,一切全靠自觉!!!
定义私有属性和私有方法
- 在属性和变量名前添加两个下划线
class Women(object):
"""docstring for Women"""
def __init__(self,name,):
self.name = name
# 私有属性
self.__age = 18
#私有方法
def __secret(self):
print("我今年%d岁了"%(self.__age))
xh = Women("小红")
如果外界需要访问私有属性name我们可以给类增加get_name()函数
如果外界需要修改私有属性name我们可以给类增加set_name()函数
私有变量的访问
-
python中没有绝对的私有,私有变量在外部也是可以访问的
python解释器会把Women的 私有变量name解释为
Women__name
所以通过
Women__name
我们还是能访问的
定义受保护变量
- _xx 以
单下划线
开头的表示的是protected类型的变量。即保护类型只能允许其本身与子类进行访问。 - 若内部变量标示,如: 当使用“from M import”时,不会将以一个下划线开头的对象引入 。
继承和多态
继承分为 单继承
和 多继承
继承是指: 子类从父类 中依据父类的属性和方法的访问权限,继承属性和方法
单继承
# 单继承简例
class Animal(object):
def eat(self):
print("吃")
class cat(Animal):
pass
xm = cat()
xm.eat() # 吃
多继承
-
多继承的方法解析顺序 MRO
当类父类出现相同的函数名时,就得根据MRO顺序去决定调用哪个类,因此尽量避免出现相同函数名
Python 至少有三种不同的 MRO:
- 经典类(classic class)的深度遍历。
- Python 2.2 的新式类(new-style class)预计算。
- Python 2.3 的新式类的C3 算法。它也是 Python 3 唯一支持的方式。
使用
类名.__mro__
查看类的都方法解析顺序
# 多继承简例
class Animal(object):
def eat(self):
print("吃")
class dog(Animal):
def dark(self):
print("汪汪汪!!!")
class cat(Animal):
def catch_mouse(self):
print("抓老鼠")
class GodDog(dog,cat):
pass
# 神犬旺财 会汪汪叫也会抓老鼠
wc = GodDog()
wc.dark()
wc.catch_mouse()
# 查看MRO顺序
print(GodDog.__mro__)
新式类和经典类(旧式类)
- 以
object
为基类的对象是新式类 - 不以
object
为基类的对象是经典类 - py3中已经取消了经典类, 新式类和经典类和旧式类在多继承时会影响MRO所以统一使用新式类
在定义类的时候如果没有父类,统一使用object
py3的解释器也会默认用object
多态
不同的子类对象 调用相同的父类方法,产生不同的结果
增加代码的灵活性
以继承和重写父类方法为前提
是调用方法的技巧,不会影响类的内部设计
# 多态简例
class dog(object):
def __init__(self,name):
self.name = name
def game(self):
print("在地上玩耍")
class GodDog(dog):
''' dog 的 __init__ 也会被继承'''
def game(self):
print("狗上天")
class Person():
def __init__(self,name):
self.name = name
def GameWithDog(self,dog):
print("%s 和 %s 快乐的玩耍"%(self.name,dog.name))
dog.game()
xm = Person("小明")
xh = dog("小黑")
wc = GodDog("旺财")
xm.GameWithDog(wc)
静态方法
- 静态方法的应用场景: 如果这个方法:
- 既不需要访问实例属性或者调用实例方法
- 也不需要访问 类属性 或者调用类方法
- 不需要创建对象,不会隐式传递self
- 调用静态方法不需要创建对象
# 静态方法
class Time(object):
def __init__(self):
pass
@staticmethod
def time():
print("滴答滴答")
# 调用静态方法不需要创建对象
Time.time()
类属性
- 类属性就是给类对象定义的属性
- 通常用来记录跟这个类相关的特征
- 类属性 不会用于记录具体对象的特征 `
- 使用对
对象名.类属性
赋值 会产生 实例属性 - 访问的话具有向上查找机制,
- 调用类方法不需要创建对象
# 类属性简例
class Gun(object):
"""枪类 gun_count:记录枪的数量"""
gun_count = 0
def __init__(self, name):
self.name = name
# 注意语法 类名.类属性
Gun.gun_count += 1
def __del__(self):
# 类名.类属性
Gun.gun_count -= 1
t1 = Gun("手枪")
t2 = Gun("vector")
print(Gun.gun_count) # 也可以使用变量名来查找类属性
类方法
- 类方法就是针对 类对象 定义的方法
# 类方法
class Gun(object):
"""枪类"""
def __init__(self, name):
self.name = name
@classmethod
def shut(cls):
print("xiu~~~")
t2 = Gun("vector")
Gun.shut()
t2.shut()
注意语法格式:
类方法前面需要用修饰器
@classmethod
来标识,告诉解释器这是一个类方法和对象的第一个参数必须是
self
一样,类方法第一个参数必须是cls
在方法内部:
- 可以通过
cls.
访问其他属性- 也可以通过
cls.
调用其他类方法