面向对象编程 (OOP,Object Oriented Programming)可以理解为将具有相互 关系的数据/操作封装成对象,以对象的⻆度去处理问题,让对象来完成相应处理 。
面向对象 vs 面向过程:
⾯向对象编程 的优点 :
对象 是承载数据,执⾏操作的 ⼀个具体 ”事物”,⽐如具体某⼀个⼈,具体某⼀只狗...
对象中包含两个组成部分:
类 物以类聚,⼈以群分
类和对象的关系 :
定义类
定义⼀个类,格式如下:
class 类名:
⽅法列表
类名的命名规则按照"⼤驼峰"
定义方法
类是定义对象的共同⾏为的,也就是说在类中定义对象的⽅法
class 类名:
def ⽅法名(self):
...
⽅法的格式和函数类似,也可以设置参数和返回值,但是 需要设置第⼀个参数为 self
demo:定义⼀个Dog类
# 定义类
class Dog:
# ⽅法
def eat(self):
print("吃⻣头")
def drink(self):
print("喝⽔")
创建对象
python中,可以根据已经定义的类去创建出对象
创建对象的格式为:
# 定义⼀个类
class Dog:
# ⽅法
def eat(self):
print("吃⻣头")
def drink(self):
print("喝⽔")
# 根据类,创建⼀个对象
dog1 = Dog()
调用方法
创建对象的格式为:
注意:虽然定义⽅法时设置第⼀个参数 self ,但是调⽤⽅法时不要传递对应 self 的参数
对象调⽤⽅法demo:
# 定义⼀个类
class Dog:
# ⽅法
def eat(self):
print("吃⻣头")
def drink(self):
print("喝⽔")
# 根据类,创建⼀个对象
dog1 = Dog()
dog1.eat() # 调用eat方法
dog2.drink() # 调用drink方法
定义/使⽤属性
格式:
属性和变量类似,⾸次赋值时会定义属性:
# 创建对象
jiqimao = Cat()
# ⾸次赋值属性,会定义属性
jiqimao.age = 3
# 定义属性后,再赋值属性,会修改属性保存的数据
jiqimao.age = 1
# 获取属性值并打印
print(jiqimao.age) # 1
创建多个对象
类作为对象的模具,根据类可以创建多个对象
# 定义类
class Cat:
def eat(self):
print("吃东⻄")
# 创建对象
cat1 = Cat()
# 调⽤⽅法
cat1.eat()
# 定义属性
cat1.name = "加菲"
print(cat1.name)
# ⼀个类是可以创建多个对象
cat2 = Cat()
# 调⽤⽅法
cat2.eat() # 同类对象都可以调⽤类中定义的对象⽅法
# 定义属性
# 同类的对象可以有同名的属性, ⽽且属性的值可以不同
cat2.name = "小叮当"
print(cat2.name)
关键字 self 主要⽤于对象⽅法中,表示调⽤该⽅法的对象 。
class Dog:
def introduce(self): # self对应的实参 就是 调⽤该⽅法的对象
# self 主要⽤于 在⽅法中使⽤⾃⼰的属性和⽅法
print("我是%s, 请多多关照" % self.name)
dog1 = Dog()
dog1.name = "大黄"
dog1.introduce() # python解释器会⾃动将调⽤⽅法的对象作为第⼀个实参进⾏传递
# 创建另⼀个对象
dog2 = Dog()
dog2.name = "小黑"
dog2.introduce() # 我是小黑,请多多关照
__init__() : 对象的初始化⽅法,在 创建⼀个对象后会被⾃动调⽤,不需要⼿动调⽤ 。
开发者可以 实现init⽅法,并在该⽅法中定义属性并设置初始值
class Dog:
# 初始化⽅法
def __init__(self):
# 设置对象的默认属性及初始值
self.type = "野狗"
# 创建了⼀个对象
dahuang = Dog( )
# 获取对象的属性
print(dahuang.type) # 野狗
__init__( ) ⾃定义参数
class Dog:
def __init__(self, name):
# 如果希望属性有不同的初始值,可以设置init的⾃定义参数
self.name = name
def introduce(self):
print("我是%s, 请多多关照" % self.name)
dog1 = Dog("大黄") # init对应的实参在创建对象时进⾏设置
dog1.introduce()
dog2 = Dog("小黑")
dog2.introduce()
将要删除⼀个对象时,python解释器会⾃动调⽤⼀个⽅法,这个⽅法为 __del__() ⽅法
del⽅法可以辅助查看对象的删除情况
class Dog:
# 将要删除对象时,会⾃动调⽤
def __del__(self):
print("对象将要被删除")
"""情况1"""
dog1 = Dog()
print("程序最后⼀⾏")
"""情况2"""
def func():
dog1 = Dog()
func()
print("程序最后⼀⾏")
class Cat:
"""定义⼀个猫类"""
def __init__(self, new_name, new_age):
self.name = new_name
self.age = new_age
def __str__(self):
"""返回⼀个对象的描述信息"""
return "名字是:%s , 年龄是:%d" % (self.name, self.age)
# 创建了⼀个对象
tom = Cat("机器猫", 3)
print(tom)
私有属性 :如果在属性名前⾯加了2个下划线'__',则表明该属性是私有属性,否则为公有属性
私有属性只能在类的内部访问
class Dog:
def __init__(self):
# 私有属性: __xx 不能在类的外部使⽤
self.__children_count = 0
def birth(self):
"""⽣育"""
print("⽣了⼀个崽⼉")
# __children_count只有在调⽤birth⽅法时才能修改,不应该在类外部直接使⽤
self.__children_count += 1
def __str__(self):
return "我有%d个崽⼉:%d" % self.__children_count
dog1 = Dog()
dog1.birth()
print(dog1)
dog1.birth()
print(dog1)
私有⽅法 :私有⽅法和私有属性类似,在⽅法名前⾯加了2个下划线'__',则表明该⽅法是私有⽅法
私有⽅法只能在类内部使⽤
class Dog:
def __init__(self):
# 私有属性: __xx 不能在类的外部使⽤
self.__children_count = 0
def birth(self):
"""⽣育"""
print("⽣了⼀个崽⼉")
self.__children_count += 1
# 休产假
self.__birth_leave() # 休产假只有在⽣孩⼦⽅法中才能使⽤,不能在类外部直接调⽤
def __birth_leave(self):
"""产假"""
print("休3个⽉产假")
def __str__(self):
return "我有%d个崽⼉:%d" % self.__children_count
dog1 = Dog()
dog1.birth()
print(dog1)
dog1.birth()
print(dog1)
⻰⽣⻰,凤⽣凤,⽼⿏的⼉⼦会打洞
面向对象三⼤特性: 封装 继承 多态
继承:某个类直接具备另⼀个类的能⼒(属性和⽅法)
格式:class ⼦类名:(⽗类名)
class Animal:
def eat(self):
print("-----吃-----")
def drink(self):
print("-----喝-----")
class Dog(Animal):
"""
def eat(self):
print("-----吃-----")
def drink(self):
print("-----喝-----")
"""
pass
xiao_hei = Dog()
xiao_hei.eat()
xiao_hei.drink()
多层继承
继承关系可以在多层间传递
class Animal:
def eat(self):
print("-----吃-----")
def drink(self):
print("-----喝-----")
class Dog(Animal):
def bark(self):
print("-----汪汪叫------")
class DYST(Dog):
"""定义了⼀个地狱三头犬类"""
pass
class Cat(Animal):
def catch(self):
print("----捉⽼⿏----")
dyd = SYST()
dyd.eat()
dyd.bark()
重写⽗类⽅法
当⼦类实现⼀个和⽗类同名的⽅法时,叫做重写⽗类⽅法
⼦类重写了⽗类⽅法,⼦类再调⽤该⽅法将不会执⾏⽗类的处理
class Animal:
def eat(self):
print("-----吃-----")
def drink(self):
print("-----喝-----")
class Dog(Animal):
def bark(self):
print("-----汪汪叫------")
class DYST(Dog):
"""定义了⼀个地狱三头犬类"""
def bark(self):
print("----嘻嘻嘻嘻-----")
dyd = DYST()
dyd.eat() # ----吃----
dyd.bark() # ----嘻嘻嘻嘻----
调⽤被重写的⽗类⽅法
⼦类重写了⽗类⽅法,仍然想执⾏⽗类中的⽅法,则可以在类中使⽤ super() 来调⽤⽅法
class Dog:
def bark(self):
print("-----汪汪叫------")
class DYST(Dog):
"""定义了⼀个地狱三头犬类"""
def bark(self):
print("----滚-----")
def see_host(self):
"""看⻅主⼈"""
print("冷漠脸")
# 调⽤已经被重写的⽅法 三种⽅式
Dog.bark(self) # ⽅式1
super(DYST, self).bark() # ⽅式2
super().bark() # ⽅式3 ⽅式2的简化形式
dyq = DYST()
dyq.see_host() # 输出: 冷漠脸 汪汪叫
私有和继承
⽗类中的 私有⽅法、属性,不会被⼦类继承
可以通过调⽤继承的⽗类的共有⽅法,间接的访问⽗类的私有⽅法、属性
class Animal(object):
def __init__(self):
self.num1 = 1
self.__num2 = 2
def __run(self):
print("----跑---")
def eat(self):
print("-----吃-----")
def drink(self):
print("-----喝-----")
def test(self):
print(self.__num2)
self.__run()
class Dog(Animal):
def bark(self):
print("-----汪汪叫------")
# self.__run() # ⽗类中的私有⽅法,没有被⼦类继承
print(self.num1)
# print(self.__num2) # ⽗类中的私有属性,没有被⼦类继承
xiao_hei = Dog()
xiao_hei.bark()
xiao_hei.test()
多继承
从图中能够看出,所谓多继承,即⼦类有多个⽗类,并且具有它们的特征
class Basketball:
def bark(self):
print("gun")
class Chicken:
def sing(self):
print("鸡你太美")
class Kun(Basketball, Chicken): # 多继承使⽤逗号隔开
pass
lianxisheng = Kun()
lianxisheng.bark() # gun
lianxisheng.sing() # 鸡你太美
注意点:
如果在上⾯的多继承例⼦中,如果⽗类篮球和⽗类鸡中,有⼀个同名的⽅法,那么通过⼦类去调⽤的时候,调⽤哪个?
class Basketball:
def eat(self):
print("东南西北风")
class Chicken:
def eat(self):
print("饲料")
class LXS(Basketball, Chicken):
# 在多继承中,调⽤指定⽗类的⽅法
def eat(self):
Chicken.eat(self) # 调⽤God的eat⽅法
zhangsan = LXS()
print(LXS.__mro__) # 多继承中使⽤ mro变量来查看继承查询顺序
zhangsan.eat() # 饲料
多态的概念是应⽤于Java和C#这⼀类强类型语⾔中,⽽Python崇尚“鸭⼦类型”。
所谓多态:定义时的类型和运⾏时的类型不⼀样,此时就成为多态。
Python伪代码实现Java或C#的多态
#-*- charset ='utf-8' -*-
class F1(object):
def show(self):
print 'F1.show'
class S1(F1):
def show(self):
print 'S1.show'
class S2(F1):
def show(self):
print 'S2.show'
# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既能执⾏S1对象的show⽅法,⼜能执⾏S2对象的show⽅法,所以定义了⼀个S1和S2类的⽗类
# 实际传⼊的参数是:S1对象和S2对象
def Func(F1 obj):
"""Func函数需要接收⼀个F1类型或者F1⼦类的类型"""
print obj.show()
s1_obj = S1()
Func(s1_obj) # 在Func函数中传⼊S1类的对象 s1_obj,执⾏ S1 的show⽅法,结果:S1.show
s2_obj = S2()
Func(s2_obj) # 在Func函数中传⼊Ss类的对象 ss_obj,执⾏ Ss 的show⽅法,结果:S2.show
Python “鸭⼦类型”
鸭⼦类型语⾔中,函数/⽅法可以接受⼀个任意类型的对象作为参数/返回值,只要该对象实现了代码后续⽤到的属性和⽅法就不会报错 。
class F1(object):
def show(self):
print 'F1.show'
class S1(F1):
def show(self):
print 'S1.show'
class S2(F1):
def show(self):
print 'S2.show'
def Func(obj):
print obj.show()
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
实例属性:
通过类创建的对象⼜称为实例对象,对象属性⼜称为实例属性,记录对象各⾃的数据,不同对象的同名实例属性,记录的数据可能各不相同。
类属性:
class Dog:
type = "狗" # 类属性
dog1 = Dog()
dog1.name = "大黄"
dog2 = Dog()
dog2.name = "小黑"
# 类属性 取值
print(Dog.type) # 结果:狗
print(dog1.type) # 结果:狗
print(dog2.type) # 结果:狗
提示:在python中 “万物皆对象”,类本身也是⼀个对象,执⾏class语句时会被创建,称为类对象。
使⽤场景:
注意点:
类属性只能通过类对象修改,不能通过实例对象修改
class Dog(object):
type = "狗" # 类属性
# 创建对象
dog1 = Dog()
Dog.type = "Dog" # 使⽤ 类对象 修改类属性
dog1.type = "dog" # 不是修改类属性, ⽽是创建了同名的对象属性type
print(Dog.type) # 结果为 "Dog" 类对象访问类属性
print(dog1.type) # 结果为 “dog” 类属性和对象属性同名,实例对象优先访问对象属性
类属性也可以设置为 私有,前边添加两个下划线。 如:
class Dog(object):
count = 0 # 公有的类属性
__type = "狗" # 私有的类属性
print(Dog.count) # 正确
print(Dog.__type) # 错误
类⽅法:类对象所拥有的⽅法
需要⽤装饰器 @classmethod 来标识其为类⽅法,对于类⽅法,第⼀个参数必须是类对象,⼀般以 cls 作为第⼀个参数。
class Dog(object):
__type = "狗"
# 类⽅法,⽤classmethod来进⾏修饰
@classmethod
def get_type(cls):
return cls.__type
print(Dog.get_type())
使⽤场景:
静态方法
需要通过装饰器 @staticmethod 来进⾏修饰,静态⽅法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。
静态⽅法也能够通过实例对象和类对象去访问。
class Dog(object):
type = "狗"
def __init__(self):
name = None
# 静态⽅法
@staticmethod
def introduce(): # 静态⽅法不会⾃动传递实例对象和类对象
print("⽝科哺乳动物,属于⻝⾁⽬..")
dog1 = Dog()
Dog.introduce() # 可以⽤ 实例对象 来调⽤ 静态⽅法
dog1.introduce() # 可以⽤ 类对象 来调⽤ 静态⽅法
使⽤场景:
当⽅法中既不需要使⽤实例对象(如实例对象,实例属性),也不需要使⽤类对象 (如类属性、类方法、创建实例等)时,定义静态⽅法 。
取消不需要的参数传递,有利于减少不必要的内存占⽤和性能消耗 。
注意点:
类中定义了同名的对象⽅法、类⽅法、静态⽅法时,调⽤⽅法会优先执⾏最后定义的⽅法 。
class Dog:
def demo_method(self):
print("对象⽅法")
@classmethod
def demo_method(cls):
print("类⽅法")
@staticmethod
def demo_method(): # 被最后定义,调⽤时优先执⾏
print("静态⽅法")
dog1 = Dog()
Dog.demo_method() # 结果: 静态⽅法
dog1.demo_method() # 结果: 静态⽅法
创建对象时,系统会⾃动调⽤new⽅法
开发者可以实现new⽅法来⾃定义对象的创建过程
class Cat:
def __new__(cls):
print("创建对象")
return object.__new__(cls)
def __str__(self):
return "%s" % self.name
dog1 = Dog()
dog1.age = 20
print(dog1)
总结
关于python面向对象的基本要点到这里就结束了,了解更多见:https://blog.csdn.net/Scrat_Kong/article/details/90257118