一、面向对象简介
面向对象(OOP)是一种对现实世界理解和抽象的方法,对象的含义是指在现实生活中能够看得见摸得着的具体事物,一句比较经典的描述是一切皆对象,Python 是一门面向对象的语言,面向对象编程简单来说就是一种封装代码的方式。
1、面向对象相关概念
-
类:描述具有相同属性和方法的集合,简单来说就是一个模板,通它来创建对象。
-
对象:类的实例。
-
方法:类中定义的函数。
-
类变量:定义在类中且在函数之外的变量,在所有实例化对象中公用。
-
局部变量:方法中定义的变量,只作用于当前实例。
2、面向对象三大特性
-
封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,提高复用性和安全性。
-
继承:一个类继承一个基类便可拥有基类的属性和方法,可提高代码的复用性。
-
多态:父类定义的引用变量可以指向子类的实例对象,提高了程序的拓展性。
二 、类属性和类方法
2.1类属性
-
定义在类里面,方法外面,定义的时候不需要self关键字,语法类似于定义普通变量
-
不需要把类实例化为对象,直接通过类名.属性名 使用
2.2类方法
-
类方法不需要把类实例化为对象,通过类名.类方法名调用
-
用@classmethod来修饰的方法,就是类方法
-
类方法的参数为 cls,在类方法内部通过 cls.类属性 或者 cls.类方法 来访问同一个类中的其他类属性和类方法;
-
类方法不需要实例化就可以调用,类方法只能访问同一个类中的类属性和类方法。
-
类方法的一个参数是cls(不是self)
-
在类方法内部如果使用类属性, cls.类属性名
-
类方法内部不能使用普通属性,也不能调用普通方法
-
因为类方法不需要对象的,但普通方法和普通属性一定需要通过对象调用
-
三、面向对象简单实现
定义类的格式
2.1 类
# 定义一个类
class StuInfo():
# 定义属性
age = "10"
addr = "hebei"
name = "tom"
# 定义方法
def showInfo(self): # 类中的方法的第一个形参必须是self
#print("%s的年龄是%s, 地址在%s"%(name, age, addr)) # 此时这三个变量是去全局段找
print("%s的年龄是%s, 地址在%s"%(self.name, self.age, self.addr)) # 加上self是去类内部找变量
# 进行实例化,将实例化结果赋值给stu1变量
# stu1是一个对象
stu1 = StuInfo()
# 显示类属性
print(stu1.age)
print(stu1.addr)
print(stu1.name)
# 调用类方法
stu1.showInfo()
构造方法 __init__()
会在类实例化时自动调用。无论构造方法还是其他方法都需要将 self
作为第一个参数,它代表类的实例。
类创建好后,我们可以直接通过类名访问属性,格式为:类名.属性名
,比如我们访问 Cat 类的 color 属性,如下所示:
# 显示类属性
print(stu1.age)
print(stu1.addr)
print(stu1.name)
上面 StuInfo 类中定义的属性和方法都是公开的,除此之外我们还可以定义私有属性和方法,声明方式为:在属性名或方法名前加两条下划线,示例如下所示:
类的私有属性和私有方法
-
私有属性就是对象不希望公开的属性 ;
-
私有⽅法就是对象不希望公开的⽅法 。
class woman:
def __init__(self):
self.name = "玛丽"
self.__weight = 200 # __weigth是一个私有属性
def __eat(self): # __eat方法为私有方法
print("吃的很多")
w = woman()
print(w.name)
# print(w.__weight) 不能在类的外部访问类的私有属性
# w.__eat() 不能在类的外部调用私有方法
-
在定义属性或⽅法时,在属性名或者⽅法名前 增加两个下划线,定义的就是私有属性或方法。
-
对于私有属性和私有方法,只能在类的内部访问,类的外部无法访问。
-
就是把类的属性和方法封装到类的内部,只能在内部使用,不能在类的外部使用
-
把属性和方法名前面加两个下划线__,这个属性和方法就成为了类的私有属性和方法
需要强调一点是:外部不能访问私有属性和调用私有方法,自然 Cat.__cid
是会报错的。
2.2 对象
创建对象也称类的实例化,比如我们通过 MyClass类创建对象,如下所示:
# 定义一个类
class MyClass():
"""
这是我的测试类
你听懂了吗
"""
name = "python开发"
def __init__(self):
self.height = "175"
def show(self):
age = "20"
print("%s 的年龄是 %s, 身高是%s"%(self.name, age, self.height))
# 创建对象 也叫类的实例化
str = MyClass()
# 使用方法
str.show()
创建好对象后,我们就可以使用它访问属性和调用方法了。
四、继承
继承的概念
-
⼦类拥有⽗类的所有⽅法和属性。
继承的语法
class 类名(⽗类名):
pass
-
⼦类继承⾃⽗类,可以直接享受⽗类中已经封装好的⽅法,不需要再次开发
-
⼦类中应该根据职责,封装⼦类特有的属性和⽅法。
专业术语
-
子类---派生类
-
dog是animal的子类
-
dog是animal的派生类
-
-
父类---基类
-
animal是dog的父类
-
animal是dog基类
-
-
继承---派生
-
dog类继承自animal
-
dog类派生自animal
-
-
一个父类可以有多个子类继承,每个子类可以有自己特有的方法和属性
object 类
在 Python 3 中定义类时,如果没有指定⽗类,会默认使⽤ object 作为该类的基类 —— Python 3 中定义的类都是新式类 。
在 Python 2 中定义类时,如果没有指定⽗类,则不会以 object 作为基类 。新式类和经典类在多继承时 —— 会影响到⽅法的搜索顺序 。
为了保证编写的代码能够同时在 Python 2 和 Python 3 运⾏! 今后在定义类时,如果没有父类,建议统一继承自 object。
五、方法的重写
当⽗类的⽅法实现不能满⾜⼦类需求时,可以对⽅法进⾏ 重写(override)。
方法重写有两种方式
-
覆盖父类方法
-
扩展父类方法
覆盖父类方法
如果在开发中,⽗类的⽅法实现和⼦类的⽅法实现,完全不同 ,就可以使 ⽤覆盖的⽅式,在⼦类中重新编写⽗类的⽅法实现 。
具体的实现⽅式,就相当于在⼦类中定义了⼀个 和⽗类同名的⽅法并且实现 。
重写之后,在运⾏时,只会调⽤⼦类中重写的⽅法,⽽不再会调⽤父类封装 的方法
-
子类中出现和父类相同的方法,那么在子类中相同方法会把父类的方法覆盖
class animal:
def sleep(self):
print("睡")
def eat(self):
print("吃")
class dog(animal):
def eat(self): # 出现和父类同名方法,在子类dog中,就没有父类的eat方法了
print("吃肉")
d = dog()
d.sleep()
d.eat() # 由于覆盖了父类的eat方法,,所以这里调用的是dog类的eat方法
扩展父类方法
-
如果父类的方法不能完全满足子类需求, 子类可以在父类方法基础上增加功能
语法
1.在子类中实现和父类同名方法
2.在子类的同名方法中用super().父类同名方法 来调用父类的方法
class animal:
def sleep(self):
print("睡")
def eat(self):
print("吃")
class dog(animal):
def sleep(self):
super().sleep() # 在子类方法中调用父类的sleep方法
print("睡得更多")
d = dog()
d.sleep() # 扩展了父类的sleep,所以既执行了父类的sleep,又增加了功能
⽗类的私有属性和私有⽅法
-
1.⼦类对象不能在⾃⼰的⽅法内部,直接访问⽗类的私有属性或私有⽅法;
-
2.⼦类对象 可以通过⽗类的公有⽅法间接访问到私有属性或私有⽅法; 私有属性、⽅法是对象的隐私,不对外公开,外界以及⼦类都不能直接访问私有属性、⽅法通常⽤于做⼀些内部的事情 。
父类的私有成员不会继承给子类
-
父类中所有的私有方法和私有属性归父类特有,子类不能继承
class animal:
def sleep(self):
print("睡")
def __eat(self): # 私有成员不会被子类继承
print("吃")
class dog(animal): # 在dog类里面,没有__eat方法
pass
d = dog()
d.sleep()
# d.__eat() # 这里的代码会出错
六、多态
不同的子类,调用相同的父类方法,产生不同的结果
多态的前提,不同的子类来自相同的一个父类,子类会覆盖父类的方法
七、静态方法
如果需要在类中封装⼀个⽅法,这个⽅法既不需要访问实例属性 或者调⽤实例⽅法也不需要访问类属性或者调⽤类⽅法, 这个时候,可以把这个⽅法封装成⼀个静态⽅法。
-
在类中通过@staticmethod修饰的方法
-
静态方法不需要实例化为对象,通过类名.静态方法名 调用
-
静态方法不能访问类中的其他成员,静态方法就是一个独立与类存在的函数
格式:
class dog:
@staticmethod
def help():
print("这是一个静态方法")
dog.help()
静态方式使用场景
-
当代码量特别大的时候,函数也会特别多,为了避免函数的重名,可以把同名函数放到不同的类里面,做为静态方法
-
避免由于函数重名带来错误
以上就是面向对象的所有内容,觉得有用的朋友可以点点收藏,还会更新更多有用的知识。