类和对象都是面向对象中的重要概念。面向对象是一种编程思想,即按照真实世界的思维方式构建软件系统。
比如在现实中,学校有学生和老师,学生有学号、姓名、班级等属性(数据),提问、学习、吃饭等动作(方法)。如果我们开发个消炎管理系统,会有学生和老师等“类”,王同学、刘同学是学生类的个体,被成为“对象”。
比如下图形象的比喻
1.定义类
Python中的数据类型都是类,我们可以自定义类,即创建一种新的数据类型。
class 类名 [(父类)]:
类体
备注:父类可以省略声明,表示直接继承object类
class Car(object):
# 类体
pass # 维持程序结构的完整,临时占用
小汽车(Car)类继承了object类,object类是所有类的根类,在Python中任何一个类(除object外)都直接或间接地继承了object,直接继承object时(object)部分的代码可以省略。
创建对象
类相当于一个模版,依据这样的模版来创建对象,就是类的实例化,所以对象也被成为“实例”。
class Car(object):
# 类体
pass # 维持程序结构的完整,临时占用
car = Car()
2.类的成员
成员变量也被称为数据成员,保存了类或对象数据
构造方法是一种特殊的函数,用于初始化类的成员变量。
成员方法是在类中定义的函数。
属性是对类进行封装而提供的特殊方法。
实例变量和实例方法属于对象,通过对象调用。而类变量和类方法属于类,属于类调用。
a.实例变量
实例变量就是对象个体特有的“数据”,如猫的名字,年龄等
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/28 14:59
@File: leiandduix-a.py
@IDE: PyCharm
"""
class Cat:
def __init__(self, name, age):
self.name = name # 创建和初始化实例变量name
self.age = age # 创建和初始化实例变量age
c = Cat('西西', 2)
print('这个猫的名字叫{0},{1}岁了。'.format(c.name, c.age))
b.构造方法
类中的__init__()方法是一个非常特殊的方法,用来创建和初始化实例变量,这种方法就是“构造方法”。在定义__init__()方法时,它的第1个参数应该是self,之后的参数用来初始化实例变量。调用构造方法时不需要传入self参数。
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/28 14:59
@File: leiandduix-b.py
@IDE: PyCharm
"""
class Cat:
def __init__(self, name, age, sex='雌性'):
self.name = name # 创建和初始化实例变量name
self.age = age # 创建和初始化实例变量age
self.sex = sex # 创建和初始化实例变量sex
c1 = Cat('西西', 2) # 创建对象调用构造方法,省略默认值
c2 = Cat('钉钉', 1, '雌性')
c3 = Cat(name = '库库', sex='雄性', age=3)
print('这个猫的名字叫{0},{1}岁{2}。'.format(c1.name, c1.age, c1.sex))
print('这个猫的名字叫{0},{1}岁{2}。'.format(c2.name, c2.age, c2.sex))
print('这个猫的名字叫{0},{1}岁{2}。'.format(c3.name, c3.age, c3.sex))
c.实例方法
实例方法与实例变量一样,都是某个实例(或对象)个体特有的方法。
定义实例方法时,它的第1个参数也应该是self,这会將当前实例与该方法绑定起来,这样说明该方法属于实例。在调用方法时不需要传入self,类似构造方法。
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/28 14:59
@File: leiandduix-c.py
@IDE: PyCharm
"""
class Cat:
def __init__(self, name, age, sex='雌性'):
self.name = name # 创建和初始化实例变量name
self.age = age # 创建和初始化实例变量age
self.sex = sex # 创建和初始化实例变量sex
# 实例方法
def run(self):
print("{}在跑。。。".format(self.name))
# 实例方法
def speak(self, sound):
print('{}在叫,"{}"'.format(self.name, sound))
cat = Cat('哈哈', 2)
cat.run()
cat.speak('喵~~')
d.类变量
类变量是属于类的变量,不属于当个对象
有一个Account(银行账户)类,有三个成员变量:amountt(账户金额)、interest_rate(利率)和owner(账户名)。amount和owner对于每一个账户都是不同的,而interest_rate对于所有账户都是相同的。amount和owners是实例变量,interest_rate是所有账户实例共享的变量,它属于类,被称为“类变量”。
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/28 15:59
@File: leiandduix-d.py
@IDE: PyCharm
"""
class Account:
interest_rate = 0.0568 # 类变量利率interset_rate
def __init__(self, owner, amount):
self.owner = owner
self.amouont = amount
account = Account('Tony', 800000.0)
print('账户名:{0}'.format(account.owner))
print('账户金额:{0}'.format(account.amouont))
print('利率:{0}'.format(Account.interest_rate))
e.类方法
类方法与类变量类型,属于类,不属于个体实例,在定义类方法时,它的第1个参数不是self,而是类本身。
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/28 15:59
@File: leiandduix-d.py
@IDE: PyCharm
"""
class Account:
interest_rate = 0.0568 # 类变量利率interset_rate
def __init__(self, owner, amount):
self.owner = owner
self.amount = amount
# 类方法
@classmethod # 定义类方法需要的装饰器,装饰器以@开头修饰函数、方法和类,用来约束他们
def interest_by(cls, amt): # cls代表类自身,就是Account类
return cls.interest_rate * amt # cls可以直接使用Account替换,cls.interest_rate * amt也可以写成Account.interest_rate * amt
interest = Account.interest_by(12000.0) # 对类的方法可以通过“类名.类方法”访问
print('计算利息:{0:.4f}'.format(interest))
3.封装性
封装性是面向对象重要的基本特性之一。封装隐藏了对象的内部细节,只保留有限的对外接口,外部调用者不用关心对象的内部细节,使得操作对象变得简单。
一台计算机内部极其复杂,有主板、CPU、硬盘和内存等,而一般人不需要了解它的内部细节。计算机制造商用机箱把计算机封装起来,对外提供了一些接口,如鼠标、键盘和显示器等,使用计算机就变得非常简单。
a.私有变量
为了防止外部调用者随意存取类的内部数据(成员变量),内部数据(成员变量)会被封装成“私有变量”。外部调用者职能通过方法调用私有变量。
默认情况下,python的变量是公有的,可以在类的外边访问它们,如果想成为私有变量,在变量前加上双下划线“__”即可
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/29 11:43
@File: fengzhuang-a.py
@IDE: PyCharm
"""
class Account:
__interest_rate = 0.0568 # 类变量利率,私有类变量
def __init__(self, owner, amount):
self.owner = owner
self.__amount = amount # 私有实例变量
def desc(self): # 在类的内部可以访问私有变量
print("{0} 金额:{1} 利率:{2}。".format(self.owner, self.__amount, Account.__interest_rate))
account = Account('Maoge', 80000, 0)
account.desc()
print('账户名:{0}'.format(account.owner))
print('账户金额:{0}'.format(account.__amount)) # 会报错
print('利率:{0}'.format(Account.__interest_rate)) # 会报错
b.私有方法
私有方法与变量封装是类似的,在方法前加双下划线__
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/29 11:43
@File: fengzhuang-b.py
@IDE: PyCharm
"""
class Account:
__interest_rate = 0.0568 # 类变量利率,私有类变量
def __init__(self, owner, amount):
self.owner = owner
self.__amount = amount # 私有实例变量
def __get_info(self):
return "{0} 金额:{1} 利率:{2}。".format(self.owner, self.__amount, Account.__interest_rate)
def desc(self): # 在类的内部调用私有方法
print(self.__get_info())
account = Account('Maoge', 80000, 0)
account.desc()
account.__get_info() # 会报错
由于在类的外部不可以访问私有方法,所有运行会报错。
c.使用属性
为了实现对象的封装,在一个类中不应该有公有的成员变量,这些成员变量应该被设计为私有的,然后通过公有的set (赋值)和get(取值)方法访问。
使用set和get方法进行封装,
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/29 11:43
@File: fengzhuang-d.py
@IDE: PyCharm
"""
class Cat:
# 构造方法
def __init__(self, name, age, sex='雌性'):
self.name = name
self.__age = age
# 实例方法
def run(self):
print("{}在跑。。。".format(self.name))
# get方法
def get_age(self):
return self.__age
# set方法
def set_age(self, age):
self.__age = age
cat = Cat('毛雪', 2)
print('猫的年龄:{}'.format(cat.get_age()))
cat.set_age(3)
print('修改后猫的年龄:{}'.format(cat.get_age()))
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/29 11:43
@File: fengzhuang-.py
@IDE: PyCharm
"""
class Cat:
# 构造方法
def __init__(self, name, age, sex='雌性'):
self.name = name
self.__age = age
# 实例方法
def run(self):
print("{}在跑。。。".format(self.name))
@property # 定义age属性的get()方法,使用@property装饰器进行修饰,方法名就是属性名,即age
def age(self): # 替代get_age(self)
return self.__age
@age.setter
def age(self, age): # 替代set_age(self,age)
self.__age = age
cat = Cat('毛雪', 2)
print('猫的年龄:{}'.format(cat.age()))
cat.age = 3 # cat.set_age(3)
print('修改后猫的年龄:{}'.format(cat.age()))
4.继承性
在现实世界中继承关系无处不在。例如猫与动物之间的关系:猫是一种特殊动物,具有动物的全部特征和行为,即数据和操作。在面向对象中动物是一般类,被称为“父类”;猫是特殊类,被称为“子类”。特殊类拥有一般类的全部数据和操作,可称之为子类继承父类。
a.Python中的继承
在Python中声明子类继承父类,语法很简单,定义类时在类的后面使用一对小括号指定它的父类就可以了
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/30 13:07
@File: jicheng-a.py
@IDE: PyCharm
"""
class Animal:
def __init__(self,name):
self.name = name
def show_info(self):
return "动物的名字:{0}".format(self.name)
def move(self):
print("动一下")
class Cat(Animal):
def __init__(self, name, age):
super().__init__(name)
self.age = age
cat = Cat('小黎', 3)
cat.move()
print(cat.show_info())
b.多类继承
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/30 13:12
@File: jicheng-b.py
@IDE: PyCharm
"""
class Hourse:
def __init__(self,name):
self.name = name # 实例变量
def show_info(self):
return "马的名字:{0}".format(self.name)
def run(self):
print("马动起来")
class Donkey:
def __init__(self, name):
self.name = name
def show_info(self):
return "驴的名字:{0}".format(self.name)
def run(self):
print("驴动起来")
def roll(self):
print("驴打滚")
class Mule(Hourse,Donkey):
def __init__(self, name, age):
super().__init__(name)
self.age = age
m = Mule('骡子', 3)
m.run() # 继承父类Horse方法
m.roll() # 继承父类Donkey
print(m.show_info()) # 继承父类Horse方法
c.方法重写
如果子类的方法名与父类的方法名相同,则在这种情况下,子类的方法会重写(Override)父类的同名方法。
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/30 13:12
@File: jicheng-c.py
@IDE: PyCharm
"""
class Hourse:
def __init__(self, name):
self.name = name # 实例变量
def show_info(self):
return "马的名字:{0}".format(self.name)
def run(self):
print("马动起来")
class Donkey:
def __init__(self, name):
self.name = name
def show_info(self):
return "驴的名字:{0}".format(self.name)
def run(self):
print("驴动起来")
def roll(self):
print("驴打滚")
class Mule(Hourse, Donkey):
def __init__(self, name, age):
super().__init__(name)
self.age = age
def show_info(self): # 重新父类方法
return "骡子:{0},{1}岁。".format(self.name, self.age)
m = Mule('骡子', 3)
m.run() # 继承父类Horse方法
m.roll() # 继承父类Donkey
print(m.show_info()) # 子类Mule自己方法
5.多态性
多态性也是面向对象重要的基本特性之一。“多态”指对象可以表现出多种形态。
例如,猫、狗、鸭子都属于动物,它们有“叫”和“动”等行为,但是叫的方式不同,动的方式也不同。
a.继承与多态
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/30 13:25
@File: duotaii.py
@IDE: PyCharm
"""
class Animal:
def speak(self):
print("动物叫声,但是不知道是哪种动物!")
class Cat(Animal):
def speak(self):
print('小猫:喵喵喵。。')
class Dog(Animal):
def speak(self):
print('小狗:汪汪汪。。')
an1 = Cat()
an2 = Dog()
an1.speak()
an2.speak()
# -*- coding: utf-8 -*-
"""
@Time: 2024/5/30 13:25
@File: duotaii-l.py
@IDE: PyCharm
"""
#接收的obj对象具有speak()方法
def start(obj):
obj.speak()
class Animal:
def speak(self):
print("动物叫声,但是不知道是哪种动物!")
class Cat(Animal):
def speak(self):
print('小猫:喵喵喵。。')
class Dog(Animal):
def speak(self):
print('小狗:汪汪汪。。')
start(Cat())
start(Dog())