概述
文章目录
- 封装
- 继承和重写
- 继承基本思想
- super()扩展父类,重写
- 多继承
- 多态
- 类属性
- 类方法
- 静态方法
python
中可以在类的外面给对象增加属性,比如tom.name="Tom"
就可以给tom
类增加一个name
属性,但是这种方法并不推荐使用,最好都封装在类的内部。
在类的内部封装可以通过self
实现,self
的地址会跟实例化对象的地址一样。
在python3
中object
是所有类的基类。
封装
所谓封装,就是将属性和方法抽象地封装到一个类中。
继承和重写
面向对象(OOP
)三要素(封装 继承 多态)之一,继承Inheritance。继承可以让子类从父类获取特征(属性和方法),在面向对象的世界中,从父类继承,就可以直接拥有父类的属性和方法。
它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展,这样可以减少代码,多复用,子类可以定义自己的属性和方法。
在使用面向对象开发前,应该首先分析需求,确定一下,程序中需要包含哪些类。
继承基本思想
在使用类创建一个对象的时候就会执行init
方法,如果子类实现了init
方法,会走子类中的init
方法,如果子类没有实现init
方法,会找继承父类init
方法。
class Envrioment:
def __init__(self,env):
self.env = env
def get_observation(self):
print("Get Observation")
class Big_Env(Envrioment):
pass
a = Big_Env(1)
a.get_observation()
print(a.env)
>>>Get Observation
1
继承是具有传递性的,也就是子类也会有爷爷类的方法。
super()扩展父类,重写
如果父类原本封装的方法实现是子类方法的一部分,就可以使用扩展的方式。在需要的位置使用super().父类方法
来调用父类方法的执行,代码其它的位置针对子类的需求编写子类特有的代码实现。
在python
中super()
是一个特殊的类,super()
就是使用super
类创建出来的对象,最常使用的场景就是在重写父类方法时,调用在父类中封装的方法实现。
子类同样是不能访问父类的私有属性和私有方法的。
可依据魔法属性mro
(method resolution order)顺序查看。
class little_animal():
def __init__(self, sleep):
self.sleep = sleep
class animal(little_animal):
def __init__(self, sleep, eat, drink):
super().__init__(sleep)
self.eat = eat
self.drink = drink
def run(self):
print("rrrrr")
class dog(animal):
def __init__(self,bark,sleep,eat,drink):
super().__init__(sleep,eat,drink)
self.bark = bark
def run(self):
super().run()
print("ttttt")
a = dog(1,2,3,4)
print(a.bark, a.sleep, a.eat, a.drink)
a.run()
print(dog.__mro__)
输出:
1 2 3 4
rrrrr
ttttt
(<class '__main__.dog'>, <class '__main__.animal'>, <class '__main__.little_animal'>, <class 'object'>)
在继承里面一定要注意的是继承不是复制,他只是指向父类,此时如果改变父类的值,子类相应的值也会发生改变。只有重写之后,也就是在子类中对其进行重新赋值之后,改变父类的值不会改变子类的值。
多继承
子类可以有多个父类,并且具有所有父类的属性和方法。
class A:
def test(self):
print("Test")
class B:
def demo(self):
print("demo")
class C(A,B):
pass
C_test = C()
C_test.test()
C_test.demo()
>>>Test
demo
在多继承中要注意的问题就是,应该尽量避免产生不同父类存在同名的方法。
为了保证编写的代码能够同时在Python2
和Python3
中同时运行,今后定义类时,如果没有父类,建议统一继承自object
。
多态
多态:不同的子类对象调用相同的父类方法,产生相同的执行结果。多态可以增加代码的灵活度,以继承和重写父类方法为前提。是调用方法的技巧,不会影响到类的内部设计。
class Dog(object):
def __init__(self, name):
self.name = name
def paly(self):
print("Dog {} Play With Game".format(self.name))
class Fly_Dog(object):
def __init__(self, name):
self.name = name
def play(self):
print("Fly_Dog {} Play With Game".format(self.name))
class Person(object):
def __init__(self, name):
self.name = name
def play(self, dog):
print("Person {} Play With Dog {}".format(self.name, dog.name))
P = Person("Bob")
P.play(Dog("Wangcai"))
P.play(Fly_Dog("xiaotian"))
>>> Person Bob Play With Dog Wangcai
Person Bob Play With Dog xiaotian
类属性
使用面向对象开发,第一步是设计类。使用类名()
创建对象,创建对象的动作有两步:
- 在内存中为对象分配空间。‘
- 调用初始化方法
__init__
为对象初始化
对象创建后,内存中就有一个对象的实实在在的内存(实例)。上述是创建对象的完整过程。
- 若创建了多个对象,每个对象有自己独立的内存空间,保存各自不同的属性。
- 多个对象的方法,在内存中只有一份,需要把对象的引用传递到方法内部。
在Python
中类是一个特殊的对象,且一切皆对象。在程序运行时,类对象同样会被加载到内存。
class AAA
:定义的类属于类对象。obj1 = AAA()
: 属于实例对象。
在程序运行时,类对象在内存中只有一份,使用一个类可以创建很多个对象实例。除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法。
class Tool(object):
count = 0
def __init__(self):
Tool.count += 1
a = Tool()
b = Tool()
print(Tool.count)
print(b.count)
>>> 2
2
类属性用来记录与这个类相关的特征,不会记录具体对象的特征。如果通过实例化对象来访问,其会先在实例化对象的方法中找该属性,没有的话就会在类里面去找。因此访问类属性有两种方式:
- 类名.类属性
- 对象.类属性(不推荐)
如果这里程序最后再设置b.count=10
,那么此时python
解释器会给实例化的对象b
创建一个属性,而不是向上去查找类属性,因此不会改变Tool.count
的值。也就是说使用对象.类属性=值
赋值语句,只会给对象添加一个属性,而不会影响到类属性的值。
类方法
从上文类属性的文章中我们可以知道,使用赋值语句在class
关键字下方可以定义类属性。
- 类方法就是针对类对象定义的方法。在类方法内部可以直接访问类属性,或者调用其他的类方法。
语法如下:
@classmethod
def 类方法名(cls):
pass
类方法需要用修饰器@classmethod
来标识,告诉解释器这是一个类方法。
第一个参数是cls
。由哪一个类调用的方法,方法内的cls
就是哪一个类的引用,这个参数和实例方法的第一个参数是self
类似,使用其他名称也可以,不过习惯使用cls
。
通过类名.
调用类方法。调用方法时,不需要传递cls
参数,在方法内部可以通过cls.
访问类的属性,也可以通过cls.
调用其他类方法。
class Tool(object):
count = 0
@classmethod
def num_of_count(cls):
print("The num of tool is {}".format(cls.count))
def __init__(self):
Tool.count += 1
a = Tool()
a.num_of_count()
>>> The num of tool is 1
静态方法
开始之前先总结一下类方法和实例方法:1. 如果需要访问实例属性,那将这个方法封装成实例方法。2. 如果某一个方法不需要访问实例属性,但是需要访问类属性,那么这个时候可以考虑将这个方法封装成类方法。
如果某一个方法既不需要访问其类属性,也不需要访问其实例属性(里面没有用到self.
这种操作访问东西,比如单纯的一个print
),那么可以将这个方法封装成静态方法。
语法如下:
@staticmethod
def 静态方法(): # 不需要指定第一个参数,因为它什么都不需要访问
pass
如:
class Dog(object):
@staticmethod
def run():
print("Run ...")
最后
以上就是畅快钻石为你收集整理的Python进阶(二)Python中的类继承、封装、多态使用方法的全部内容,希望文章能够帮你解决Python进阶(二)Python中的类继承、封装、多态使用方法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复