面向对象编程(Object-oriented Programming,OOP) 是一种编程范式(编程思想)
一、类和对象
概念
对象:现实世界中每一个事物都是一个对象,是一个具体的概念。
类:拥有相同的属相和功能的事物成为一个类,是一个抽象的概念。
拥有相同属性和功能的具体事物则成为这个类的实例对象。
例如:
狗的属性是有尾巴,有毛,四条腿等,功能是能汪汪叫,能吃骨头,能咬人等。能有这些
属性和功能的事物我们就认为属于狗类。而金毛是这个类的具体实例对象。
电脑的属性是有CPU,存储器,操作系统等,功能就是能安装APP,能连网等。能有这些属性
和功能的事物我们就认为属于电脑类。而联想电脑是这个类的具体实例对象。
汽车的属性是有四个轮子,一个地盘,一个方向盘等,功能是能行驶,能加速,能刹车
等。能有这些属性和功能的事物我们就认为属于汽车类。而小米汽车是这个类的具体实例对象。

具体代码举例:
# 狗类
class Dog:
# 类的属性
legs_num=4
has_hair=True
has_tail=True
# 实例方法(第一个参数是self实例对象而不是cls类对象,故为实例方法)
def bark(self):
print("狗会汪汪叫")
def bite(self):
print("狗会咬坏人")
def fetch(self):
print("狗会捡球")
#鸟类
class Bird:
# 类的属性
legs_num = 2
has_hair = True
has_tail = False
# 实例方法
def fly(self):
print("鸟会飞")
def eat_worms(self):
print("鸟吃虫子")
def nest(self):
print("鸟会筑巢")
狗类实例化:
# 狗类的实例化
Jinmao=Dog()
# 调用类的属性和功能
print(Jinmao.legs_num)
Jinmao.bite()
运行结果:
鸟类实例化:
# 鸟类的实例化
Maque=Bird()
# 调用类的属性和功能
print(Maque.legs_num)
Maque.nest()
运行结果:

语法

类名:推荐首字母大写,多个单词则采用大驼峰命名法(ExampleName),不能以数字开头
同一个类的不同具体实例对象,存储位置不同,在不同的实例空间;同一个类的不同具体实例对象调用共同的属性和方法,存储位置相同,都在类空间。
二、实例对象
实例对象的实例属性
类属性在所有实例化对象中作为公用资源存在的,实例属性是属于类的每个实例对象的特定属性,实例属性是在创建对象时赋予的,每个对象可以具有不同的实例属性值。
Jinmao=Dog()
Bixiong=Dog()
# 实例属性
Jinmao.name='金毛'
Bixiong.name='比熊'
注意:会报错,因为查找顺序按照[实例空间,类空间],Jinmao.bark()会被认为是1000(),int类型的值并不能作方法名,也没有该方法
Jinmao.bark=1000 # 存储在实例空间
Jinmao.bark() # 存储在类空间
如果通过实例对象.属性=属性值,该属性与属性值会存放在实例空间内,即使该属性是类属性,调用时,优先返回实例空间的值
实例对象的实例方法
何时使用哪种方法?
-
若方法需要读写实例属性(如
self.name),第一个形参是self实例对象,用实例方法。 -
若方法需要修改类属性(如全局配置)或提供多种构造方式(工厂),第一个形参是cls类对象用类方法。
-
如果方法既不需要实例也不需要类属性,考虑使用静态方法(
@staticmethod)。
# 狗类
class Dog:
# 类的属性
legs_num=4
has_hair=True
has_tail=True
# 实例方法
def bark(self):
print(f"{self.name}会汪汪叫") # 调用了实例属性
def bite(self,person):
print(f"狗会咬{person}")
Jinmao=Dog()
# 实例属性
Jinmao.name='金毛'
Jinmao.bite("坏人") # 传参时没有传self,self默认为当前所调用实例方法的实例对象(即Jinmao)
Jinmao.bark()
输出结果:

三、构造方法
上述代码,对象的属性是通过直接赋值给对象的实例属性来实现的,但是一般是使用构造方法来初始化对象的属性。减少代码冗余,提高可维护性
# 狗类
class Dog:
def __init__(self,name,breed,color,age):
self.name=name
self.breed=breed
self.color=color
self.age=age
def show_infos(self):
print(f"名字:{self.name},品种:{self.breed},颜色:{self.color},年龄:{self.age}")
Jinmao=Dog("小鸡毛","金毛","黄色","两岁")
Jinmao.show_infos()
运行结果:
四、类对象
类对象和类属性
# 这里的Car就是一个类变量
class Car (object):
total_cars=0
def __init__(self,make,model):
self.make=make
self.model=model
Car.total_cars+=1 # 类对象.类属性,只有这样才能改变类属性的值
# 实例方法
def accelerate(self):
print(f"一辆{self.make}的{self.model}正在加速")
car1=Car("Toyota","Camry")
car2=Car("Honda","Accord")
print(Car.total_cars)
那类对象可不可以调用实例方法呢?运行以下代码:
Car.accelerate()
运行结果,如下:

缺少参数,修改代代码,如下:
car1=Car("Toyota","Camry")
Car.accelerate(car1)
运行结果,如下:

故类对象不能像实例对象一样,不能通过self传递,必须手动添加参数,但通常不会使用类对象调用实例方法
类方法
用于读写类属性,使用装饰器@classmethod
# 类方法
@classmethod
def show_total_cars(cls):
print(f"当前的total_cars:{Car.total_cars}")
# 调用类方法
Car.show_total_cars()
也可以改写成以下形式,在类方法中用cls代替Car类对象,代码可维护性变高
同理,在实例方法中用self代替实例对象
# 类方法
@classmethod
def show_total_cars(cls):
print(f"当前的total_cars:{cls.total_cars}")
# 调用类方法
Car.show_total_cars()
构造方法中的类对象可以使用,self.__class__代替
def __init__(self,make,model):
self.make=make
self.model=model
self.__class__.total_cars+=1 # 类对象.类属性,只有这样才能改变类属性的值
完整代码如下:
# 这里的Car就是一个类变量
class Car (object):
total_cars=0
def __init__(self,make,model):
self.make=make
self.model=model
self.__class__.total_cars+=1 # 类对象.类属性,只有这样才能改变类属性的值
# 实例方法
def accelerate(self):
print(f"一辆{self.make}的{self.model}正在加速")
# 类方法
@classmethod
def show_total_cars(cls):
print(f"当前的total_cars:{cls.total_cars}")
car1=Car("Toyota","Camry")
car2=Car("Honda","Accord")
print(Car.total_cars)
Car.accelerate(car1)
五、静态方法
定义:使用装饰器@staticemethod。参数随意,没有self和cls参数,方法体中不能使用类或实例的任何属性和方法
调用:类对象或实例对象都可以调用
class Cal():
@staticmethod
def add(x,y):
return x+y
@staticmethod
def mul(x,y):
return x*y
cal=Cal()
print(cal.add(3,5))
# or
print(Cal.add(3,5))
运行结果如下:

930

被折叠的 条评论
为什么被折叠?



