Python 面向对象(封装、继承、多态)

OOP(Object oriented Programming)面向对象编程

1 封装

根据职责将【属性】和【方法】封装到一个类中

1.1 类

1.1.1 描述

对具有相同特征(属性)或 行为(方法)的事物的统称
开发之前,需求分析阶段,需要确定程序中需要包含哪些类

类名:大驼峰命名法
属性:该类事物具有哪些特征
方法:该类事物具有哪些行为

1.1.2 定义类 class

class 类名:
	def 方法1(self,参数列表):
		pass
	def 方法2(self,参数列表):
		pass

1.1.3 私有属性和方法

对象的某些属性或方法,只希望在对象内部被使用,不对外界公开的属性和方法被称为私有属性和私有方法
子类同样不可以访问父类中的私有方法和属性

定义
__属性名 、__方法名

class Girl:
	def __init__(self,name):
		self.name = name
		# 私有属性
		self.__age = 30
	
	# 私有方法
	def __secret(self):
		print("%s is %s" % (self.name, self.__age))

补充:
Python 中没有真正的私有,而是伪私有
访问私有方法:
_类名 => _类名__名称

class Girl:
	def __init__(self,name):
		self.name = name
		# 私有属性
		self.__age = 30
	
	# 私有方法
	def __secret(self):
		print("%s is %s" % (self.name, self.__age))

jiejie = Girl("jiejie")

print(jiejie._Girl__age)
jiejie._Girl__secret()

1.1.4 实例属性和方法

调用方法:【实例对象.属性】、【实例对象.方法】

实例属性
__init__方法为实例属性初始化

class Cat:
	
	def __init__(self, name)
	self.name = name

# 创建对象
tom = Cat()
tom.name = "Tom"

实例方法

实例方法的第一个参数必须是self,哪个对象调用,self 就是哪个对象的引用

class Cat:
	
	def __init__(self, name)
	self.name = name
	
	def eat(self):
		print("%s eat" % self.name) # 输出 Tom eat
	def run(self):
		print("Cat run")

# 创建对象
tom = Cat()
tom.name = "Tom"
tom.eat() 

1.1.5 类属性和方法

类是一个特殊对象,程序运行,类同样会被加载到内存中,在内存中类对象只有一份。※
调用方法:【类名.属性】、【类名.方法】
【对象名.属性】同样可以调用类属性,但是不推荐使用,容易造成混淆

类属性

给类定义的属性,用于记录这个类相关的特征,不关心具体对象的特征
例:

class Tool(object):
	#类属性
	count = 0
	
	def __init__(self, name)
		self.name = name
		Tool.count += 1

tool1 = Tool("刀")
tool2 = Tool("枪")

补充:
属性向上查找机制
对象调用类属性时,先到该方法中查找该属性,如果没有,则会向上查找同名类属性,同样可以获取到类属性值(不推荐)

class Persion(object):

    count = 0

    def __init__(self):

        Persion.count += 1
        print("创建次数: %s " % Persion.count)


persion = Persion()
persion1 = Persion()
persion2 = Persion()

# 同样可以调用类属性(向上查找机制)
print(persion.count)

类方法

@classmethod 修饰
第一个参数必须是cls,cls. 调用类属性和方法

@classmethod
def 类方法名(cls):
	pass

实例:

class Persion(object):

	# 类属性
    count = 0

    def __init__(self):
        Persion.count += 1

	# 类方法
    @classmethod
    def clMethod(cls):
        print(cls.count)

per1 = Persion()
per2 = Persion()

Persion.clMethod()

1.1.6 静态方法

调用方法:【类名.方法】
即不访问实例属性,也不访问类属性的时候,可以用到静态 ※

@staticmethod 修饰
不需要传递第一个参数

@staticmethod
def 静态方法名():
	pass

当方法内部即需要访问实例属性,又需要访问类属性,应该定义为实例方法,因为类只有一个,在实例方法中通过类名.类属性 的方式也可以访问类属性。
实例:

class Dog(object):

	# 静态方法
    @staticmethod
    def run():
        print("run")

dog = Dog()
dog.run()

1.1.7 实例、静态、类类型综合练习

class Game(object):

    # 类属性,历史最高分
    top_score = 0

    def __init__(self,name):
        # 实例属性,玩家姓名
        self.player_name = name

    # 静态方法,显示帮助信息
    @staticmethod
    def show_help():
        print("这是游戏帮助信息")

    # 类方法,显示最高分数
    @classmethod
    def show_top_score(cls):
        print("最高分数为%s" % cls.top_score)

    # 实例方法,玩家开始游戏
    def start_game(self):
        print("%s 开始了游戏" % self.player_name)


# 查看帮助信息
Game.show_help()

# 查看历史最高分
Game.show_top_score()

# 创建游戏对象,并开启游戏
game = Game("chengcheng")
game.start_game()

1.1.8 object 基类

在Python3 中,object 是所有类的基类,内部封装了一些内置的属性和方法,用dir 函数可以查看
如果定义类时,没有指定父类,会默认使用object 作为该类的基类

在Python2 中定义类时,如果没有指定父类,则不会以object 作为基类

以object 为基类的类,称作新式类,新式类创建的对象,会默认拥有object 属性和内置方法
在Python2 中,如果指定了object 为基类,则该类同样属于新式类

补充:※
为了保证编写的代码能够同时在Python2 和Python3 运行,定义类时,如果没有父类,建议统一继承自object

1.2 实例对象

由类创建出的一个具体,可以直接使用

1.2.1 创建实例对象

实例类的对象创建后,在内存中就会生成一个实实在在的对象,由类创建的对象,叫做实例

对象变量 = 类名()

例:

class Cat:

	def eat(self):
		print("Cat eat")
	def run(self):
		print("Cat run")

# 创建对象
tom = Cat()

tom.eat()
tom.run()

1.2.2 给对象增加临时属性

对象变量.属性名 = “名称”
开发中不常用,并未真正修改类的属性,并且程序运行时,找不到该属性会报错

class Cat:

	def eat(self):
		print("Cat eat")
	def run(self):
		print("Cat run")

# 创建对象
tom = Cat()
tom.name = "Tom"

1.2.3 内置函数dir()

查看对象的所有属性和方法,“XX” 为该对象的内置方法和属性

方法名类型作用
__new__方法创建对象时,会被自动调用
__init__方法对象被初始化时,会被自动调用
__del__方法对象被从内存中销毁时,会被自动调用
__str__方法返回对象的描述信息,print 函数输出使用

1.2.4 初始化方法init

当使用 类名() 创建对象时,会自动为对象分配内存空间,并初始化属性值
初始化方法__init__,专门定义一个类具有哪些属性

class Cat:
	
	def __init__(self, new_name):
		
		print("this is init")
		self.name = new_name
	
	def eat(self):
		print("%s eat" % self.name)

tom = Cat("Tom")
print(tom.name) # 输出 TOM

fat = Cat("Fat")

1.2.5 销毁方法del

__del__,如果希望在对象被销毁前,再做一些事情,可以使用该方法

del 关键字,可以删除一个对象

1.2.6 生命周期

创建对象,生命周期开始调用__init__方法
__del__方法被调用后,生命周期结束
在对象的生命周期内,可以访问对象属性或调用方法

1.2.7 __str__方法

打印对象变量时,默认输出类名和该对象的内存地址,
在开发中,若希望能够打印对象的自定义内容时,可以使用该内置方法
该方法必须返回字符串

class Cat:
	
	def __init__(self, new_name):
		self.name = new_name
	
	def __str__(self):
		return "I am %s" % self.name

tom = Cat("Tom")
print(tom) #输出: I am TOM

1.2.8 None 关键字

表示一个空对象,没有任何方法和属性,可以赋值给任何一个变量
针对None 比较时,建议使用is 判断

1.2.9 身份运算符is

用于比较两个对象的内存地址是否一致,即是否是对同一个对象的引用

运算符描述实例
is判断两个标识符是不是引用同一个对象x is y, 类似 id(x) == id(y)
is not判断两个标识符是不是引用不同对象x is not y, 类似 id(x) != id(y)

1.2.10 is 和 == 区别

is 判断两个变量引用对象(内存地址)是否是同一个
== 判断引用变量的值是否相等

2 继承

2.1 作用

可以实现代码的重用

2.2 语法

class 类名(父类名):
	pass

2.3 继承的传递性

C 类继承B 类,B 类又继承A 类
则C 类具有B 类和A 类的所有属性和方法

2.4 方法的重写

当父类的方法不能满足子类需求时,可以在子类中定义一个和父类方法同名的方法并实现,达到方法的重写(override)

父类方法被重写后,可以用 “super().父类方法” 的方式来调用父类中的方法

应用技巧:
子类重写父类方法时,不必重写父类方法的所有内容,只是扩展方法功能的话,可以在重写方法中,结合super()方法来扩展子类方法。

补充:
Python 2.0 没有super() 方法,使用“父类名.方法(self)” 来实现对子类的调用,3.0之后不推荐使用。

2.5 多继承

子类可以拥有多个父类,并且具有所有父类的属性和方法

语法:

clas 子类名(父类名1, 父类名2...)
	pass

注意:
如果不同父类中存在同名的方法,子类对象在调用方法时,遵循MRO 方法搜索顺序;

MRO 方法搜索顺序
针对类的内置属性__mro__ 可以查看 方法搜索顺序

class A:

    def money(self):
        print("money1")

class B:

    def money(self):
        print("money2")

class C(A,B):

    pass

c = C()
c.money()

print(C.__mro__)

输出:
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

在开发中,尽量避免此种现象发生,容易产生混淆,如果父类之间存在同名的属性或者方法,应该尽量避免使用多继承。

3 多态

3.1 描述

不同的子类对象调用相同相同的父类方法,产生不同的执行结果
从而达到代码灵活度的目的
强调:多态是方法调用的技巧,不会影响到类的内部设计

3.2 前提

多态的使用前提,【继承】和 【重写】

3.2 应用 ※

父类作为参数类型,调用方法时可以传递父类也可以传递不同的子类,方法中传入不同的子类对象,会执行不同的结果。

实例:
Person 类中调用Dog 对象,而传递参数时,可以使用Dog 类的子类,从而可以灵活调用子类方法。
Person 类中game_with_dog 方法中,传入Dog 对象即可,不用关心传递的是什么Dog 对象,传入不同Dog 对象,可以实现不同效果。

class Dog(object):

    def __init__(self,name):
        self.name = name

    def game(self):
        print("%s 在地上玩耍" % self.name)


class XiaoTianDog(Dog):

    def game(self):
        print("%s fly game" % self.name)


class Person(object):

    def __init__(self,name):
        self.name = name

    def game_with_dog(self,dog):
        self.dog = dog
        print("%s 和 %s 玩耍" % (self.name,dog.name))

        dog.game()

#dog = Dog("tudou")
dog = XiaoTianDog("xiaotiangou")

xiaoming = Person("mingming")
xiaoming.game_with_dog(dog)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值