目录
面向对象简介
- Python是一种面向对象的编程语言
- 所谓面向对象的语言,简单理解就是语言中的所有操作都是通过对象来进行的面向过程
- 面向过程指将我们的程序分解为一个一个步骤,通过对每个步骤的抽象来完成程序,这种编写方式往往只适用于一个功能,如果要实现别的功能,往往复用性比较低
- 面向对象的编程语言,关注的是对象,而不注重过程,对于面向对象一切皆对象。
"""
类 实例
汽车图纸 汽车
"""
class MyClass: # 类对象,创建对象的对象
def fun1(self):
print("我的第一个类")
mc = MyClass() # 实例对象
mc.fun1()
print(type(mc))
print(mc)
"""
MyClass 类对象
mc 实例对象,是通过类来创建的 mc = MyClass()
1.类怎么创建 class 类名:
pass
2.类是什么(作用是干什么的) 实现功能、创建实例对象
3.实例怎么去创建 实例名称 = 类名()
4.实例是什么(作用是干什么的) 具现化功能,调用(使用、展示)方法(功能)
"""
self参数
class Person:
name = ""
def speaker(self):
# 占位符 %s
print('大家好, 我是%s' % self.name)
p1 = Person()
p1.name = "唐三"
p1.speaker()
p2 = Person()
p2.name = "小舞"
p2.speaker()
特殊函数__init__(self):
def __init__(self, name, age): # 做属性的初始化
# self.name = name
self.name = "唐三"
self.name = name
self.age = age
面向对象的三大特征
- 封装:保证对象中数据的安全
- 继承:保证了对象的扩展性
- 多态:保证了程序的灵活性
封装
- 概念:进行一个代码的书写的规定,使我们的协同开发者知道这个数据的重要性,从而不轻易修改这个属性。
- _name 私有属性
- __name 隐藏属性
- getter 和 setter 方法
getter 方法:控制是否是可读属性
setter 方法:控制是否是只读属性,如果不是只读属性,那么就是存在setter方法,就可以修改。 - 出现封装的原因:我们需要一种方式来增强数据的安全性
1.属性不能随意修改
2.属性不能改为任意的值 - @property装饰器
@property
def name(self): # getter方法
pass
@name_setter
def name(self): # setter方法
pass
"""
一个下划线_ 代表私有属性,还可以修改,但没有set方法
两个下划线__ 代表隐藏属性,不能通过 p1.__name 修改
"""
class Person:
def __init__(self, name):
self._name = name
@property # 创建一个同名的getter方法
# getter方法
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
p1 = Person("唐三")
print(p1.name)
p1.name = "小舞"
print(p1.name)
继承
继承的简介
class A(object):
def __int__(self):
pass
class B(A): # 括号里写的是你要继承的父类的名称
pass
- isinatance
"""省略或者不写都是object"""
class Person(object):
name = ''
age = ''
def speak(self):
print("有人在说话")
class Doctor(Person):
pass
class Driver(Person):
pass
d = Doctor()
d.speak()
dri = Driver()
dri.speak()
# isinstance()判断是否是类的实例
res = isinstance(d, Doctor)
print(res)
res = isinstance(d, Person)
print(res)
res = isinstance(dri, object)
print(res)
res = isinstance(dri, Doctor)
print(res)
方法的重写
- 如果在子类中有和父类同名的方法,则通过子类实例去调用方法时,会调用自类的方法而不是父类的父法,这个特点我们称之为方法的重写(覆盖)。
class A(object):
def run(self):
pass
class B(A):
# 这就是方法的重写,是建立在继承的基础上的,并且是重写同名的方法
def run(self):
pass
建立在方法的重写之上,需要调用父类的方法。
class A(object):
def run(self):
pass
class B(A):
def run(self):
super().run() # 这就是调用父类的同名方法
pass
# @File : 06super方法的使用.py
class Animal(object):
def __init__(self, name, weight):
self.name = name
self.weight = weight
def run(self):
print("动物会跑")
class Dog(Animal):
def run(self):
# super(Dog, self).run() # python2的写法
super().run()
print("狗会跑")
class Labuladuo(Dog):
def __init__(self, name, age, weight):
super().__init__(name, weight)
self.age = age
def run(self):
# super().run()
print("拉布拉多在跑")
# d = Dog()
# d.run()
la = Labuladuo("多多", 18, 50)
la.run()
print(la.name, la.age, la.weight)
多重继承(最好不用)
class A(object):
def run(self):
pass
class B(object):
def run(self):
super().run()
pass
class C(A, B): # 这就是多重继承
pass
(类似认干爹)
- 在Python中是支持多重继承的,也就是我们可以为一个类同时指定多个父类。
- 可以在类名的()后边添加多个类,来实现多重继承
- 多重继承,会使子类同时拥有多个父类,并且会获取到所有父类中的方法
- 在开发中没有特殊情况,应该尽量避免使用多重继承。因为多重继承会让我们的代码更加复杂
- 如果多个父类中有同名的方法,则会先在第一个父类中寻找,然后找第二个,找第三个…前面会覆盖后面的
class A(object):
def test(self):
print("A...")
def run(self):
print("跑步")
class B(object):
def test(self):
print("B...")
def sing(self):
print("唱歌")
class C(B, A):
pass
c = C()
c.test()
c.run()
"""查看当前类继承的所有的父类"""
print(C.__bases__)
"""查看当前类继承的所有的父类"""
print(C.__bases__)
模块化思维
写代码还讲究一个解耦合的原则:不想让不同代码之间产生过多的练习
多态
多态的简介
- 不关心对象的类别,只关心对象的实例方法的名字是否一样,一样的话,则可以使用一个接口调用多个不同的类的实例方法,展现出不同的形态。
本质上是使用的技巧 - 只关心对象的实例方法是否同名,不关心对象所属的类型(类class);
- 对象所属的类之间,继承关系可有可无;
- 好处
– 1. 多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强;
– 2. 多态是调用方法的技巧,不会影响到类的内部设计。
# @File : 01多态.py
# 没有继承关系
# class Duck(object):
# def fly(self):
# print("鸭子在草地里飞")
#
#
# class Swan(object):
# def fly(self):
# print("天鹅在空中翱翔")
#
#
# class Plane(object):
# def fly(self):
# print("飞机在云层滑翔")
#
#
# def method(obj):
# obj.fly()
#
#
# duck = Duck()
# method(duck)
#
# swan = Swan()
# method(swan)
#
# plane = Plane()
# method(plane)
# 有继承关系
class Grandpa(object):
def money(self):
print('这是爷爷的钱')
class Father(Grandpa):
def money(self):
super().money()
print("这是父亲的钱")
class Son(Father):
def money(self):
super().money()
print("这是儿子的钱")
def fun(obj): # 接口
obj.money()
grandpa = Grandpa()
father = Father()
son = Son()
fun(grandpa)
fun(father)
fun(son)
鸭子类型:不关注类型本身,只关注有没有相同的方法
属性和方法
类属性
- 类属性,也就是公共属性,直接定义在类中的属性
- 类属性可通过类对象和该类的实例对象来访问
- 类属性只能通过类对象来修改,不能通过实例对象来修改
# 1、类属性
# class A(object):
# 类属性,也就是公共属性,直接定义在类中的属性
# 类属性可通过类对象和该类的实例对象来访问
# 类属性只能通过类对象来修改,不能通过实例对象来修改
# num = 0
a = A()
a.num = 10
# 修改属性:对象.属性名 = 属性值
A.num = 10
print(A.num)
print(a.num)
实例属性
- 实例对象可以访问,类对象不能访问
- 创建一个新的同名的num的实例属性
# class A(object):
# def __init__(self):
# # a.name = "胡歌"
# self.name = '胡歌'
#
# a = A()
# 2、实例属性
# 实例对象可以访问,类对象不能访问
# 创建一个新的同名的num的实例属性
# a.num = 10
# 修改属性:对象.属性名 = 属性值
# print(A.num)
# print(a.num)
实例方法
- 实例方法 实例是可以直接调用的-
- 实例方法 类也是可以调用的,但是需要传递一个实例对象作为参数
class B(object):
# 实例方法
# 实例方法 实例是可以直接调用的
# 实例方法 类也是可以调用的,但是需要传递一个实例对象作为参数
def demo(self):
print("这是demo方法")
b = B()
b.demo()
B.demo(b)
类方法
- 类方法必须需要使用装饰器@classmethod来装饰
- 类方法可以由实例对象和类对象来调用,不需要传递任何参数
class B(object):
# 类方法
# 类方法必须需要使用装饰器@classmethod来装饰
# 类方法可以由实例对象和类对象来调用,不需要传递任何参数
@classmethod
def demo1(cls): # cls是默认参数,相当于当前的类对象
print('我才是真正的类方法')
b = B()
b.demo1()
B.demo1()
class B(object):
# 静态方法,与类没有什么关系,相当于放到类里面的一个功能函数,可以通过类对象调用,也可以通过实例对象调用
@staticmethod
def demo2():
print('我是静态方法')
b = B()
b.demo2()
B.demo2()
__new__()魔法方法
# __new__()方法用于创建与返回一个对象,在类准备将自身实例化时调用
class Demo(object):
def __init__(self):
print("__init__")
def __new__(cls, *args, **kwargs):
print("__new__")
super().__new__(cls)
""" Create and return a new object. See help(type) for accurate signature. """
return super().__new__(cls)
d = Demo()
输出结果:
__new__
__init__
单例模式
"""
如何用代码来实现单例模式
1.判断对象不存在:不存在--->创建实例
2.如果存在:返回已经创建的实例
"""
class Single(object):
# 创建一个类属性,我们也可以称呼为常量
obj = None
# 重写父类的new方法
def __new__(cls, *args, **kwargs):
# 判断实例是否没有被创建
if cls.obj is None:
cls.obj = super().__new__(cls)
return cls.obj
else:
return cls.obj
s1 = Single()
s2 = Single()
print(id(s1))
print(id(s2))
- 完成
面向对象