1 面向对象的基本概念
1.1 对象和类
对象既能表示结构化的数据,也能表示抽象的事件。
类是具有相同属性和操作行为的一组对象的集合。类和对象的关系是抽象和具体的关系,类的作用是定义对象,类给出了属于该类的全部对象的抽象定义,而对象是类的具体化,是符合这种定义的一个类的实例。
总的来说,类是对对象的抽象,对象是类的具体实例。
1.2 封装
封装是针对对象来说的,指将对象的属性和行为(数据和操作)包裹起来形成一个封装体。该封装体内包含对象的属性和行为,对象的属性由若干个数据组成,而对象的行为则由若干个操作组成,这些操作通过函数实现,也称为方法。封装体和外界的联系是通过接口(函数)进行的。
1.3 继承
继承是针对类来说的继承提供了一种创建新类的一种方法,表现了特殊类和一般类的关系。特殊类具有一般类的全部属性和行为,并且还具有自己的特殊属性和行为。通常称一般类为基类(父类),而将特殊类称为派生类(子类)。
2 类的定义和对象的创建
2.1 类的定义
格式:
class<类名>:
<属性定义>
<方法定义>
class Person:
# 这里是类的属性
number = 0
# 构造函数,相当于说明对象里都有什么属性
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
Person.number += 1
# 类的操作
def playPerson(self):
print('Name:', self.name, 'Gender:', self.gender, 'Age:', self.age)
def playNumber(self):
print('Total person:', Person.number)
2.2 对象的创建
<对象名> = <类名>(属性值,属性值…)
stu1 = Person('Liming', 'M', 19)
stu2 = Person('Zhang', 'F', 20)
class Person:
# 这里是类的属性
number = 0
# 构造函数,相当于说明对象里都有什么属性
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
Person.number += 1
# 类的操作
def playPerson(self):
print('Name:', self.name, 'Gender:', self.gender, 'Age:', self.age)
def playNumber(self):
print('Total person:', Person.number)
stu1 = Person('Liming', 'M', 19)
stu2 = Person('Zhang', 'F', 20)
stu1.score = 90
stu2.score = 85
stu1.playPerson()
print('Total person:', Person.number)
print(stu1.score,stu2.score)
2.3 属性的修改
直接操作:
对象属性的添加:直接添加,如果原来没有这个属性那就是添加,如果原来有这个属性那就是修改
stu1.score = 90
stu2.score = 85
对象属性的删除:格式:del <对象名>.<属性名>
del stu1.score
通过函数操作:
访问对象的属性:
print(getattr(stu1,'score'))
检查是否存在一个属性,结果为逻辑值:
hasattr(stu1,'score')
修改或者创建对象的属性:
setattr(stu1,'score',86)
删除对象的属性:
delattr(stu1,'score')
3 属性和方法
3.1 类属性和对象属性
class Person:
# 这里是类的属性
number = 0
# 构造函数,里面都是对象属性
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
Person.number += 1
# 类的操作
def playPerson(self):
print('Name:', self.name, 'Gender:', self.gender, 'Age:', self.age)
def playNumber(self):
print('Total person:', Person.number)
stu1 = Person('Liming', 'M', 19)
stu2 = Person('Zhang', 'F', 20)
print(Person.number)#输出类的属性
print(Person.name)#很明显这是错误的,不能通过类名访问对象的属性
3.2 公有属性和私有属性
Python的公有属性和私有属性通过属性命名方式区分,如果属性名以两个下划线开头,但不结尾,则说明是私有属性,否则是公有属性。要注意的是:类和对象都有公有属性和私有属性。私有属性的访问方式与上文提到的公有属性不同:
格式:
<类(对象)名>.<_类名__私有属性名>
class Car:
price = 1500 #公有类属性
__cost = 1000 #私有类属性
def __init__(self,brand,serial):
self.brand=brand #公有对象属性
self.__serial=serial #私有对象属性
car1 = Car('丰田','普拉多')
print(Car.price) #访问类的公有属性
print(Car._Car__cost) #访问类的私有属性
print(car1.brand) #访问对象的公有属性
print(car1._Car__serial)#访问对象的私有属性
3.3 属于对象的方法
Python的方法可以分为公有方法和私有方法、类方法以及静态方法。其中对象的方法包括公有方法和私有方法。公有方法的定义不需要特别说明,而私有方法定义时,函数名要以双下划线开头,但不结尾。
公有方法通过对象名可以直接调用,但是私有方法不可以通过对象名直接调用。
调用私有方法的方式有三种:
- 通过对象的公有方法调用私有方法
- 通过对象名调用私有方法
- 通过类名调用私有方法
class Methods:
def publicMethod1(self): #定义公有方法
print('公有方法publicMethod!')
def __privateMethod(self):#定义私有方法
print('私有方法privateMethod!')
def publicMethod2(self): #定义公有方法
self.__privateMethod()
m=Methods()
m.publicMethod1() #通过对象调用公有方法
Methods.publicMethod1(m) #通过类名调用公有方法
m.publicMethod2() #通过对象的公有方法调用私有方法
m._Methods__privateMethod() #通过对象调用私有方法
Methods._Methods__privateMethod(m) #通过类名调用私有方法
要注意的是,通过类名无论是调用公有类方法还是私有类方法,都必须传入一个对象名
3.4 属于类的方法
3.4.1 类方法
类方法属于类,可以通过Python的修饰器@classmethod定义,也可以通过内置函数classmethod()的方式将一个普通的方法转换为类方法。类方法可以通过类名或对象名访问。
class Methods:
@classmethod
def publicClassMethod(cls): #定义公有类方法
print('公有类方法publicMethod!')
@classmethod
def __privateClassMethod(self):#定义私有方法
print('私有类方法privateMethod!')
def publicMethod(self): #定义普通公有方法
print('普通私有方法privateMethod1')
def __privateMethod(self):#定义普通私有方法
print('私有类方法privateMethod!')
publicMethodToClassMethod = classmethod(publicMethod) #转换为类方法
privateMethhodToClassMethod = classmethod(__privateMethod) #转换为类方法
m=Methods()
m.publicClassMethod() #通过对象调用公有类方法
Methods.publicClassMethod() #通过类名调用公有方法
m._Methods__privateClassMethod() #通过对象调用私有类方法
Methods._Methods__privateClassMethod() #通过类名调用私有类方法
m.publicMethodToClassMethod()
Methods.publicMethodToClassMethod()
m.privateMethhodToClassMethod()
Methods.privateMethhodToClassMethod()
定义类方法时,一般用cls作为类方法的第一个参数的名称,在调用类方法时,不需要为该参数传递任何值。
3.4.2 静态方法
静态方法也属于类,可以通过Python的修饰器@staticmethod定义,也同样可以通过使用内置函数staticmethod()将一个普通的方法转换为静态的方法。
class Methods:
@staticmethod
def publicStaticMethod(): #定义公有静态方法
print('公有静态方法publicStaticMethod!')
@staticmethod
def __privateStaticMethod():#定义私有静态方法
print('私有静态方法privateStaticMethod!')
def publicMethod(self): #定义普通公有方法
print('普通私有方法privateMethod1')
def __privateMethod(self):#定义普通私有方法
print('私有类方法privateMethod!')
publicMethodToStaticMethod = staticmethod(publicMethod) #转换为静态方法
privateMethhodToStaticMethod = staticmethod(__privateMethod) #转换为静态方法
m=Methods()
m.publicStaticMethod() #通过对象调用公有静态方法
Methods.publicStaticMethod() #通过类名调用公有静态方法
m._Methods__privateStaticMethod() #通过对象调用私有静态方法
Methods._Methods__privateStaticMethod() #通过类名调用私有静态方法
m.publicMethodToStaticMethod(m)
Methods.publicMethodToStaticMethod(m)
m.privateMethhodToStaticMethod(m)
Methods.privateMethhodToStaticMethod(m)
要注意的是:定义静态方法的时候,不需要传入self参数或cls参数。通过普通函数转化的静态函数调用的时候必须传入一个对象名
3.4.3 内置函数
以双下划线开头并且以双下划线结尾的函数,经常使用的就是__init__()函数和__del__函数。前一个常被称为构造函数,后一个经常被称为析构函数。一般情况下,构造函数需要用户自己定义,而析构函数不需要自己定义。
4 继承和多态
4.1 派生类的定义
格式:
class <派生类名>(<基类名>):
def __init__(self[,<参数>]):
<基类类名>.__init__(self[,<参数>])
<新增属性定义>
class Person:
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
def display(self):
print('Name:', self.name, 'Gender:', self.gender, 'Age:', self.age)
class Student(Person):
def __init__(self, num, major, name, gender, age): # 派生类构造函数
Person.__init__(self, name, gender, age)
self.num = num
self.major = major
def dispalyStudent(self):
print('Number:', self.num, 'Major:', self.major)
Person.display(self)
stu1 = Student('201602784', '中文', 'Liming', 'M', 19)
stu2 = Student('201610050', 'CS', 'Zhang', 'F', 20)
stu1.displayStudent()
stu2.displayStudent()
4.2 多态性
4.2.1 方法的重载
方法的重载,顾名思义就是在派生类中对基类中定义的方法进行重新定义。
class Animal(): #基类
def display(self):
print("动物")
class Dog(Animal):
def display(self):
print("狗")
dog1 = Dog()
dog1.display()
4.2.2 运算符的重载
还记得我们上文说的Python的内置方法吗?Python中还有大量内置的特殊方法,运算符重载便是通过重写这些内置方法实现的。这些特殊方法都是以双下划线开头和结尾的,Python通过这种特殊的命名方式拦截操作符,以实现重载。
class Number:
def __init__(self,a,b):
self.a = a
self.b = b
def __add__(self,another): #重载+
return Number(self.a + another.a, self.b + another.b)
def __sub__(self,another): #重载-
return Number(self.a - another.a, self.b - another.b)
n1 = Number(10,20)
n2 = Number(100,200)
m = n1 + n2
p = n2 - n1
print(m.a,m.b)
print(p.a,p.b)
可以看到,重载以后的加法运算符就可以用于两个对象相加,得到一个新的对象,所以要注意,对象经过运算符运算之后自然生成一个新的对象。
转载:https://blog.csdn.net/qq_44384577/article/details/106529483