面向对象特性
1. 继承
Outline
·继承概念
·单继承/多继承
·子类重写/调用父类的同名属性和方法
·多层继承
·super()
·私有属性和私有方法
1.1 继承的概念
继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法
·拓展:经典类(旧式类)与新式类
·不由任意内置类型派生出的类称为经典类
·也即:继承了object类的是新式类,没有继承object类的是经典类
·注意:在python3中所有自定义类的基类都会默认继承object类,也即py3中所有类都是新式类
# 经典类
class ClassName:
......
......
# 新式类
class ClassName(object):
......
......
·在python3中,所有类默认继承object类,object类是顶级类或基类;其他自类叫做派生类
1.2 单继承/多继承
·注意:需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
# 单继承 && 多继承
class Python:
code_language = ''
def __init__(self):
self.code_language = 'Python'
def code(self):
print(f"I'm coding in {self.code_language}")
class Java:
code_language = ""
def __init__(self):
self.code_language = 'Java'
def code(self):
print(f"I'm coding in {self.code_language}")
# 单继承
class subLang(Python):
pass
# 多继承
class sub2Lang(Java,Python):
pass
lang1 = subLang()
lang1.code()
lang2 = sub2Lang()
lang2.code()
I'm coding in Python
I'm coding in Java
1.3 子类重写/调用父类同名方法和属性
·子类和父类具有同名属性和方法时,默认使用子类的
# 重写父类方法
class sub3Lang(Java,Python):
def __init__(self):
self.code_language = 'Scala'
def code(self):
print("code by %s" % self.code_language)
lang3 = sub3Lang()
lang3.code()
print("--"*5)
# 调用父类方法
class sub4Lang(Java,Python):
def __init__(self):
self.code_language = 'scala'
def code(self):
#如果先调用了父类属性和方法,父类属性会覆盖子类属性,所以在调用属性前,先调用子类的初始化
self.__init__()
print("code by %s" % self.code_language)
# 调用父类方法,为了保证调用到的是父类属性,在调用方法前先调用父类的初始化
def codeByPython(self):
Python.__init__(self)
Python.code(self)
def codeByJava(self):
Java.__init__(self)
Java.code(self)
lang4 = sub4Lang()
lang4.code()
lang4.codeByPython()
lang4.codeByJava()
lang4.code()
code by Scala
----------
code by scala
I'm coding in Python
I'm coding in Java
code by scala
1.4 多层继承
# 多层继承
class sub5Lang(sub4Lang):
pass
lang5 = sub5Lang()
lang5.code()
lang5.codeByPython()
lang5.codeByJava()
code by scala
I'm coding in Python
I'm coding in Java
1.5 super()
1.5.1 __mro__
·查看一个类的父类及层级关系(继承层级顺序)
# __mro__
print(sub5Lang.__mro__)
print(sub4Lang.__mro__)
print(subLang.__mro__)
(<class '__main__.sub5Lang'>, <class '__main__.sub4Lang'>, <class '__main__.Java'>, <class '__main__.Python'>, <class 'object'>)
(<class '__main__.sub4Lang'>, <class '__main__.Java'>, <class '__main__.Python'>, <class 'object'>)
(<class '__main__.subLang'>, <class '__main__.Python'>, <class 'object'>)
1.5.2 super()方法
作用:调用父类方法
语法:
# 带参形式
super(当前类名,self).funName()
# python3中可以使用简化写法
super().funName()
·注意:super可以自动查找父类,调用顺序遵循__mro__的顺序,适合单继承使用。
1.6 私有权限
1.6.1 定义私有属性和方法
·在python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或方法不继承给子类
·方法:在属性名/方法名前面加两个下划线
·注意:私有属性和私有方法只能在类中访问和修改
# 定义私有属性和方法
class Father():
def __init__(self):
self.house = 'BJ2huan'
self.__money = "9999999$"
def __giveMoney(self):
print(f"give u {self.__money}")
man = Father()
man.__giveMoney()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-15-7260ef001b55> in <module>
8
9 man = Father()
---> 10 man.__giveMoney()
AttributeError: 'Father' object has no attribute '__giveMoney'
print(man.__money)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-16-0f10097db91d> in <module>
----> 1 print(man.__money)
AttributeError: 'Father' object has no attribute '__money'
1.6.2 获取和修改私有属性值
一般定义get_xx来获取私有属性,定义set_xx来修改私有属性
class dad():
def __init__(self):
self.__money = '$9999999999'
def get_money(self):
return self.__money
def set_money(self,money):
self.__money = money
man = dad()
print(man.get_money())
man.set_money('¥999999')
print(man.get_money())
$9999999999
¥999999
2. 多态
·定义:多态是一种使用对象的方式;子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行效果
·好处:调用灵活,让代码可重用性提高
·实现步骤:
1.定义父类,提供公共方法
2.定义子类,重写父类方法
3.将子类对象传给调用者,可以看到不同子类执行效果不同
class Dog:
def work(self):
pass
class PoliceDog(Dog):
def work(self):
print("Follow and find the animy")
class DrugDog(Dog):
def work(self):
print("Find the drugs")
class Policeman:
def workWithDog(self,dog):
dog.work()
police_dog = PoliceDog()
drug_dog = DrugDog()
police = Policeman()
police.workWithDog(police_dog)
police.workWithDog(drug_dog)
Follow and find the animy
Find the drugs
3. 类属性和实例属性
3.1 类属性
3.1.1 设置&访问类属性
·类属性就是类对象所拥有的属性,它被该类的所有实例对象 共有
·类属性可以使用类对象或实例对象访问
class Cat:
brother = 'tiger'
daJu = Cat()
xiaoHua = Cat()
print(f"cat's bro : {Cat.brother} \n\
daju's bro:{daJu.brother} \n\
xiaohua's bro: {xiaoHua.brother}")
cat's bro : tiger
daju's bro:tiger
xiaohua's bro: tiger
·类属性的优点
- 记录的某项数据 始终保持一致时,则定义类属性。
- 实例属性 要求 每个对象 为其 单独开辟一份内存空间 来记录数据,而 类属性 为全类所共有 ,仅占用一份内存,更加节省内存空间。
3.1.2 修改类属性
·类属性只能通过类对象来修改,而不能通过实例对象来修改,如果通过实例对象来修改类属性,实际上表示创建了一个实例属性。
# 修改类属性
Cat.brother = 'xiba'
print(f"cat's bro : {Cat.brother} \n\
daju's bro:{daJu.brother} \n\
xiaohua's bro: {xiaoHua.brother}")
print("---"*10)
# 不能通过实例对象修改类属性
daJu.brother = 'cat'
print(f"cat's bro : {Cat.brother} \n\
daju's bro:{daJu.brother} \n\
xiaohua's bro: {xiaoHua.brother}")
cat's bro : xiba
daju's bro:cat
xiaohua's bro: xiba
------------------------------
cat's bro : xiba
daju's bro:cat
xiaohua's bro: xiba
3.2 实例属性
class Cat:
def __init__(self):
self.age = 5
def print_info(self):
print(self.age)
shabi = Cat()
print(shabi.age)
shabi.print_info()
print(Cat.age) # 报错:实例属性不可以通过类对象访问
5
5
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-29-f947428b7ef1> in <module>
8 print(shabi.age)
9 shabi.print_info()
---> 10 print(Cat.age) # 报错:实例属性不可以通过类对象访问
AttributeError: type object 'Cat' has no attribute 'age'
4. 类方法和静态方法
4.1 类方法
4.1.1 类方法的特点
·需要使用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls为第一个参数
4.1.2 类方法的使用场景
·当方法中需要使用类对象(如访问私有类属性等)时,定义类方法
·类方法一般需要和类属性配合使用
class Doggie:
__master = 'jcl'
@classmethod
def get_mastername(cls):
return cls.__master
wangcai = Doggie()
print(wangcai.get_mastername())
jcl
4.2 静态方法
4.2.1 静态方法特点
- 需要使用装饰器@staticmethod来修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)
- 静态方法也能通过实例对象和类对象去访问。
4.2.2 静态方法使用场景
- 当方法中既不需要使用实例对象(如实例对象或属性),也不需要使用类对象(类对象/属性/创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利于减少不必要地内存占用和性能消耗
class Doggg:
@staticmethod
def print_info():
print("This is a dog class,try to create a dog object")
wangcai = Doggg()
wangcai.print_info()
Doggg.print_info()
This is a dog class,try to create a dog object
This is a dog class,try to create a dog object
Summary
面向对象三大特性:
- 封装
- 将属性和方法书写到类的里面的操作即为封装
- 封装可以为属性和方法添加私有权限
- 继承
- 子类默认继承父类的所有属性和方法
- 子类可以重写父类属性和方法
- 多态
- 传入不同的对象,产生不同的结果